Skip to content

Commit

Permalink
refactoring test code and pulling console redirection out into a trait
Browse files Browse the repository at this point in the history
  • Loading branch information
trptcolin committed Jun 12, 2009
1 parent 07707ca commit 43b38f1
Show file tree
Hide file tree
Showing 25 changed files with 502 additions and 361 deletions.
64 changes: 39 additions & 25 deletions src/trptcolin/tictactoescala/basegame/Board.scala
@@ -1,68 +1,82 @@
package trptcolin.tictactoescala.basegame

object Board{
object Board
{
val winSets =
List(
List(0, 1, 2),
List(3, 4, 5),
List(6, 7, 8),
List(0, 3, 6),
List(1, 4, 7),
List(2, 5, 8),
List(0, 4, 8),
List(2, 4, 6))
List(
List(0, 1, 2),
List(3, 4, 5),
List(6, 7, 8),
List(0, 3, 6),
List(1, 4, 7),
List(2, 5, 8),
List(0, 4, 8),
List(2, 4, 6))

}

trait Board{
def full(): Boolean ={
trait Board
{
def positions: List[String]
def clear(): Board
def move(mark: String, position: Int): Board

def full(): Boolean =
{
return !positions.exists(_ == null)
}

def openPositions(): List[Int] ={
def openPositions(): List[Int] =
{
if (full())
{
return List()
}
else{
val positionsList =
for {
for
{
position <- (0 to 8).toList
if positions(position) == null
} yield position
}
yield position

return positionsList
}
}

def won(): Boolean ={
def won(): Boolean =
{
return wonBy("X") || wonBy("O")
}

def wonBy(mark: String): Boolean ={
def wonBy(mark: String): Boolean =
{
return Board.winSets.exists(winSet => winSet.forall(positions(_) == mark))
}

def over(): Boolean = {
def over(): Boolean =
{
return full() || won()
}

def positions: List[String]
def clear(): Board

def move(mark: String, position: Int): Board

override def toString: String ={
override def toString: String =
{
return positions.toString
}

def newPositions(mark: String, position: Int): List[String] ={
def newPositions(mark: String, position: Int): List[String] =
{
val newPositions = new Array[String](9)
positions.copyToArray(newPositions, 0)

newPositions(position) = mark
return newPositions.toList
}

def invalidMove(position: Int): Boolean ={
def invalidMove(position: Int): Boolean =
{
return position < 0 || position > 8 || positions(position) != null
}
}
12 changes: 8 additions & 4 deletions src/trptcolin/tictactoescala/basegame/BoardImpl.scala
@@ -1,18 +1,22 @@
package trptcolin.tictactoescala.basegame

class BoardImpl(val positions: List[String]) extends Board {
def this() ={
class BoardImpl(val positions: List[String]) extends Board
{
def this() =
{
this (List[String](
null, null, null,
null, null, null,
null, null, null))
}

def move(mark: String, position: Int): Board ={
def move(mark: String, position: Int): Board =
{
return new BoardImpl(newPositions(mark, position))
}

def clear(): Board = {
def clear(): Board =
{
new BoardImpl()
}
}
43 changes: 28 additions & 15 deletions src/trptcolin/tictactoescala/basegame/Game.scala
@@ -1,53 +1,66 @@
package trptcolin.tictactoescala.basegame

abstract class Game(startingBoard: Board, players: Array[Player]){
abstract class Game(startingBoard: Board, players: Array[Player])
{
val fsm = new GameContext(this)

var board = startingBoard
def clearBoard(): Unit = {
board = board.clear
}

def refreshBoardState(board: Board): Unit
def decidePlayAgain(): Unit
def decideGameType(): Unit

def start(): Unit ={

def clearBoard(): Unit =
{
board = board.clear
}

def start(): Unit =
{
fsm.enterStartState()
}

def setGameType(player1: Player, player2: Player) {
def setGameType(player1: Player, player2: Player): Unit =
{
players(0) = player1
players(1) = player2

fsm.GameTypeChosen()
}

def playerMove(playerIndex: Int, square: Int) = {
def playerMove(playerIndex: Int, square: Int): Unit =
{
board = board.move(players(playerIndex).playerMark, square)
}

def getNextMove(playerIndex: Int, board: Board): Unit = {
if(board.over()) {
def getNextMove(playerIndex: Int, board: Board): Unit =
{
if(board.over())
{
fsm.GameOver()
}
else {
else
{
val pickedPosition = players(playerIndex).move(board)
pickIfValidMove(board, pickedPosition)
}
}

def pickIfValidMove(board: Board, square: Int): Unit = {
if(isValidMove(board, square)) {
def pickIfValidMove(board: Board, square: Int): Unit =
{
if(isValidMove(board, square))
{
fsm.PickSquare(board, square)
}
}

def isValidMove(board: Board, square: Int): Boolean ={
def isValidMove(board: Board, square: Int): Boolean =
{
return board.openPositions.exists(_ == square)
}

def refreshBoardState(): Unit = {
def refreshBoardState(): Unit =
{
refreshBoardState(board)
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/trptcolin/tictactoescala/basegame/Player.scala
@@ -1,12 +1,15 @@
package trptcolin.tictactoescala.basegame

trait Player{
trait Player
{
val playerMark: String
def move(board: Board): Int
}

object Player {
def otherMark(mark: String): String ={
object Player
{
def otherMark(mark: String): String =
{
if (mark == "X")
"O"
else
Expand Down
45 changes: 30 additions & 15 deletions src/trptcolin/tictactoescala/console/ConsoleGame.scala
Expand Up @@ -4,32 +4,41 @@ import basegame._
import java.io.EOFException
import players.PlayerFactory

class ConsoleGame(startingBoard: Board, val players: Array[Player]) extends Game(startingBoard, players) {
def refreshBoardState(board: Board): Unit = {
class ConsoleGame(startingBoard: Board, val players: Array[Player]) extends Game(startingBoard, players)
{
def refreshBoardState(board: Board): Unit =
{
Console.println(ConsoleGame.stringify(board))
}

def decidePlayAgain: Unit = {
def decidePlayAgain: Unit =
{
Console.println("Press any key to play again.")
Console.readLine()

fsm.PlayAgain()
}

def decideGameType(): Unit = {
def decideGameType(): Unit =
{
Console.println("What type of game would you like to play?")
Console.println(" 1 - Computer (X) vs. Computer (O)")
Console.println(" 2 - Computer (X) vs. Human (O)")
Console.println(" 3 - Human (X) vs. Computer (O)")
Console.println(" 4 - Human (X) vs. Human (O)")

try{
try
{
val attemptedGameType = Console.readInt()

if (attemptedGameType > 4 || attemptedGameType < 1)
{
throw new NumberFormatException()
else {
attemptedGameType match {
}
else
{
attemptedGameType match
{
case 1 =>
setGameType(PlayerFactory.generate("Computer", "X"), PlayerFactory.generate("Computer", "O"))
case 2 =>
Expand All @@ -41,7 +50,8 @@ class ConsoleGame(startingBoard: Board, val players: Array[Player]) extends Game
}
}
}
catch{
catch
{
case ex: NumberFormatException =>
Console.println("There was a problem with your input! Digits only!")
decideGameType()
Expand All @@ -52,22 +62,27 @@ class ConsoleGame(startingBoard: Board, val players: Array[Player]) extends Game
}
}

object ConsoleGame {
object ConsoleGame
{

def stringify(board: Board): String = {
def stringForPosition(position: Int): String = {
def stringify(board: Board): String =
{
def stringForPosition(position: Int): String =
{
val mark = board.positions(position)
if(mark == null)
return " "
else
return mark
}

def addHorizontalLine(boardString: String): String = {
def addHorizontalLine(boardString: String): String =
{
return boardString + "\n-----------\n"
}

def addRowOfSquares(boardString: String, row: Int): String = {
def addRowOfSquares(boardString: String, row: Int): String =
{
return boardString + " " +
stringForPosition(3 * row) +
" | " +
Expand All @@ -79,12 +94,12 @@ object ConsoleGame {


var boardString = ""
for(row <- 0 to 2) {
for(row <- 0 to 2)
{
boardString = addRowOfSquares(boardString, row)
if(row < 2)
boardString = addHorizontalLine(boardString)
}
return boardString + "\n"
}

}
6 changes: 4 additions & 2 deletions src/trptcolin/tictactoescala/console/ConsoleTicTacToe.scala
Expand Up @@ -2,8 +2,10 @@ package trptcolin.tictactoescala.console
import basegame.BoardImpl
import players._

object ConsoleTicTacToe{
def main(args: Array[String]){
object ConsoleTicTacToe
{
def main(args: Array[String])
{
val board = new BoardImpl()
val player1 = new ComputerPlayer("X")
val player2 = new ComputerPlayer("O")
Expand Down

0 comments on commit 43b38f1

Please sign in to comment.