From Gossip@caterpillar

Algorithm Gossip: 生命遊戲

 說明

生命遊戲(game of life)為1970年由英國數學家J. H. Conway所提出,某一細胞的鄰居包括上、下、左、右、左上、左下、右上與右下相鄰之細胞,遊戲規則如下:
  1. 孤單死亡:如果細胞的鄰居小於一個,則該細胞在下一次狀態將死亡。
  2. 擁擠死亡:如果細胞的鄰居在四個以上,則該細胞在下一次狀態將死亡。
  3. 穩定:如果細胞的鄰居為二個或三個,則下一次狀態為穩定存活。
  4. 復活:如果某位置原無細胞存活,而該位置的鄰居為三個,則該位置將復活一細胞。

解法

生命遊戲的規則可簡化為以下,並使用CASE比對即可使用程式實作:
  1. 鄰居個數為0、1、4、5、6、7、8時,則該細胞下次狀態為死亡。
  2. 鄰居個數為2時,則該細胞下次狀態為穩定。
  3. 鄰居個數為3時,則該細胞下次狀態為復活。

實作:C    Java    Python    Scala

  • C
#include <stdio.h> 
#include <stdlib.h>
#include <ctype.h>

#define MAXROW 10
#define MAXCOL 25
#define DEAD 0
#define ALIVE 1

void output();
void copy(int[][MAXCOL], int[][MAXCOL]);
void init(int[][MAXCOL]);
int neighbors(int[][MAXCOL], int, int);

int main() {
puts("Game of life Program");
puts("Enter x, y where x, y is living cell");
printf("0 <= x <= %d, 0 <= y <= %d\n", MAXROW-1, MAXCOL-1);
puts("Terminate with x, y = -1 -1");

int map[MAXROW][MAXCOL];
int newmap[MAXROW][MAXCOL];

init(map);

while(1) {
output(map);

int row, col;
for(row = 0; row < MAXROW; row++) {
for(col = 0; col < MAXCOL; col++) {
switch (neighbors(map, row, col)) {
case 0: case 1: case 4: case 5: case 6: case 7: case 8:
newmap[row][col] = DEAD; break;
case 2:
newmap[row][col] = map[row][col]; break;
case 3:
newmap[row][col] = ALIVE; break;
}
}
}

copy(map, newmap);

printf("\nContinue next Generation ? ");
getchar();
char ans = toupper(getchar());
if(ans != 'Y')
break;
}

return 0;
}

void init(int map[][MAXCOL]) {
int row, col;
for(row = 0; row < MAXROW; row++)
for(col = 0; col < MAXCOL; col++)
map[row][col] = DEAD;

while(1) {
scanf("%d %d", &row, &col);
if(0 <= row && row < MAXROW &&
0 <= col && col < MAXCOL)
map[row][col] = ALIVE;
else if(row == -1 || col == -1)
break;
else
printf("(x, y) exceeds map ranage!");
}
}

int neighbors(int map[][MAXCOL], int row, int col) {
int count = 0;

int c, r;
for(r = row-1; r <= row+1; r++)
for(c = col-1; c <= col+1; c++) {
if(r < 0 || r >= MAXROW || c < 0 || c >= MAXCOL)
continue;
if(map[r][c] == ALIVE)
count++;
}

if(map[row][col] == ALIVE)
count--;

return count;
}

void output(int map[][MAXCOL]) {
printf("\n\nGame of life cell status\n");

int row, col;
for(row = 0; row < MAXROW; row++) {
printf("\n%20c", ' ');
for(col = 0; col < MAXCOL; col++)
if(map[row][col] == ALIVE)
putchar('#');
else
putchar('-');
}
}

void copy(int map[][MAXCOL], int newmap[][MAXCOL]) {
int row, col;
for(row = 0; row < MAXROW; row++)
for(col = 0; col < MAXCOL; col++)
map[row][col] = newmap[row][col];
}

  • Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class LifeGame {
private boolean[][] map;
private boolean[][] newmap;

public LifeGame(int maxRow, int maxColumn) {
map = new boolean[maxRow][maxColumn];
newmap = new boolean[maxRow][maxColumn];
}

public void cell(int x, int y) {
map[x][y] = true;
}

public void next() {
for(int row = 0; row < map.length; row++) {
for(int col = 0; col < map[0].length; col++) {
switch (neighbors(row, col)) {
case 0:
case 1:
case 4:
case 5:
case 6:
case 7:
case 8:
newmap[row][col] = false;
break;
case 2:
newmap[row][col] = map[row][col];
break;
case 3:
newmap[row][col] = true;
break;
}
}
}

for(int row = 0; row < map.length; row++)
for(int col = 0; col < map[0].length; col++)
map[row][col] = newmap[row][col];
}

public void print() throws IOException {
System.out.println("\n\nGame of life cell status");
for(int row = 0; row < map.length; row++) {
System.out.println();
for(int col = 0; col < map[0].length; col++)
System.out.printf("%c", map[row][col] ? '#' : '-');
}
}

private int neighbors(int row, int col) {
int count = 0;

for(int r = row-1; r <= row+1; r++)
for(int c = col-1; c <= col+1; c++) {
if(r < 0 || r >= map.length ||
c < 0 || c >= map[0].length)
continue;
if(map[r][c])
count++;
}

if(map[row][col])
count--;

return count;
}

public static void main(String[] args)
throws NumberFormatException, IOException {
BufferedReader bufReader =
new BufferedReader(
new InputStreamReader(System.in));

LifeGame game = new LifeGame(10, 25);

System.out.println("Game of life Program");
System.out.println(
"Enter x y where x y is living cell");
System.out.println("0 <= x < 10, 0 <= y < 25");
System.out.println("Terminate with x y = -1 -1");

int row = -1;
int col = -1;
do {
String[] strs = bufReader.readLine().split(" ");
row = Integer.parseInt(strs[0]);
col = Integer.parseInt(strs[1]);
if(0 <= row && row < 10 && 0 <= col && row < 25)
game.cell(row, col);
} while(col != -1);

while(true) {
game.print();
game.next();

System.out.print(
"\nContinue next Generation ? ");

String ans = bufReader.readLine().toUpperCase();

if(ans.equals("N"))
break;
}
}
}

  • Python
