forked from clausjoergensen/game_of_life
-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_of_life.swift
executable file
·131 lines (111 loc) · 4.21 KB
/
game_of_life.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/swift
// Copyright (c) 2020 Claus Jørgensen
import Foundation
/// Conway's Game of Life
///
/// https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
struct GameOfLife: CustomStringConvertible {
private var map: [[Int]]
/// Constructs a Game of Life
///
/// - param seed: The initial game seed (two-dimensional array).
init(_ seed: [[Int]]) {
self.map = seed
}
/// Transitions the game once
mutating func transition () {
var newMap: [[Int]] = .init(repeating: [Int](), count: map.count)
for x in 0..<map.count {
for y in 0..<map[x].count {
if newMap[x].count == 0 {
newMap[x] = map[x]
}
let neighbors = self.neighbors(x: x, y: y)
let numAlive = neighbors.reduce(into: 0) { (a, c) in a = (c == 1 ? a + 1 : a) }
if (numAlive < 2) {
newMap[x][y] = 0 // death by under population
} else if (numAlive > 3) {
newMap[x][y] = 0 // death by over population
} else if (map[x][y] == 0 && numAlive == 3) {
newMap[x][y] = 1 // alive by reproduction
} else {
newMap[x][y] = map[x][y] // continue unchanged
}
}
}
map = newMap
}
/// Gets a string representation of the game's current state.
var description: String {
var output = ""
for x in 0..<map.count {
for y in 0..<map[x].count {
if (map[x][y] == 1) {
output += "+ "
} else {
output += " "
}
}
output += "\n"
}
return output
}
/// Gets the cell neighbors
private func neighbors(x: Int, y: Int) -> [Int] {
var neighbors: [Int] = []
let mapSizeX = map.count
let mapSizeY = map[0].count
if (x - 1) >= 0 {
neighbors.append(map[x - 1][y]) // left
}
if (x + 1) < mapSizeX {
neighbors.append(map[x + 1][y]) // right
}
if (y - 1) >= 0 {
neighbors.append(map[x][y - 1]) // top
}
if (y + 1) < mapSizeY {
neighbors.append(map[x][y + 1]) // bottom
}
if (x - 1) >= 0 && (y - 1) >= 0 {
neighbors.append(map[x - 1][y - 1]) // top-left
}
if (x - 1) >= 0 && (y + 1) < mapSizeY {
neighbors.append(map[x - 1][y + 1]) // bottom-left
}
if (x + 1) < mapSizeX && (y + 1) < mapSizeY {
neighbors.append(map[x + 1][y + 1]) // top-right
}
if (x + 1) < mapSizeX && (y - 1) >= 0 {
neighbors.append(map[x + 1][y - 1]) // bottom-right
}
return neighbors
}
}
let pentadecathlon = [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
]
var game = GameOfLife(pentadecathlon)
while true {
print("\u{001B}[2J", game)
game.transition()
sleep(1)
}