From d13de717ce99fee03efb0c418ec4db9fee50e9b2 Mon Sep 17 00:00:00 2001 From: Christos Choutouridis Date: Tue, 20 Oct 2020 21:33:53 +0300 Subject: [PATCH] WIP: First draft of the game with rounds and winners --- src/net/hoo2/auth/labyrinth/Board.java | 52 ++++++++++++++++ src/net/hoo2/auth/labyrinth/Common.java | 3 + src/net/hoo2/auth/labyrinth/Game.java | 65 ++++++++++++++++++-- src/net/hoo2/auth/labyrinth/Player.java | 80 ++++++++++++++++++++++++- src/net/hoo2/auth/labyrinth/Supply.java | 5 ++ src/net/hoo2/auth/labyrinth/Tile.java | 17 ++++++ 6 files changed, 215 insertions(+), 7 deletions(-) diff --git a/src/net/hoo2/auth/labyrinth/Board.java b/src/net/hoo2/auth/labyrinth/Board.java index 109012c..ea875aa 100644 --- a/src/net/hoo2/auth/labyrinth/Board.java +++ b/src/net/hoo2/auth/labyrinth/Board.java @@ -126,6 +126,58 @@ class Board { System.out.println(); } } + + /** + * Predicate to check if a direction is Walkable + * @param tileId The starting tileId. + * @param direction The desired direction. + * @return True if it is walkable. + */ + boolean isWalkable(int tileId, int direction) { + return !tiles[tileId].hasWall(direction) + && !(tileId == 0 && direction == Direction.DOWN); + } + + /** + * Predicate to check if a direction is Walkable + * @param row Row position of the starting tile. + * @param column Column position of the starting tile. + * @param direction The desired direction. + * @return True if it is walkable. + */ + boolean isWalkable(int row, int col, int direction) { + return !tiles[Position.toID(row, col)].hasWall(direction) + && !(Position.toID(row, col) == 0 && direction == Direction.DOWN); + } + + /** + * Try to pick supply from a tile. If succeed it also erases the + * supply from the board. + * + * @param tileId The tile to check + * @return The id of supply. + * @arg Const.noSupply if there is none + * @arg The ID of supply if there is one. + */ + int tryPickSupply(int tileId) { + int supplyId = tiles[tileId].hasSupply(supplies); + if (supplyId != Const.noSupply) { + tiles[tileId].pickSupply(supplies, supplyId); + } + return supplyId; + } + + /** + * A plain fair dice functionality provided by the board. + * @return A random direction; + */ + int dice () { + ShuffledRange d = new ShuffledRange(Direction.Begin, Direction.End, Direction.Step); + return d.get(); + } + + /** @return the size of each site of the board. */ + int size () { return N; } /** @} */ /** diff --git a/src/net/hoo2/auth/labyrinth/Common.java b/src/net/hoo2/auth/labyrinth/Common.java index d0ba3c5..20f3cad 100644 --- a/src/net/hoo2/auth/labyrinth/Common.java +++ b/src/net/hoo2/auth/labyrinth/Common.java @@ -178,7 +178,10 @@ class Range { } } + /** @name protected data types */ + /** @{ */ protected ArrayList numbers; /**< handle to range */ + /** @} */ } /** diff --git a/src/net/hoo2/auth/labyrinth/Game.java b/src/net/hoo2/auth/labyrinth/Game.java index 3f6ce2d..20733a1 100644 --- a/src/net/hoo2/auth/labyrinth/Game.java +++ b/src/net/hoo2/auth/labyrinth/Game.java @@ -8,21 +8,74 @@ package net.hoo2.auth.labyrinth; /** - * + * Main application class. This class is the only public interface of + * the entire game. */ public class Game { + Game() {} /**< An empty constructor */ + + /** + * @name Accessor/Mutator interface + * @note + * Please consider not to use mutator interface. Its the abstraction killer :( + * We have added a bit of logic however, in order to make it a bit more safe. + */ + /** @{ */ + int getRound() { return round; } + void setRound (int round) { this.round = round; } + /** @} */ + + /** @name Game's data */ + /** @{ */ + private int round; + /** @} */ + + /** + * Main game loop + */ public static void main(String[] args) { try { - Board board = new Board(7, 3, 60); - board.createBoard(0, Position.toID(3, 3)); - String[][] frame = board.getStringRepresentation(0, Position.toID(3, 3)); - board.printBoard(frame); + // Create a game, a board and 2 players. + Game game = new Game(); + Board board = new Board(11, 4, 82); + Player T = new Player(1, "Theseus", board, 0); + Player M = new Player(2, "Minotaur", board, Position.toID(3, 3)); + // Populate data to the board + board.createBoard(T.playerTileId(), M.playerTileId()); + + while (true) { + int[] m; + System.out.println(); + System.out.println("Round: " + (game.getRound()+1)); + + m = T.move(T.playerTileId()); + System.out.println(T.getName() + ":\t tileId =" + m[0] + " (" + m[1] + ", " + m[2] + ")"); + m = M.move(M.playerTileId()); + System.out.println(M.getName() + ":\t tileId =" + m[0] + " (" + m[1] + ", " + m[2] + ")"); + board.printBoard( + board.getStringRepresentation(T.playerTileId(), M.playerTileId()) + ); + + // Termination cases + if (T.getScore() == 4) { + System.out.println(T.getName() + " Wins!!! Score =" + T.getScore()); + System.exit(0); + } + if (M.getScore() == 4 || M.playerTileId() == T.playerTileId()) { + System.out.println(M.getName() + " Wins!!! Score =" + M.getScore()); + System.exit(0); + } + game.setRound(game.getRound()+1); + if (!(game.getRound() < 100)) { + System.out.println("New day has come... Tie!!!"); + System.exit(0); + } + } } catch (Exception e) { System.out.println(e.getMessage()); System.exit(1); } } - } diff --git a/src/net/hoo2/auth/labyrinth/Player.java b/src/net/hoo2/auth/labyrinth/Player.java index cdfd98d..9ada13a 100644 --- a/src/net/hoo2/auth/labyrinth/Player.java +++ b/src/net/hoo2/auth/labyrinth/Player.java @@ -6,8 +6,86 @@ package net.hoo2.auth.labyrinth; * This class represents the game's player */ class Player { + /** @name Contructors */ + /** @{ */ + + /** + * Create a new player and put him at the row-column coordinates + * @param id The id of the player + * @param name The name of the player + * @param board Reference to the board of the game + */ + Player(int id, String name, Board board, int row, int column) { + this.playerId = id; + this.name = name; + this.board = board; + this.score = 0; + this.x = column; + this.y = row; + } + + /** + * Create a new player and put him at the row-column coordinates + * @param id The id of the player + * @param name The name of the player + * @param board Reference to the board of the game + */ + Player(int id, String name, Board board, int tileId) { + this.playerId = id; + this.name = name; + this.board = board; + this.score = 0; + this.x = Position.toCol(tileId); + this.y = Position.toRow(tileId); + } + /** @} */ + + /** @name Player main application interface */ + /** @{ */ + + /** + * Player's move. + * + * A player first throw a dice to get a random direction. Then checks if the direction + * is walkable. If it is, then goes to that tile, pick up a possible supply on the tile + * and update player's data. + * + * @param id The id of the starting tile. + * @return An array containing player's final position and possible supply of that position. + * The array format is: + * + */ + int[] move(int id) { + // Init return array with the current data + int[] ret = {id, Position.toRow(id), Position.toCol(id), Const.noSupply}; + + int diceDirection = board.dice(); // throw the dice + if (board.isWalkable(id, diceDirection)) { // The result is walkable + // Get next tile + Position next = new Position(Position.toRow(id), Position.toCol(id), diceDirection); + ret[0] = next.getId(); // Update player's and return data + ret[1] = y = next.getRow(); + ret[2] = x = next.getCol(); + if ((ret[3] = board.tryPickSupply(next.getId())) != Const.noSupply) { + ++score; // keep score + System.out.println(name + ":\t*Found a supply. [score: " + score + "]"); + } + } + else + System.out.println(name + ":\t*Can not move."); + return ret; + } + + int playerTileId() { return Position.toID(y, x); } + int playerRow() { return y; } + int playerCol() { return x; } + /** @} */ - /** * @name Accessor/Mutator interface * @note diff --git a/src/net/hoo2/auth/labyrinth/Supply.java b/src/net/hoo2/auth/labyrinth/Supply.java index 73d86c5..ae66cb4 100644 --- a/src/net/hoo2/auth/labyrinth/Supply.java +++ b/src/net/hoo2/auth/labyrinth/Supply.java @@ -126,6 +126,11 @@ class Supply { this.supplyTileId = p.getId(); // =tileId; return p; } + + /** + * Marks the supply removed. This usually mean the supply is picked up by a user. + */ + void removeSupply () { this.supplyId = Const.noSupply; } /** @} */ /** diff --git a/src/net/hoo2/auth/labyrinth/Tile.java b/src/net/hoo2/auth/labyrinth/Tile.java index 9fbdfde..fca8ea7 100644 --- a/src/net/hoo2/auth/labyrinth/Tile.java +++ b/src/net/hoo2/auth/labyrinth/Tile.java @@ -179,12 +179,28 @@ class Tile { return ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); } + /** + * Utility to check if the tile has a supply. + * @param supplies Reference to supply array to check. + * @return Const.noSupply if there is no supply or the supplyId if succeed. + */ int hasSupply (Supply[] supplies) { for (Supply s: supplies) if (s.position().getId() == position().getId()) return s.getSupplyId(); return Const.noSupply; } + + /** + * Utility to find a supply in the supplies array and removes it. + * @param supplies Reference to supply array to check + * @param supplyId The supplyId to search. + */ + void pickSupply (Supply[] supplies, int supplyId) { + for (Supply s: supplies) + if (s.getSupplyId() == supplyId) + s.removeSupply(); + } /** @} */ /** @@ -244,4 +260,5 @@ class Tile { * We implement it just because its in the requirements of the assignment. * @see Supply.supplyTileId */ + /** @} */ }