class LifeGame:
def __init__(self, maxRow, maxColumn):
self.__map = []
self.__newMap = []
for i in range(maxRow):
self.__map.append([False] * maxColumn)
self.__newMap.append([False] * maxColumn)
def cell(self, x, y):
self.__map[x][y] = True
def next(self):
for row in range(len(self.__map)):
for col in range(len(self.__map[0])):
n = self.__neighbors(row, col)
if n in [0, 1, 4, 5, 6, 7, 8]:
self.__newMap[row][col] = False
elif n == 2:
self.__newMap[row][col] = self.__map[row][col]
elif n == 3:
self.__newMap[row][col] = True
for row in range(len(self.__map)):
for col in range(len(self.__map[0])):
self.__map[row][col] = self.__newMap[row][col]
def print(self):
print("\nGame of life cell status")
for row in range(len(self.__map)):
print()
for col in range(len(self.__map[0])):
if self.__map[row][col]:
print("#", end="")
else:
print("-", end="")
def __neighbors(self, row, col):
count = 0
for r in range(row - 1, row + 2):
for c in range(col - 1, col + 2):
rc = r < 0 or r >= len(self.__map)
cc = c < 0 or c >= len(self.__map[0])
if rc or cc:
continue
if self.__map[r][c]:
count += 1
if self.__map[row][col] == True:
count -= 1
return count

game = LifeGame(10, 25)
print("Game of life Program")
print("Enter x, y where x, y is living cell")
print("0 <= x < 10, 0 <= y < 25")
print("Terminate with x, y = -1, -1")
while(True):
strs = input().split(",")
row = int(strs[0])
col = int(strs[1])
if row >= 0 and row < 10 and col >= 0 and row < 25:
game.cell(row, col)
elif row == -1 or col == -1:
break

while(True):
game.print()
game.next()
print("\nContinue next Generation ?", end="")
if input().upper() == "N":
break

  • Scala
class LifeGame(maxRow: Int, maxColumn: Int) {
val map = new Array[Array[Boolean]](maxRow, maxColumn)
val newmap = new Array[Array[Boolean]](maxRow, maxColumn)
def cell(x: Int, y: Int) { map(x)(y) = true }
def next() {
for{
row <- 0 until map.length;
col <- 0 until map(0).length
} neighbors(row, col) match {
case 0|1|4|5|6|7|8 => newmap(row)(col) = false
case 2 => newmap(row)(col) = map(row)(col)
case 3 => newmap(row)(col) = true
}
for{
row <- 0 until map.length;
col <- 0 until map(0).length
} map(row)(col) = newmap(row)(col)
}

private def neighbors(row: Int, col: Int) = {
var count = 0
for(r <- (row - 1) to (row + 1);
c <- (col - 1) until (col + 1)
) if(r >= 0 && r < map.length &&
c >= 0 && c < map(0).length
&& map(r)(c)) {
count += 1
}

if(map(row)(col)) count -= 1
count
}

def print() {
println("\n\nGame of life cell status");
for(row <- 0 until map.length) {
println()
for(col <- 0 until map(0).length) {
printf(if(map(row)(col)) "#" else "-")
}
}
}
}

println("Game of life Program")
println("Enter x y where x y is living cell")
println("0 <= x < 10, 0 <= y < 25")
println("Terminate with x y = -1 -1")

val game = new LifeGame(10, 25)
var row = -1
var col = -1
do {
val strs = readLine split(" ")
row = strs(0).toInt
col = strs(1).toInt
if(0 <= row && row < 10 && 0 <= col && row < 25)
game.cell(row, col)
} while(row != -1)

do {
game.print()
game.next()
print("\nContinue next Generation ? ")
} while(readLine().toUpperCase() != "N")