Created
July 5, 2009 10:58
-
-
Save hitode909/140930 to your computer and use it in GitHub Desktop.
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
import scala.collection.mutable.HashMap | |
import java.lang.Math | |
class Vector(var x:Int, var y:Int) { | |
override def toString = { | |
"("+ x + "," + y + ")" | |
} | |
override def equals(that: Any): Boolean = | |
that.isInstanceOf[Vector] && { | |
val o = that.asInstanceOf[Vector] | |
o.x == x && o.y == y | |
} | |
override def hashCode = { | |
(x, y).hashCode() | |
} | |
def + (that: Vector): Vector = { | |
new Vector(that.x + x, that.y + y) | |
} | |
def - (that: Vector): Vector = { | |
new Vector(that.x - x, that.y - y) | |
} | |
} | |
class Cell(var state:Boolean) { | |
def step(previous: Cell, neighbors: List[Cell]) { | |
state = (previous.state, neighbors.count( b => b.state)) match { | |
case (true, 2) => true | |
case (true, 3) => true | |
case (false, 3) => true | |
case _ => false | |
} | |
} | |
override def toString = { | |
(if (state) "*" else ".") | |
} | |
} | |
class Board { | |
var min = new Vector(0,0) | |
var max = new Vector(0,0) | |
var field = new HashMap[Vector, Cell]; | |
def cellFor(position:Vector): Cell ={ | |
if (field.contains(position)) { | |
field(position) | |
} else { | |
new Cell(false) | |
} | |
} | |
def put(position:Vector, cell:Cell):Board = { | |
if (cell.state) { | |
field(position) = cell | |
expand_field(position) | |
} | |
this | |
} | |
def expand_field(position:Vector) { | |
if (position.x < min.x) min.x = position.x | |
if (position.y < min.y) min.y = position.y | |
if (position.x > max.x) max.x = position.x | |
if (position.y > max.y) max.y = position.y | |
} | |
def cut_field() { | |
var at = (min.x to max.x).map(x => (min.y to max.y).map(y => cellFor(new Vector(x,y)))).map(line => line.toList.count(c => c.state) > 0).indexOf(true) | |
if (at != -1) { | |
min.x = (min.x to max.x)(at) | |
} | |
at = (min.y to max.y).map(y => (min.x to max.x).map(x => cellFor(new Vector(x,y)))).map(line => line.toList.count(c => c.state) > 0).indexOf(true) | |
if (at != -1) { | |
min.y = (min.y to max.y)(at) | |
} | |
at = (min.x to max.x).map(x => (min.y to max.y).map(y => cellFor(new Vector(x,y)))).map(line => line.toList.count(c => c.state) > 0).lastIndexOf(true) | |
if (at != -1) { | |
max.x = (min.x to max.x)(at) | |
} | |
at = (min.y to max.y).map(y => (min.x to max.x).map(x => cellFor(new Vector(x,y)))).map(line => line.toList.count(c => c.state) > 0).lastIndexOf(true) | |
if (at != -1) { | |
max.y = (min.y to max.y)(at) | |
} | |
} | |
} | |
class Game { | |
var board = new Board; | |
var use_cut_field = false; | |
private var cycle = 0 | |
def put(x:Int, y:Int) { | |
board.put(new Vector(x, y), new Cell(true)) | |
} | |
def step { | |
var newboard = new Board; | |
cycle += 1 | |
for(x <- board.min.x-1 to board.max.x+1) { | |
for(y <- board.min.y-1 to board.max.y+1) { | |
var position = new Vector(x,y) | |
var neighbors = List(new Cell(false)) | |
for( diffx <- (-1 to 1) ) { | |
for( diffy <- (-1 to 1) ) { | |
if (!(diffx == 0 && diffy == 0)) { | |
neighbors = board.cellFor(position + new Vector(diffx, diffy)) :: neighbors | |
} | |
} | |
} | |
var newcell = new Cell(false) | |
newcell.step(board.cellFor(position), neighbors) | |
newboard.put(position, newcell) | |
} | |
} | |
board = newboard | |
} | |
override def toString = { | |
if (use_cut_field) board.cut_field | |
var buffer = "" | |
if (use_cut_field) buffer += (board.min + new Vector(-1,-1)) + "~" + (board.max + new Vector(1,1)) + "\n" | |
for(x <- board.min.x-1 to board.max.x+1) { | |
for(y <- board.min.y-1 to board.max.y+1) { | |
var position = new Vector(x,y) | |
buffer += board.cellFor(position)+" " | |
} | |
buffer += "\n" | |
} | |
buffer | |
} | |
} | |
object LifeGame { | |
def main(args: Array[String]) { | |
var i=0; | |
var game = new Game | |
for (arg <- args) { | |
if (arg == "use_cut_field") { | |
game.use_cut_field = true | |
} | |
if (arg == "glider") { | |
load(game, glider) | |
} | |
if (arg == "blinker") { | |
load(game, blinker) | |
} | |
if (arg == "glidergun") { | |
load(game, glidergun) | |
} | |
if (arg == "help") { | |
println("% scala LifeGame [glider|blinker|glidergun] (use_cut_field)") | |
exit | |
} | |
} | |
while(true) { | |
println(game) | |
game.step | |
Thread.sleep(80) | |
} | |
} | |
def load(game: Game, what: List[(Int, Int)]) { | |
for(pos <- what) { | |
game.put(pos._2, pos._1) | |
} | |
} | |
def glider = List((0,1),(1,2),(2,2),(2,1),(2,0)) | |
def blinker = List((0,0),(1,0),(2,0)) | |
def glidergun = List( | |
(-1,4), | |
(-1,5), | |
(0,4), | |
(0,5), | |
(9,4), | |
(9,5), | |
(9,6), | |
(10,3), | |
(10,7), | |
(11,2), | |
(11,8), | |
(12,2), | |
(12,8), | |
(13,5), | |
(14,3), | |
(14,7), | |
(15,4), | |
(15,5), | |
(15,6), | |
(16,5), | |
(19,2), | |
(19,3), | |
(19,4), | |
(20,2), | |
(20,3), | |
(20,4), | |
(21,1), | |
(21,5), | |
(23,0), | |
(23,1), | |
(23,5), | |
(23,6), | |
(33,2), | |
(33,3), | |
(34,2), | |
(34,3) | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment