github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/test/solitaire.go (about) 1 // build 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 // Test general operation by solving a peg solitaire game. 8 // A version of this is in the Go playground. 9 // Don't run it - produces too much output. 10 11 // This program solves the (English) peg solitaire board game. 12 // See also: http://en.wikipedia.org/wiki/Peg_solitaire 13 14 package main 15 16 const N = 11 + 1 // length of a board row (+1 for newline) 17 18 // The board must be surrounded by 2 illegal fields in each direction 19 // so that move() doesn't need to check the board boundaries. Periods 20 // represent illegal fields, ● are pegs, and ○ are holes. 21 var board = []rune( 22 `........... 23 ........... 24 ....●●●.... 25 ....●●●.... 26 ..●●●●●●●.. 27 ..●●●○●●●.. 28 ..●●●●●●●.. 29 ....●●●.... 30 ....●●●.... 31 ........... 32 ........... 33 `) 34 35 // center is the position of the center hole if there is a single one; 36 // otherwise it is -1. 37 var center int 38 39 func init() { 40 n := 0 41 for pos, field := range board { 42 if field == '○' { 43 center = pos 44 n++ 45 } 46 } 47 if n != 1 { 48 center = -1 // no single hole 49 } 50 } 51 52 var moves int // number of times move is called 53 54 // move tests if there is a peg at position pos that can jump over another peg 55 // in direction dir. If the move is valid, it is executed and move returns true. 56 // Otherwise, move returns false. 57 func move(pos, dir int) bool { 58 moves++ 59 if board[pos] == '●' && board[pos+dir] == '●' && board[pos+2*dir] == '○' { 60 board[pos] = '○' 61 board[pos+dir] = '○' 62 board[pos+2*dir] = '●' 63 return true 64 } 65 return false 66 } 67 68 // unmove reverts a previously executed valid move. 69 func unmove(pos, dir int) { 70 board[pos] = '●' 71 board[pos+dir] = '●' 72 board[pos+2*dir] = '○' 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 func main() { 114 if !solve() { 115 println("no solution found") 116 } 117 println(moves, "moves tried") 118 }