Created
March 4, 2015 17:29
-
-
Save irumiha/45d65315927a3f8229f6 to your computer and use it in GitHub Desktop.
Game of Life short implementation in Scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.rumi | |
object GameOfLife { | |
/** | |
* Calculate the next iteration of the Game of Life. The game state is | |
* represented by a Set[(Int,Int)] of alive cells. A new set is generated | |
* for every generation. Coordinates count from (1,1) to (w,h), while the | |
* (1,1) cell is in the top left corner. | |
* | |
* @param cells The current set of alive cells | |
* @param xdim The width dimension of the playing field. | |
* @param ydim The height dimension of the playing field. | |
* @return The next generation of cells | |
*/ | |
def nextIteration(cells: Set[(Int,Int)], xdim: Int, ydim: Int): Set[(Int,Int)] = { | |
val allCells = for { | |
ox <- 1 to xdim | |
oy <- 1 to ydim | |
} yield { | |
val ac: Int = aliveNeighbourCount(cells, xdim, ydim, ox, oy) | |
if (cells.contains((ox, oy))) { // if this cell is alive | |
if (ac < 2) (0, 0) // and it has < 2 live neighbours, -> die | |
else if (ac == 2 || ac == 3) (ox, oy) // and it has 2 or 3 live neightbours, -> continue to live | |
else (0, 0) // more than 3 live neighbours -> die | |
} | |
else if (ac == 3) { // if the cell is dead and it has exactly 3 live neighboutrs | |
(ox, oy) // make it alive | |
} | |
else { | |
(0, 0) // everything else -> dead cell | |
} | |
} | |
allCells.filterNot(_ equals (0,0)).toSet | |
} | |
/** | |
* Counts the number of alive cells neighbouring the cell with the given | |
* coordinates. | |
* | |
* @param cells The Set of all alive cells | |
* @param xdim The width dimension of the playing field. | |
* @param ydim The height dimension of the playing field. | |
* @param ox X Coordinate of the cell under test | |
* @param oy Y Coordinate of the cell under test | |
* @return | |
*/ | |
def aliveNeighbourCount(cells: Set[(Int, Int)], xdim: Int, ydim: Int, ox: Int, oy: Int): Int = { | |
val aliveCount = (for { | |
nx <- Math.max(1, ox - 1) to Math.min(ox + 1, xdim) | |
ny <- Math.max(1, oy - 1) to Math.min(oy + 1, ydim) | |
if !(nx == ox && ny == oy) && cells.contains((nx, ny)) | |
} yield 1).sum | |
aliveCount | |
} | |
def main(args: Array[String]): Unit = { | |
// The famous "Beacon" starting pattern | |
val startCells = Set((2,2), (3,2), (2,3), (5,4), (5,5), (4,5)) | |
// We create an infinite stream of game iterations but only take 10 of them | |
// and print the resulting game states. | |
val game = Stream.iterate(startCells){ ni => nextIteration(ni, 6,6) } | |
game.take(10).foreach { citer => | |
for { | |
x <- 1 to 6 | |
} { | |
for (y <- 1 to 6) { | |
if (citer.contains((x,y))) print("X") | |
else print(".") | |
} | |
println() | |
} | |
println() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment