-
Notifications
You must be signed in to change notification settings - Fork 0
/
game.go
112 lines (95 loc) · 1.74 KB
/
game.go
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
package main
import (
"fmt"
"math/rand"
)
var ShowAnalysis bool
type game struct {
turn Player
board Board
}
func NewGame() *game {
return &game{turn: X}
}
func (g *game) Turn() Player {
return g.turn
}
func (g *game) Move(n int) (ok bool) {
if n < 0 || n > 8 || g.board[n] != None || g.Over() {
return false
}
g.board[n], g.turn = g.turn, g.turn.Other()
return true
}
func (g *game) unMove(n int) {
g.board[n], g.turn = None, g.turn.Other()
}
func (g *game) MoveAI(depth int) (ok bool) {
w, r, l := g.analyze(depth)
rand := func(m []int) int {
return m[rand.Intn(len(m))]
}
var m int
switch {
case len(w) > 0:
m = rand(w)
case len(r) > 0:
m = rand(r)
case len(l) > 0:
m = rand(l)
default:
return false
}
g.Move(m)
return true
}
func (g *game) analyze(depth int) (wins, rest, losses []int) {
if g.Over() {
return nil, nil, nil
}
moves := g.board.Moves()
if depth == 0 {
return nil, moves, nil
}
for _, m := range moves {
g.Move(m)
switch {
case g.board.Won():
wins = append(wins, m)
case g.board.Full():
rest = append(rest, m)
default:
w, r, l := g.analyze(depth - 1) // enemy
switch {
case len(w) > 0:
losses = append(losses, m)
case len(r) > 0:
rest = append(rest, m)
case len(l) > 0:
wins = append(wins, m)
}
}
g.unMove(m)
}
return
}
func (g *game) Over() (gameOver bool) {
return g.board.Full() || g.board.Won()
}
func (g *game) Winner() Player {
if !g.board.Won() {
return None
}
return g.turn.Other()
}
func (g *game) String() string {
s := ""
s += g.board.String()
if ShowAnalysis {
w, d, l := g.analyze(-1)
s += fmt.Sprintf(" %s%v%s", green, w, clrRst)
s += fmt.Sprintf(" %v", d)
s += fmt.Sprintf(" %s%v%s\n\n", red, l, clrRst)
}
return s
}