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