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