Nature of Code 之 7 - CA
Game of Life
module main
import rand
import gg
import gx
pub struct Cell {
mut:
x int
y int
state int
prev_state int
}
pub fn new_cell(x_ int, y_ int) Cell {
st := rand.intn(2)
return Cell{
x: x_
y: y_
state: st
prev_state: st
}
}
pub fn (mut c Cell) save_prev_state() {
c.prev_state = c.state
}
pub fn (mut c Cell) new_state(s int) {
c.state = s
}
pub struct Gol {
mut:
w int
columns int
rows int
board [][]Cell
}
pub fn new_gol(width int, height int, w_ int) &Gol {
col := height / w_
row := width / w_
mut bo := [][]Cell{len: col, init: []Cell{len: row}}
for i := 0; i < col; i++ {
for j := 0; j < row; j++ {
bo[i][j] = new_cell(j, i)
}
}
return &Gol{
w: w_
columns: col
rows: row
board: bo
}
}
pub fn (mut g Gol) generate() {
for i := 0; i < g.columns; i++ {
for j := 0; j < g.rows; j++ {
g.board[i][j].save_prev_state()
}
}
// Loop through every spot in our 2D array and check spots neighbors
for y := 0; y < g.columns; y++ {
for x := 0; x < g.rows; x++ {
// Add up all the states in a 3x3 surrounding grid
mut neighbors := 0
for i := -1; i <= 1; i++ {
for j := -1; j <= 1; j++ {
neighbors += g.board[(y + i + g.columns) % g.columns][(x + j + g.rows) % g.rows].prev_state
}
}
neighbors -= g.board[y][x].prev_state
if g.board[y][x].state == 1 && neighbors < 2 {
g.board[y][x].new_state(0)
} else if g.board[y][x].state == 1 && neighbors > 3 {
g.board[y][x].new_state(0)
} else if g.board[y][x].state == 0 && neighbors == 3 {
g.board[y][x].new_state(1)
}
}
}
}
struct App {
mut:
gg &gg.Context
gol &Gol
}
fn main() {
mut app := &App{
gg: 0
gol: 0
}
app.gg = gg.new_context(
bg_color: gx.black
width: 640
height: 480
create_window: true
window_title: 'Game of Life'
frame_fn: frame
user_data: app
)
app.gol = new_gol(640, 480, 8)
app.gg.run()
}
fn frame(mut app &App) {
app.gg.begin()
app.gol.generate()
app.draw()
app.gg.end()
}
fn (app &App) draw() {
w := app.gol.w
for i := 0; i < app.gol.columns; i++ {
for j := 0; j < app.gol.rows; j++ {
if app.gol.board[i][j].state == 1 {
app.gg.draw_rect_filled(j * w, i * w,w,w,gx.yellow)
} else {
app.gg.draw_rect_filled(j * w, i * w,w,w,gx.black)
}
}
}
}
See also