// // simple text-mode version of Conway's game of life // // initial board configuration is read in from a file, one line // per row, with X's for occupied cells and .'s for unoccupied cells. // case class Board(b : Array[Array[Boolean]]) val EmptyChar = '.' val FullChar = 'X' val usageMessage = "command-line argument: file with initial configuration" if (args.length < 1) { println(usageMessage) } else { try { val board = readBoard(args(0)) if (board.b.length > 0) play(board) } catch { case e:java.io.FileNotFoundException => { println("could not open file " + args(0)) } } } def readBoard(filename : String) : Board = { val source = scala.io.Source.fromFile(filename) val lines = source.getLines.toArray source.close val boardRows = Array.tabulate(lines.length)(i => buildRow(lines(i))) if (boardRows.length == 0) { println("no lines in input file") Board(boardRows) } else { if (!boardRows.forall(_.length == boardRows(0).length)) { println("not all lines the same length") Board(Array.fill(0,0)(false)) } else { Board(boardRows) } } } def buildRow(line : String) : Array[Boolean] = { line.toArray.map(_ != EmptyChar) } def printBoard(board : Board) = { for (row <- 0 until board.b.length) { println(board.b(row).map(if (_) FullChar else EmptyChar).mkString) } } def oneStep(board : Board) : Board = { Board(Array.tabulate(board.b.length, board.b(0).length)( (i,j) => newCellValue(board, i, j))) } def newCellValue(oldBoard : Board, row : Int, col : Int) : Boolean = { var neighbors = 0 val lastRow = oldBoard.b.length-1 val lastCol = oldBoard.b(0).length-1 // neighbors above if (row > 0) { if ((col > 0) && oldBoard.b(row-1)(col-1)) neighbors += 1 if (oldBoard.b(row-1)(col)) neighbors += 1 if ((col < lastCol) && oldBoard.b(row-1)(col+1)) neighbors += 1 } // neighbors in same row if ((col > 0) && oldBoard.b(row)(col-1)) neighbors += 1 if ((col < lastCol) && oldBoard.b(row)(col+1)) neighbors += 1 // neighbors below if (row < lastRow) { if ((col > 0) && oldBoard.b(row+1)(col-1)) neighbors += 1 if (oldBoard.b(row+1)(col)) neighbors += 1 if ((col < lastCol) && oldBoard.b(row+1)(col+1)) neighbors += 1 } if (oldBoard.b(row)(col)) (neighbors == 2) || (neighbors == 3) else neighbors == 3 } def play(board : Board) : Unit = { println() ; printBoard(board); println() println("press enter for next step, any other text (and enter) to quit") val response = readLine if (response == "") { play(oneStep(board)) } }