Skip to content

Instantly share code, notes, and snippets.

@FSX
Last active December 20, 2015 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FSX/6088771 to your computer and use it in GitHub Desktop.
Save FSX/6088771 to your computer and use it in GitHub Desktop.
Game of life in Go.
// I peeked at http://rosettacode.org/wiki/Conway's_Game_of_Life#Go
package main
import (
"fmt"
"github.com/nsf/termbox-go"
// "math/rand"
"strings"
"time"
)
var GLIDER_GUN []string = strings.Split(strings.TrimSpace(`
-------------------------1-----------
-----------------------1-1-----------
------------11-------11------------11
-----------1---1-----11------------11
11--------1------1---11--------------
11--------1---1--11----1-1-----------
----------1------1-------1-----------
-----------1---1---------------------
------------11-----------------------
-------------------------------------
`), "\n")
var PATTERN_1 []string = strings.Split(strings.TrimSpace(`
-----1-
---1-11
---1-1-
---1---
--1----
1-1----
`), "\n")
var PATTERN_2 []string = strings.Split(strings.TrimSpace(`
11111111-11111---111------1111111-11111
`), "\n")
var PATTERN_3 []string = strings.Split(strings.TrimSpace(`
111-1
1----
---11
-11-1
1-1-1
`), "\n")
type Life struct {
width, height int
current [][]bool
next [][]bool
status string
living, dead int
generation int
}
func NewLife(width, height int) *Life {
current := make([][]bool, height)
for i := range current {
current[i] = make([]bool, width)
}
// for i := 0; i < (width * height / 2); i++ {
// current[rand.Intn(height)][rand.Intn(height)] = true
// }
for y, line := range PATTERN_3 {
for x, r := range line {
if r == '1' {
current[y+20][x+50] = true
}
}
}
next := make([][]bool, height)
for i := range next {
next[i] = make([]bool, width)
}
return &Life{width, height, current, next,
"Total: %d; Living: %d; Dead: %d; Generation: %d;",
0, 0, 0,
}
}
func (l *Life) NextGeneration(x, y int) bool {
on := 0
for i := -1; i <= 1; i++ {
for j := -1; j <= 1; j++ {
if l.CurrentState(x+i, y+j) && !(j == 0 && i == 0) {
on++
}
}
}
return on == 3 || on == 2 && l.CurrentState(x, y)
}
func (l *Life) CurrentState(x, y int) bool {
for y < 0 {
y += l.height
}
for x < 0 {
x += l.width
}
return l.current[y%l.height][x%l.width]
}
func (l *Life) Step() {
l.generation++
l.living, l.dead = 0, 0
for y := 0; y < l.height; y++ {
for x := 0; x < l.width; x++ {
status := l.NextGeneration(x, y)
l.next[y][x] = status
if status == true {
l.living++
} else {
l.dead++
}
}
}
l.current, l.next = l.next, l.current
}
func (l *Life) Draw() {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
text := fmt.Sprintf(l.status, (l.living + l.dead), l.living, l.dead, l.generation)
for i, r := range text {
termbox.SetCell(i, l.height, r, termbox.ColorDefault, termbox.ColorDefault)
}
for y, row := range l.current {
for x, alive := range row {
if alive {
termbox.SetCell(x, y, '*', termbox.ColorBlack, termbox.ColorWhite)
} else {
termbox.SetCell(x, y, ' ', termbox.ColorWhite, termbox.ColorWhite)
}
}
}
termbox.Flush()
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
event_queue := make(chan termbox.Event)
go func() {
for {
event_queue <- termbox.PollEvent()
}
}()
l := NewLife(200, 60)
l.Draw()
loop:
for {
select {
case ev := <-event_queue:
if ev.Type == termbox.EventKey && ev.Key == termbox.KeyEsc {
break loop
}
default:
l.Step()
l.Draw()
time.Sleep(100 * time.Millisecond)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment