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