214 lines
3.1 KiB
Go
214 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/jpeg"
|
|
"math/rand"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// Grid size
|
|
//size = 150
|
|
size = 30
|
|
// Image zoom value
|
|
zoom = 8
|
|
// Generations per second
|
|
gps = 2
|
|
)
|
|
|
|
type Grid struct {
|
|
G [size][size]bool
|
|
}
|
|
|
|
func (g *Grid) Blinker() {
|
|
g.G[14][13] = true
|
|
g.G[14][14] = true
|
|
g.G[14][15] = true
|
|
}
|
|
|
|
func (g *Grid) Bipole() {
|
|
g.G[14][14] = true
|
|
g.G[14][15] = true
|
|
g.G[15][14] = true
|
|
g.G[16][17] = true
|
|
g.G[17][16] = true
|
|
g.G[17][17] = true
|
|
}
|
|
|
|
func (g *Grid) Tripole() {
|
|
g.G[14][14] = true
|
|
g.G[14][15] = true
|
|
g.G[15][14] = true
|
|
g.G[16][15] = true
|
|
g.G[16][17] = true
|
|
g.G[17][18] = true
|
|
g.G[18][17] = true
|
|
g.G[18][18] = true
|
|
}
|
|
|
|
func (g *Grid) Pulsator() {
|
|
for i := 10; i < 20; i++ {
|
|
g.G[i][14] = true
|
|
}
|
|
}
|
|
|
|
func (g *Grid) Glider() {
|
|
g.G[1][0] = true
|
|
g.G[2][1] = true
|
|
g.G[2][2] = true
|
|
g.G[1][2] = true
|
|
g.G[0][2] = true
|
|
}
|
|
|
|
func (g *Grid) Random() {
|
|
rand.Seed(size)
|
|
for i := 0; i < size; i++ {
|
|
for j := 0; j < size; j++ {
|
|
g.G[i][j] = rand.Intn(2) == 1
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
func (g *Grid) Pentomino() {
|
|
g.G[75][74] = true
|
|
g.G[76][74] = true
|
|
g.G[74][75] = true
|
|
g.G[75][75] = true
|
|
g.G[75][76] = true
|
|
}
|
|
*/
|
|
|
|
type GOL struct {
|
|
grid1 *Grid
|
|
grid2 *Grid
|
|
Gen int
|
|
}
|
|
|
|
func NewGOL() (g *GOL) {
|
|
g = &GOL{grid1: new(Grid), grid2: new(Grid)}
|
|
g.grid1.Blinker()
|
|
//g.grid1.Bipole()
|
|
//g.grid1.Tripole()
|
|
//g.grid1.Pulsator()
|
|
//g.grid1.Random()
|
|
//g.grid1.Pentomino()
|
|
return
|
|
}
|
|
|
|
func min(i int) int {
|
|
if i == -1 {
|
|
return i + 1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func max(i int) int {
|
|
if i == size {
|
|
return i - 1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func (g *GOL) check(x, y int) {
|
|
n := 0
|
|
for i := min(x - 1); i <= max(x+1); i++ {
|
|
for j := min(y - 1); j <= max(y+1); j++ {
|
|
if g.grid1.G[i][j] {
|
|
n++
|
|
}
|
|
}
|
|
}
|
|
if g.grid1.G[x][y] {
|
|
n--
|
|
switch n {
|
|
case 0, 1:
|
|
g.grid2.G[x][y] = false
|
|
case 2, 3:
|
|
g.grid2.G[x][y] = true
|
|
default:
|
|
g.grid2.G[x][y] = false
|
|
}
|
|
} else {
|
|
if n == 3 {
|
|
g.grid2.G[x][y] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *GOL) grid() (gr *Grid) {
|
|
gr = new(Grid)
|
|
for i := 0; i < size; i++ {
|
|
gr.G[i] = g.grid1.G[i]
|
|
}
|
|
g.grid1, g.grid2 = g.grid2, new(Grid)
|
|
return
|
|
}
|
|
|
|
func (g *GOL) Calc() (gr *Grid) {
|
|
for i := 0; i < size; i++ {
|
|
for j := 0; j < size; j++ {
|
|
g.check(i, j)
|
|
}
|
|
}
|
|
g.Gen++
|
|
return g.grid()
|
|
}
|
|
func main() {
|
|
gol := NewGOL()
|
|
gc := make(chan *Grid, 10)
|
|
ic := make(chan image.Image, 10)
|
|
go func() {
|
|
o := jpeg.Options{100}
|
|
img := <-ic
|
|
for {
|
|
select {
|
|
case img = <-ic:
|
|
default:
|
|
}
|
|
if jpeg.Encode(os.Stdout, img, &o) == nil {
|
|
os.Stdout.Sync()
|
|
}
|
|
time.Sleep(time.Millisecond * 16)
|
|
}
|
|
}()
|
|
go func() {
|
|
s := size * zoom
|
|
r := image.Rect(0, 0, s, s)
|
|
for {
|
|
img := image.NewGray(r)
|
|
grid := <-gc
|
|
x := 0
|
|
y := 0
|
|
var c color.Color
|
|
for i := 0; i < size; i++ {
|
|
for j := 0; j < size; j++ {
|
|
if grid.G[i][j] {
|
|
c = color.Black
|
|
} else {
|
|
c = color.White
|
|
}
|
|
for a := 0; a < zoom; a++ {
|
|
for b := 0; b < zoom; b++ {
|
|
img.Set(x+a, y+b, c)
|
|
}
|
|
}
|
|
y += zoom
|
|
}
|
|
x += zoom
|
|
y = 0
|
|
}
|
|
ic <- img
|
|
}
|
|
}()
|
|
|
|
for {
|
|
gc <- gol.Calc()
|
|
fmt.Fprintf(os.Stderr, "\rGeneration: %d", gol.Gen)
|
|
time.Sleep(time.Second / gps)
|
|
}
|
|
}
|