Difference between revisions of "User:Ziggy/golang1"

From The Crowdsourced Resource-Based Economy Knowledgebase
Jump to: navigation, search
(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...")

Revision as of 19:36, 22 May 2017

// 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 < 300; 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;
		}
	}
}
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox
Share