board.gno
1.29 Kb · 54 lines
1package connect4
2
3const (
4 cols = 7
5 rows = 6
6)
7
8// board is indexed [column][row]; row 0 is the bottom. 0 = empty, 1/2 = player.
9type board [cols][rows]byte
10
11// drop places piece p in column c (0-based) and returns its row, or -1 if the column is full.
12func (b *board) drop(c int, p byte) int {
13 for r := 0; r < rows; r++ {
14 if b[c][r] == 0 {
15 b[c][r] = p
16 return r
17 }
18 }
19 return -1
20}
21
22// wins reports whether the piece at (c, r) is part of four in a row.
23func (b *board) wins(c, r int) bool { return b.winLine(c, r) != nil }
24
25// winLine returns the cells of the four-or-more line through (c, r), in order
26// along the line, or nil if the piece there completes none.
27func (b *board) winLine(c, r int) [][2]int {
28 p := b[c][r]
29 for _, d := range [4][2]int{{1, 0}, {0, 1}, {1, 1}, {1, -1}} {
30 back := b.count(c, r, -d[0], -d[1], p)
31 n := 1 + back + b.count(c, r, d[0], d[1], p)
32 if n >= 4 {
33 line := make([][2]int, n)
34 for i := range line {
35 k := i - back
36 line[i] = [2]int{c + k*d[0], r + k*d[1]}
37 }
38 return line
39 }
40 }
41 return nil
42}
43
44// count returns how many consecutive p pieces follow (c, r) in direction (dc, dr).
45func (b *board) count(c, r, dc, dr int, p byte) int {
46 n := 0
47 for {
48 c, r = c+dc, r+dr
49 if c < 0 || c >= cols || r < 0 || r >= rows || b[c][r] != p {
50 return n
51 }
52 n++
53 }
54}