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
// An implementation of Conway's Game of Life.
package main
 
import (
   "bytes"
   "fmt"
   "math/rand"
   "time"
)
 
// Field represents a two-dimensional field of cells.
type Field struct {
   s    [][]bool
   w, h int
}
 
// NewField returns an empty field of the specified width and height.
func NewField(w, h int) *Field {
   s := make([][]bool, h)
   for i := range s {
       s[i] = make([]bool, w)
   }
   return &Field{s: s, w: w, h: h}
}
 
// Set sets the state of the specified cell to the given value.
func (f *Field) Set(x, y int, b bool) {
   f.s[y][x] = b
}
 
// Alive reports whether the specified cell is alive.
// If the x or y coordinates are outside the field boundaries they are wrapped
// toroidally. For instance, an x value of -1 is treated as width-1.
func (f *Field) Alive(x, y int) bool {
   x += f.w
   x %= f.w
   y += f.h
   y %= f.h
   return f.s[y][x]
}
 
// Next returns the state of the specified cell at the next time step.
func (f *Field) Next(x, y int) bool {
   // Count the adjacent cells that are alive.
   alive := 0
   for i := -1; i <= 1; i++ {
       for j := -1; j <= 1; j++ {
           if (j != 0 || i != 0) && f.Alive(x+i, y+j) {
               alive++
           }
       }
   }
   // Return next state according to the game rules:
   //   exactly 3 neighbors: on,
   //   exactly 2 neighbors: maintain current state,
   //   otherwise: off.
   return alive == 3 || alive == 2 && f.Alive(x, y)
}
 
// Life stores the state of a round of Conway's Game of Life.
type Life struct {
   a, b *Field
   w, h int
}
 
// NewLife returns a new Life game state with a random initial state.
func NewLife(w, h int) *Life {
   a := NewField(w, h)
   for i := 0; i < (w * h / 4); i++ {
       a.Set(rand.Intn(w), rand.Intn(h), true)
   }
   return &Life{
       a: a, b: NewField(w, h),
       w: w, h: h,
   }
}
 
// Step advances the game by one instant, recomputing and updating all cells.
func (l *Life) Step() {
   // Update the state of the next field (b) from the current field (a).
   for y := 0; y < l.h; y++ {
       for x := 0; x < l.w; x++ {
           l.b.Set(x, y, l.a.Next(x, y))
       }
   }
   // Swap fields a and b.
   l.a, l.b = l.b, l.a
}
 
// String returns the game board as a string.
func (l *Life) String() string {
   var buf bytes.Buffer
   for y := 0; y < l.h; y++ {
       for x := 0; x < l.w; x++ {
           b := byte(' ')
           if l.a.Alive(x, y) {
               b = '*'
           }
           buf.WriteByte(b)
       }
       buf.WriteByte('\n')
   }
   return buf.String()
}
 
func main() {
   l := NewLife(40, 15)
   for i := 0; i < 300; i++ {
       l.Step()
       fmt.Print("\x0c", l) // Clear screen and print field.
       time.Sleep(time.Second / 30)
   }
}