From c7c84b658487f51d61cbeff0199c124fcf13a268 Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Sun, 24 Nov 2019 19:13:56 -0500 Subject: Fixed end condition to handle when the current player can not move but the opponent can. --- .idea/scala_compiler.xml | 4 +++- .../me/robbyzambito/othello/game/AIPlayer.scala | 19 ++++++++++++++++++- .../scala/me/robbyzambito/othello/game/Game.scala | 20 +++++++++++++++----- .../scala/me/robbyzambito/othello/game/Player.scala | 15 ++++++++++++--- .../me/robbyzambito/othello/game/UserPlayer.scala | 7 +++++-- 5 files changed, 53 insertions(+), 12 deletions(-) diff --git a/.idea/scala_compiler.xml b/.idea/scala_compiler.xml index a26a233..8fdaf03 100644 --- a/.idea/scala_compiler.xml +++ b/.idea/scala_compiler.xml @@ -1,6 +1,8 @@ - + + \ No newline at end of file diff --git a/src/main/scala/me/robbyzambito/othello/game/AIPlayer.scala b/src/main/scala/me/robbyzambito/othello/game/AIPlayer.scala index 5c3efc6..307c8e1 100644 --- a/src/main/scala/me/robbyzambito/othello/game/AIPlayer.scala +++ b/src/main/scala/me/robbyzambito/othello/game/AIPlayer.scala @@ -1,12 +1,29 @@ package me.robbyzambito.othello.game +/** + * Decides how the AI player should behave. + * + * Written by Robby Zambito + * Written on 11/20/2019 + * Targeting Scala 2.13.1 + * + * See [[Player]] + */ case class AIPlayer(override val color: Position) extends Player(color) { override def nextMove(board: Board): Move = { + + implicit val moveOrdering: Ordering[Move] = new Ordering[Move] { + override def compare(x: Move, y: Move): Int = { + x.takenPositions.length.compareTo(y.takenPositions.length) + } + } + println(s"$this moving...") Thread.sleep(500L) println() - possibleMoves(board).head + + possibleMoves(board).max } } diff --git a/src/main/scala/me/robbyzambito/othello/game/Game.scala b/src/main/scala/me/robbyzambito/othello/game/Game.scala index 4c0e7a2..6fc278f 100644 --- a/src/main/scala/me/robbyzambito/othello/game/Game.scala +++ b/src/main/scala/me/robbyzambito/othello/game/Game.scala @@ -17,6 +17,10 @@ case class Game(board: Board, val currentPlayer: Player = players(turnCount % players.length) val currentOpponent: Player = players(turnCount % players.length) + /** + * Plays the game. + * @param game Current state of the game. + */ @tailrec final def loop(game: Game = this): Unit = { if (game.winner.isEmpty) { @@ -38,10 +42,10 @@ case class Game(board: Board, * * [[None]] if there has not been a winner yet. Otherwise return the [[Player]] which has won. */ - lazy val winner: Option[Player] = { - if (currentPlayer.canMove(board) || (!currentPlayer.canMove(board) && currentOpponent.canMove(board))) + val winner: Option[Player] = { + if (currentPlayer.canMove(board) || currentOpponent.canMove(board)) None - else { // No one can move + else { // No one can move => Game is finished val whiteCount = board.positions.flatten.count(_ == Position.WHITE) val blackCount = board.positions.flatten.count(_ == Position.BLACK) @@ -64,9 +68,15 @@ case class Game(board: Board, def takeTurn: Game = { println(s"${this}\n") - val move = currentPlayer.nextMove(board) + if (currentPlayer.canMove(board)) { + val move = currentPlayer.nextMove(board) - this.copy(board = move(board, currentPlayer), turnCount = turnCount + 1) + this.copy(board = move(board, currentPlayer), turnCount = turnCount + 1) + } else { + println(s"$currentPlayer has no moves! Skipping turn...") + + this.copy(board = board, turnCount = turnCount + 1) + } } override def toString: String = diff --git a/src/main/scala/me/robbyzambito/othello/game/Player.scala b/src/main/scala/me/robbyzambito/othello/game/Player.scala index 7abf3d2..925f7d2 100644 --- a/src/main/scala/me/robbyzambito/othello/game/Player.scala +++ b/src/main/scala/me/robbyzambito/othello/game/Player.scala @@ -2,6 +2,16 @@ package me.robbyzambito.othello.game import scala.util.Try +/** + * Represents a party which is partaking in the game. + * Both the AI and the end user are instances of Player. + * + * Written by Robby Zambito + * Written on 11/20/2019 + * Targeting Scala 2.13.1 + * + * @param color The color of the player. + */ abstract class Player(val color: Position) { def nextMove(board: Board): Move @@ -59,7 +69,7 @@ abstract class Player(val color: Position) { } else List.empty } - // Check can move left or right + // Check can move down or up val changes = checkInDirection(rowCount, 1) ::: checkInDirection(rowCount, -1) if (changes.nonEmpty) Some(Move(rowCount, colCount, changes)) @@ -75,8 +85,7 @@ abstract class Player(val color: Position) { Some( Move(rowCount, colCount, - acc.map(_.takenPositions).getOrElse(List.empty) ::: vert.map(_.takenPositions).getOrElse(List.empty) - ) + acc.map(_.takenPositions).getOrElse(List.empty) ::: vert.map(_.takenPositions).getOrElse(List.empty)) ) else None }).flatten diff --git a/src/main/scala/me/robbyzambito/othello/game/UserPlayer.scala b/src/main/scala/me/robbyzambito/othello/game/UserPlayer.scala index dc1c84c..4ecf1e1 100644 --- a/src/main/scala/me/robbyzambito/othello/game/UserPlayer.scala +++ b/src/main/scala/me/robbyzambito/othello/game/UserPlayer.scala @@ -4,12 +4,13 @@ import scala.io.StdIn import scala.util.Try /** - * Represents a party which is partaking in the game. - * Both the AI and the end user are instances of Player. + * Allows for the User to input their moves. * * Written by Robby Zambito * Written on 11/20/2019 * Targeting Scala 2.13.1 + * + * See [[Player]] */ case class UserPlayer(override val color: Position) extends Player(color) { @@ -22,6 +23,8 @@ case class UserPlayer(override val color: Position) extends Player(color) { Try(StdIn.readLine(s"Enter the col to move for ${this}: ").toInt) ).dropWhile(_.isFailure).next().get + println() + (rowCount, colCount) } -- cgit v1.2.3