Skip to content

Instantly share code, notes, and snippets.

@irumiha
Created March 4, 2015 17:29
Show Gist options
  • Save irumiha/45d65315927a3f8229f6 to your computer and use it in GitHub Desktop.
Save irumiha/45d65315927a3f8229f6 to your computer and use it in GitHub Desktop.
Game of Life short implementation in Scala
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