Difference between revisions of "User:Ziggy/golang1"
Line 3: | Line 3: | ||
Updated to display wide and stop when game ends rather than a fixed number of cycles | Updated to display wide and stop when game ends rather than a fixed number of cycles | ||
− | Try on [https://play.golang.org/p/P-Dk0NH_vf] | + | Try on [https://play.golang.org/p/P-Dk0NH_vf https://play.golang.org/p/P-Dk0NH_vf]<br> |
+ | (copy the code below and paste replacing the original code in the page from the link above) | ||
<source lang="go"> | <source lang="go"> |
Latest revision as of 19:42, 22 May 2017
[edit] Go Playground - An implementation of Conway's Game of Life
Updated to display wide and stop when game ends rather than a fixed number of cycles
Try on https://play.golang.org/p/P-Dk0NH_vf
(copy the code below and paste replacing the original code in the page from the link above)
<source lang="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} }
// Check if two fields are the same. func (f *Field) Same(f2 *Field) bool { if f.w != f2.w || f.h != f2.h { return false } for y := range f.s { for x := range f.s[y] { if f.s[y][x] != f2.s[y][x] { return false } } } return true }
// 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, c *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 / 5); i++ { a.Set(rand.Intn(w), rand.Intn(h), true) } return &Life{ a: a, b: NewField(w, h), c: 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)) } } // Rotate fields a, b and c. l.a, l.b, l.c = l.b, l.c, 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 = 'o' } buf.WriteByte(b) } buf.WriteByte('\n') } return buf.String() }
func main() { l := NewLife(80, 10) for i := 0; i < 3000; i++ { l.Step() fmt.Print("\x0c", l) // Clear screen and print field. time.Sleep(time.Second / 30) if i > 1 && (l.a.Same(l.b) || l.a.Same(l.c)) { break; } } } </source>