]> Cypherpunks.ru repositories - gostls13.git/blob - test/solitaire.go
test: use testlib in a few more cases.
[gostls13.git] / test / solitaire.go
1 // build
2
3 // don't run it - produces too much output
4
5 // Copyright 2010 The Go Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style
7 // license that can be found in the LICENSE file.
8
9 // This program solves the (English) peg solitaire board game.
10 // See also: http://en.wikipedia.org/wiki/Peg_solitaire
11
12 package main
13
14 const N = 11 + 1 // length of a board row (+1 for newline)
15
16 // The board must be surrounded by 2 illegal fields in each direction
17 // so that move() doesn't need to check the board boundaries. Periods
18 // represent illegal fields, ● are pegs, and ○ are holes.
19 var board = []rune(
20         `...........
21 ...........
22 ....●●●....
23 ....●●●....
24 ..●●●●●●●..
25 ..●●●○●●●..
26 ..●●●●●●●..
27 ....●●●....
28 ....●●●....
29 ...........
30 ...........
31 `)
32
33 // center is the position of the center hole if there is a single one;
34 // otherwise it is -1.
35 var center int
36
37 func init() {
38         n := 0
39         for pos, field := range board {
40                 if field == '○' {
41                         center = pos
42                         n++
43                 }
44         }
45         if n != 1 {
46                 center = -1 // no single hole
47         }
48 }
49
50 var moves int // number of times move is called
51
52 // move tests if there is a peg at position pos that can jump over another peg
53 // in direction dir. If the move is valid, it is executed and move returns true.
54 // Otherwise, move returns false.
55 func move(pos, dir int) bool {
56         moves++
57         if board[pos] == '●' && board[pos+dir] == '●' && board[pos+2*dir] == '○' {
58                 board[pos] = '○'
59                 board[pos+dir] = '○'
60                 board[pos+2*dir] = '●'
61                 return true
62         }
63         return false
64 }
65
66 // unmove reverts a previously executed valid move.
67 func unmove(pos, dir int) {
68         board[pos] = '●'
69         board[pos+dir] = '●'
70         board[pos+2*dir] = '○'
71 }
72
73 // solve tries to find a sequence of moves such that there is only one peg left
74 // at the end; if center is >= 0, that last peg must be in the center position.
75 // If a solution is found, solve prints the board after each move in a backward
76 // fashion (i.e., the last board position is printed first, all the way back to
77 // the starting board position).
78 func solve() bool {
79         var last, n int
80         for pos, field := range board {
81                 // try each board position
82                 if field == '●' {
83                         // found a peg
84                         for _, dir := range [...]int{-1, -N, +1, +N} {
85                                 // try each direction
86                                 if move(pos, dir) {
87                                         // a valid move was found and executed,
88                                         // see if this new board has a solution
89                                         if solve() {
90                                                 unmove(pos, dir)
91                                                 println(string(board))
92                                                 return true
93                                         }
94                                         unmove(pos, dir)
95                                 }
96                         }
97                         last = pos
98                         n++
99                 }
100         }
101         // tried each possible move
102         if n == 1 && (center < 0 || last == center) {
103                 // there's only one peg left
104                 println(string(board))
105                 return true
106         }
107         // no solution found for this board
108         return false
109 }
110
111 func main() {
112         if !solve() {
113                 println("no solution found")
114         }
115         println(moves, "moves tried")
116 }