Difference between revisions of "User:Ziggy/golang1"
(Created page with "<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...") |
|||
Line 1: | Line 1: | ||
+ | = 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] | ||
+ | |||
<source lang="go"> | <source lang="go"> | ||
// An implementation of Conway's Game of Life. | // An implementation of Conway's Game of Life. | ||
Line 122: | Line 128: | ||
func main() { | func main() { | ||
l := NewLife(80, 10) | l := NewLife(80, 10) | ||
− | for i := 0; i < | + | for i := 0; i < 3000; i++ { |
l.Step() | l.Step() | ||
fmt.Print("\x0c", l) // Clear screen and print field. | fmt.Print("\x0c", l) // Clear screen and print field. |
Revision as of 19:40, 22 May 2017
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 [1]
<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>