mirror of
https://github.com/golang/go
synced 2024-11-23 09:00:04 -07:00
abe384f68a
Phrases like "returns whether or not the image is opaque" could be describing what the function does (it always returns, regardless of the opacity) or what it returns (a boolean indicating the opacity). Even when the "or not" is missing, the phrasing is bizarre. Go with "reports whether", which is still clunky but at least makes it clear we're talking about the return value. These were edited by hand. A few were cleaned up in other ways. R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/11699043
114 lines
2.4 KiB
Go
114 lines
2.4 KiB
Go
// 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)
|
|
}
|
|
}
|