|  | // 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) | 
|  | } | 
|  | } |