../

pt-br en

Conway's Game Of Life

Para o Game Of Life, nosso espaço será definido como um 2d array, isso equivale a uma tela ou plano cartesiano. O estado será um simples booliano, porque nesse Autômato o estado varia apenas entre dois valores. Temos assim o seguinte struct para armazenar nossos estados.

type GameOfLife struct {
 values [][]bool
}

O comportamento do nosso Autômato é definido nesse método Update. Nele cada elemento do nosso array é comparado aos seus vizinhos, isso determina qual o novo estado daquela célula.

func (gol *GameOfLife) Update() error {
 // Primeiro criamos uma cópia do estado original, garantindo assim que não haverá conflitos
	m0 := make([][]bool, len(gol.values))
	copy(m0, gol.values)

	for x, row := range gol.values {
		for y, v0 := range row {
			// Cell names
			// |v1|v2|v3|
			// |v4|v0|v5|
			// |v6|v7|v8|
			var alive uint

			// Aqui contamos quantos vizinhos com estado verdadeiro essa célula possui
			if v1 := gol.IsAliveOrNil(x-1, y-1); v1 != nil && *v1 {
				alive++
			}
			if v2 := gol.IsAliveOrNil(x, y-1); v2 != nil && *v2 {
				alive++
			}
			if v3 := gol.IsAliveOrNil(x+1, y-1); v3 != nil && *v3 {
				alive++
			}
			if v4 := gol.IsAliveOrNil(x-1, y); v4 != nil && *v4 {
				alive++
			}
			if v5 := gol.IsAliveOrNil(x+1, y); v5 != nil && *v5 {
				alive++
			}
			if v6 := gol.IsAliveOrNil(x-1, y+1); v6 != nil && *v6 {
				alive++
			}
			if v7 := gol.IsAliveOrNil(x, y+1); v7 != nil && *v7 {
				alive++
			}
			if v8 := gol.IsAliveOrNil(x+1, y+1); v8 != nil && *v8 {
				alive++
			}

			// Essa é aplicação da regra em si. A definição dela é a clássico proposta por Conway.
			// Uma célula viva morre quando possui menos de 2 vizinhos vivos
			// Uma célula viva morre quando possui mais de 3 vizinhos vivos
			// Uma célula morta volta a vida quando possui exatamente 3 vizinhos vivos
			// Em todos os outros casos ela mantém seu estado original
			if v0 && (alive < 2 || alive > 3) { 
				m0[x][y] = false
			}
			if !v0 && (alive == 3) {
				m0[x][y] = true
			}

		}
	}
	gol.values = m0
	return nil
}

Para determinar se a célula existe e qual o seu estado, existe esse método. Perceba que ele retorna um ponteiro, caso a célula não exista é retornado um ponteiro vazio(nil), do contrário é retornado o estado daquela célula.

func (gol *GameOfLife) IsAliveOrNil(x, y int) *bool {
	xOut := x < 0 || x > len(gol.values)-1
	yOut := y < 0 || y > len(gol.values)-1

	if xOut || yOut {
		return nil
	}
	return &gol.values[x][y]
}

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas praticas e fora do mundinho web. Caso tenha alguma duvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. thank you!