diff --git a/src/net/hoo2/auth/labyrinth/Board.java b/src/net/hoo2/auth/labyrinth/Board.java index d77abbb..109012c 100644 --- a/src/net/hoo2/auth/labyrinth/Board.java +++ b/src/net/hoo2/auth/labyrinth/Board.java @@ -16,14 +16,14 @@ import java.util.function.IntFunction; * The board is the square arrangement of the tiles. This class is also * the owner of the tile and supply objects. */ -public class Board { +class Board { /** @name Constructors */ /** @{ */ /** * The empty constructor for default initialization */ - protected Board() { + Board() { this.N = this.S = this.W = 0; this.tiles = null; this.supplies =null; @@ -35,7 +35,7 @@ public class Board { * @param S The number of supplies on the board * @param W The number of walls on the board */ - protected Board(int N, int S, int W) { + Board(int N, int S, int W) { assert (W>= 4*N-1 && W<=(3*N*N+1)/2 ) : "Boards walls has to be in the range [4N-1, (3N^2+1)/2]"; @@ -59,7 +59,7 @@ public class Board { * In this class we try to cope with this situation knowing that we can not do anything about * assignment operator. We just add value semantics to the copy constructor and go on with our lifes... */ - protected Board(Board b) { + Board(Board b) { // Copy primitives this.N = b.N; this.S = b.S; @@ -70,31 +70,35 @@ public class Board { } /** @} */ - /** @name Supply's main application interface */ + /** @name Board's main application interface */ /** @{ */ - protected void createTiles() { - int wallPool = W; - wallPool -= createBasicTileWalls (); - createInnerWalls(wallPool); - } - - protected void createSupplies(int theseusTile, int minotaurTile) { - ShuffledRange rand = new ShuffledRange(0, N*N); - for (int tileId, i=0 ; i=0 ; --i) { for (String it : sBoard[i]) System.out.print(it); System.out.println(); } } - - int size() { return N; } - /** @} */ /** @@ -124,95 +134,208 @@ public class Board { * Please consider not to use mutator interface. Its the abstraction killer :( */ /** @{ */ - protected int getN() { return N; } - protected int getS() { return S; } - protected int getW() { return W; } + int getN() { return N; } + int getS() { return S; } + int getW() { return W; } /** * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure". * see also here * @return Reference to inner tiles array. */ - protected Tile[] getTiles() { return tiles; } + Tile[] getTiles() { return tiles; } /** * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure". * see also here * @return Reference to inner supplies array. */ - protected Supply[] getSupplies() { return supplies; } + Supply[] getSupplies() { return supplies; } - protected void setN(int N) { this.N = N; } - protected void setS(int S) { this.S = S; } - protected void setW(int W) { this.W = W; } + void setN(int N) { this.N = N; } + void setS(int S) { this.S = S; } + void setW(int W) { this.W = W; } /** * @param tiles Reference to tiles that we want to act as replacement for the inner tiles array. * @note Use with care. * Any call to this function will probably add memory for the garbage collector. */ - protected void setTiles(Tile[] tiles) { this.tiles = tiles; } + void setTiles(Tile[] tiles) { this.tiles = tiles; } /** * @param supplies Reference to supplies that we want to act as replacement for the inner supplies array. * @note Use with care. * Any call to this function will probably add memory for the garbage collector. */ - protected void setSupplies(Supply[] supplies) { this.supplies= supplies; } + void setSupplies(Supply[] supplies) { this.supplies= supplies; } + /** @} */ + + /** + * @name private functionality of the object + */ + /** @{ */ + + /** + * This function creates randomly all the tiles of the board + */ + private void createTiles() throws Exception { + int wallPool = W; + wallPool -= createBasicTileWalls (); // First create tiles with outer walls + if (createInnerWalls(wallPool) > 0) // Create inner walls with the rest of the requested walls + throw new Exception("Can not create the requested number of walls"); + } + + /** + * This function create randomly the board's supplies. + * + * The supplies has to be in separate tiles and in tiles with no player + * + * @param theseusTile The tile of the Theseus + * @param minotaurTile The tile of the Minotaur + */ + private void createSupplies(int theseusTile, int minotaurTile) { + ShuffledRange rand = new ShuffledRange(0, N*N); // Make a shuffled range of all tiles + for (int tileId, i=0 ; i + *
  • The wall is not the DOWN wall from tile (0, 0). + *
  • There is not already a wall in the desired direction. (Implies no sentinel tile). + *
  • The neighbor in this direction has at most `Const.maxTileWalls -1` walls. + * + * + * @note + * A wallable direction automatically implies that the direction in not an outer wall. + * + * @param tileId The tile to check. + * @param direction The direction to check + * @return True if the direction is wallable. + */ + private boolean isWallableDir (int tileId, int direction) { + // Check list + if (tileId == 0 && direction == Direction.DOWN) + return false; + if (tiles[tileId].hasWall(direction)) + return false; + switch (direction) { + case Direction.UP: return (tiles[upTileId.apply(tileId)].hasWalls() < Const.maxTileWalls); + case Direction.DOWN: return (tiles[downTileId.apply(tileId)].hasWalls() < Const.maxTileWalls); + case Direction.LEFT: return (tiles[leftTileId.apply(tileId)].hasWalls() < Const.maxTileWalls); + case Direction.RIGHT:return (tiles[rightTileId.apply(tileId)].hasWalls() < Const.maxTileWalls); + } + return false; + } + + /** + * Predicate to check if a tile is `Wallable`. + * + * A `wallable` tile is a tile where: + *
      + *
    • The tile has at most `Const.maxTileWalls -1` walls. + *
    • There is at least one wallable direction on the tile. + *
    + * @param tileId The tile to check + * @return True if the tile is wallable. + */ + private boolean isWallable (int tileId) { + // Check list + if (tileId == Const.noTileId) + return false; + if (tiles[tileId].hasWalls() >= Const.maxTileWalls) + return false; + Range dirs = new Range(Direction.Begin, Direction.End, Direction.Step); + for (int dir ; (dir = dirs.get()) != Const.noTileId ; ) + if (isWallableDir(tileId, dir)) + return true; + return false; + } + + + /** + * This utility function create/allocate the tiles of the board and create + * the outer walls at the same time. + * + * @return The number of walls created from the utility. + */ private int createBasicTileWalls () { int tileCount =0; - // Create basic tiles and outer walls for (int i =0 ; i< tiles.length ; ++i) { - int r = Position.toRow(i); - int c = Position.toCol(i); - boolean up = (r == N-1) ? true : false; - boolean down = (r == 0 && c != 0) ? true : false; - boolean left = (c == 0) ? true : false; - boolean right = (c == N-1) ? true : false; + boolean up = isUpSentinel(i); + boolean down = isDownSentinel(i) && (i != 0); + boolean left = isLeftSentinel(i); + boolean right = isRightSentinel(i); tileCount += ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); tiles[i] = new Tile (i, up, down, left, right); } return tileCount; } - private int createInnerWalls (int wallPool) { - // Create inner walls for the rest of the desired walls + /** + * Create randomly a wall in the wallable selected tile. + * @param tileId The wallable tile to create the wall + */ + private void createInnerWall(int tileId) { + // Randomly pick a wallable direction in that tile. + ShuffledRange randDirections = new ShuffledRange(Direction.Begin, Direction.End, Direction.Step); + int dir; + do + dir = randDirections.get(); + while (!isWallableDir(tileId, dir)); + Position neighbor = new Position(Position.toRow(tileId), Position.toCol(tileId), dir); + tiles[tileId].setWall(dir); + tiles[neighbor.getId()].setWall(Direction.opposite(dir)); + } + + /** + * This utility creates the inner walls of the board. + * + * @param walls The number of walls to create + * @return The number of walls failed to create. + */ + private int createInnerWalls (int walls) { ShuffledRange randTiles = new ShuffledRange(0, N*N); - for (int tileId, i =0 ; i= 2); //XXX: Predicate : can put wall - // Randomly pick a not used direction in that tile - ShuffledRange randDirections = new ShuffledRange(Direction.Begin, Direction.Step, Direction.End); - Position tilePos = new Position(tileId); - int dir; - do - dir = randDirections.get(); - while (tiles[tileId].hasWall(dir)); - switch (dir) { - case Direction.UP: - tiles[tileId].setWalls(true, false, false, false); - tiles[Position.toID(tilePos.getRow()+1, tilePos.getCol())].setWalls(false, true, false, false); - break; - case Direction.DOWN: - tiles[tileId].setWalls(false, true, false, false); - tiles[Position.toID(tilePos.getRow()-1, tilePos.getCol())].setWalls(true, false, false, false); - break; - case Direction.LEFT: - tiles[tileId].setWalls(false, false, true, false); - tiles[Position.toID(tilePos.getRow(), tilePos.getCol()-1)].setWalls(false, false, false, true); - break; - case Direction.RIGHT: - tiles[tileId].setWalls(false, false, false, true); - tiles[Position.toID(tilePos.getRow(), tilePos.getCol()+1)].setWalls(false, false, true, false); - break; - } + if ((tileId = randTiles.get())== Const.noTileId) { + if (i == shuffleMark) // Wallable tiles exhausted. + return walls - i; + else { // Re-shuffle and continue. + randTiles = new ShuffledRange(0, N*N); + shuffleMark =i; + } + } + } while (!isWallable(tileId)); + createInnerWall(tileId); } return 0; } + /** + * Utility to get the body (center line) of the string representation of the tile. + * + * @param row What board's row to get. + * @param col What board's column to get. + * @param theseusTile The current tile of the Theseus. + * @param minotaurTile The current tile of the Minotaur. + * @return The body string + */ private String getTileBody (int row, int col, int theseusTile, int minotaurTile) { int tileId = Position.toID(row, col); boolean T = (tileId == theseusTile) ? true : false; @@ -227,6 +350,15 @@ public class Board { else return " "; } + /** + * Utility to render the 3 strings of the tile in the representation frame. + * + * @param frame Reference to the frame to print into. + * @param row The board's row to print. + * @param col The board's column to print. + * @param theseusTile The current tile of the Theseus. + * @param minotaurTile The current tile of the Minotaur. + */ private void renderTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile) { IntFunction toframe = (r)->{ return 2*r+1; }; @@ -237,7 +369,16 @@ public class Board { frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---" : "+ "; } - + /** + * Utility to render the 3 strings of the tile in the representation frame in + * the case the tile lies in the east wall. We call these tiles `sentinel tiles` + * + * @param frame Reference to the frame to print into. + * @param row The board's row to print. + * @param col The board's column to print. + * @param theseusTile The current tile of the Theseus. + * @param minotaurTile The current tile of the Minotaur. + */ private void renderSentinelTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile ) { IntFunction toframe = (r)->{ return 2*r+1; }; @@ -248,6 +389,15 @@ public class Board { + (tiles[tileId].hasWall(Direction.RIGHT)? "|" : " "); frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---+" : "+ +"; } + /** @} */ + + /** @name Neighbor access lambdas */ + /** @{ */ + private IntFunction leftTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)-1); }; + private IntFunction rightTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)+1); }; + private IntFunction upTileId = (id) -> { return Position.toID(Position.toRow(id)+1, Position.toCol(id) ); }; + private IntFunction downTileId = (id) -> { return Position.toID(Position.toRow(id)-1, Position.toCol(id) ); }; + /** @} */ /** @name Class data */ /** @{ */ diff --git a/src/net/hoo2/auth/labyrinth/Common.java b/src/net/hoo2/auth/labyrinth/Common.java index d05e017..d0ba3c5 100644 --- a/src/net/hoo2/auth/labyrinth/Common.java +++ b/src/net/hoo2/auth/labyrinth/Common.java @@ -9,15 +9,19 @@ package net.hoo2.auth.labyrinth; import java.util.ArrayList; import java.util.Collections; +/** + * Class to hold constant values for entire application + */ class Const { - static final int noSupply =-1; - static final int noTileId =-1; + static final int maxTileWalls = 2; /**< Number of maximum walls for each tile on the board */ + static final int noSupply =-1; /**< Number to indicate the absent of supply */ + static final int noTileId =-1; /**< Number to indicate wrong tileId */ } /** * Application wide object to hold settings like values for the session. */ class Session { - static int boardSize = 15; /**@< Default board's size (if no one set it via command line) */ + static int boardSize = 15; /**< Default board's size (if no one set it via command line) */ } /** @@ -28,9 +32,16 @@ class Direction { static final int RIGHT =3; /**< East direction */ static final int DOWN =5; /**< South direction */ static final int LEFT =7; /**< West direction */ - static final int Begin =1; - static final int End =8; - static final int Step =2; + static final int Begin =1; /**< Iterator style begin of range direction (starting north) */ + static final int End =8; /**< Iterator style end of range direction (one place after the last) */ + static final int Step =2; /**< Step for iterator style direction */ + + /** + * Utility to get the opposite + * @param direction Input direction + * @return The opposite direction + */ + static int opposite (int direction) { return (direction+4)%End; } } /** @@ -45,11 +56,11 @@ class Direction { class Position { /** - * Basic constructor from col-row coordinates + * Basic constructor from row-column coordinates * @param row The row coordinate * @param col The column coordinate */ - protected Position(int row, int col) { + Position(int row, int col) { this.id = toID(row, col); } @@ -57,15 +68,33 @@ class Position { * Basic constructor from Id * @param tileId The id of tile */ - protected Position(int tileId) { + Position(int tileId) { this.id = tileId; } + /** + * Constructor from row-column coordinates and a direction. + * + * This constructor creates a position relative to coordinates. + * + * @param row The row coordinate + * @param col The column coordinate + * @param direction The direction + */ + Position(int row, int col, int direction) { + switch (direction) { + case Direction.UP: this.id = toID(row+1, col); break; + case Direction.DOWN: this.id = toID(row-1, col); break; + case Direction.LEFT: this.id = toID(row, col-1); break; + case Direction.RIGHT:this.id = toID(row, col+1); break; + } + } + /** @name non-static API */ /** @{ */ - protected int getRow() { return toRow(id); } /**< Read access to virtual row coordinate */ - protected int getCol() { return toCol(id); } /**< Read access to virtual column coordinate */ - protected int getId() { return id; } /**< Read access to id coordinate */ + int getRow() { return toRow(id); } /**< Read access to virtual row coordinate */ + int getCol() { return toCol(id); } /**< Read access to virtual column coordinate */ + int getId() { return id; } /**< Read access to id coordinate */ /** @} */ /** @name Static convention utilities */ @@ -76,7 +105,7 @@ class Position { * @param col The column coordinate * @return The converted value */ - protected static int toID(int row, int col) { + static int toID(int row, int col) { return row * Session.boardSize + col; } @@ -85,7 +114,7 @@ class Position { * @param id The id coordinate * @return The row coordinate */ - protected static int toRow(int id){ + static int toRow(int id){ return id / Session.boardSize; } /** @@ -93,7 +122,7 @@ class Position { * @param id The id coordinate * @return The column coordinate */ - protected static int toCol(int id) { + static int toCol(int id) { return id % Session.boardSize; } /** @} */ @@ -104,36 +133,42 @@ class Position { /** @} */ } -class ShuffledRange { - - ShuffledRange() { - numbers = new ArrayList(); - } - - ShuffledRange(int begin, int end) { +/** + * Class to create ranges of numbers + */ +class Range { + /** + * Create the range [begin, end) + * @param begin The first item on the range + * @param end The item after the last on the range + */ + Range (int begin, int end) { numbers = new ArrayList(); - init (begin, end); + init (begin, end, 1); } - - ShuffledRange(int begin, int step, int end) { + /** + * Create the range [begin, end) using step as interval between items. + * @param begin The first item on the range + * @param end The item after the last on the range + * @param step The interval between items + */ + Range(int begin, int end, int step) { numbers = new ArrayList(); - init (begin, step, end); - } - - void init (int begin, int end) { - numbers.clear(); - for (int i=begin ; i numbers; + protected ArrayList numbers; /**< handle to range */ +} + +/** + * Class to create shuffled ranges of numbers + */ +class ShuffledRange extends Range { + /** + * Create a shuffled version of range [begin, end) + * @param begin The first item on the range + * @param end The item after the last on the range + */ + ShuffledRange(int begin, int end) { + super(begin, end); // Delegate + Collections.shuffle(numbers); + } + /** + * Create a shuffled version of the range [begin, end) + * using step as interval between items. + * + * @param begin The first item on the range + * @param end The item after the last on the range + * @param step The interval between items + */ + ShuffledRange(int begin, int end, int step) { + super(begin, end, step); // Delegate + Collections.shuffle(numbers); + } } diff --git a/src/net/hoo2/auth/labyrinth/Game.java b/src/net/hoo2/auth/labyrinth/Game.java index 900da80..3f6ce2d 100644 --- a/src/net/hoo2/auth/labyrinth/Game.java +++ b/src/net/hoo2/auth/labyrinth/Game.java @@ -13,12 +13,16 @@ package net.hoo2.auth.labyrinth; public class Game { public static void main(String[] args) { - // TODO Auto-generated method stub - System.out.println("Lets begin"); - Board board = new Board(7, 3, 42); - board.createBoard(0, Position.toID(3, 3)); - String[][] frame = board.getStringRepresentation(0, Position.toID(3, 3)); - board.printBoard(frame); + 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); + } + 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 236f403..cdfd98d 100644 --- a/src/net/hoo2/auth/labyrinth/Player.java +++ b/src/net/hoo2/auth/labyrinth/Player.java @@ -1,5 +1,48 @@ package net.hoo2.auth.labyrinth; + +/** + * @brief + * This class represents the game's player + */ class Player { + + /** + * @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 getPlayerId () { return playerId; } + String getName() { return name; } + Board getBoard () { return board; } + int getScore () { return score; } + int getX() { return x; } + int getY() { return y; } + + void setPlayerId(int id) { playerId = id; } + void setName(String name) { this.name = name; } + void setBoard (Board board){ this.board = board; } + void setScore(int score) { this.score = score; } + void setX(int x) { + assert (x >= 0 && x< Session.boardSize) : "X(column) coordinate must be in the range [0, Session.boardSize)"; + this.x = x; + } + void setY(int y) { + assert (y >= 0 && y< Session.boardSize) : "Y(row) coordinate must be in the range [0, Session.boardSize)"; + this.y = y; + } + /** @} */ + + /** @name Class data */ + /** @{ */ + private int playerId; /**< The unique identifier of the player */ + private String name; /**< The name of the player */ + private Board board; /**< Reference to the session's boards */ + private int score; /**< The current score of the player */ + private int x; /**< The column coordinate of the player on the board */ + private int y; /**< The row coordinate of the player on the board */ + /** @} */ } diff --git a/src/net/hoo2/auth/labyrinth/Supply.java b/src/net/hoo2/auth/labyrinth/Supply.java index 684a1cb..73d86c5 100644 --- a/src/net/hoo2/auth/labyrinth/Supply.java +++ b/src/net/hoo2/auth/labyrinth/Supply.java @@ -27,7 +27,7 @@ class Supply { * @param row The row coordinate to place the supply * @param col The column coordinate to place the supply */ - protected Supply(int id, int row, int col) { + Supply(int id, int row, int col) { // Boundary checks assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; assert (col >= 0 && col< Session.boardSize) : "Column coordinate must be in the range [0, Session.boardSize)"; @@ -45,7 +45,7 @@ class Supply { * @param id The Id of the created supply * @param tileId The linear combination of (row, column) */ - protected Supply(int id, int tileId) { + Supply(int id, int tileId) { // Boundary check assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; @@ -60,7 +60,7 @@ class Supply { /** * A deep copy constructor. */ - protected Supply (Supply s) { + Supply (Supply s) { this.supplyId = s.supplyId; this.x = s.x; this.y = s.y; @@ -73,20 +73,20 @@ class Supply { /** @{ */ /** @return the supplyId */ - protected int supplyId () { return supplyId; } + int supplyId () { return supplyId; } /** * Set the supplyId * @param sId The Id to set * @return The supplyId * @note This function also returns the supplyId to help in chained expressions. */ - protected int supplyId (int sID) { return supplyId = sID; } + int supplyId (int sID) { return supplyId = sID; } /** * @return the position of the supply as a Position object * @see Position */ - protected Position position () { return new Position (supplyTileId); } + Position position () { return new Position (supplyTileId); } /** * Set the position of the supply from a (row, column) pair @@ -96,7 +96,7 @@ class Supply { * @note This function also returns the Position to help in chained expressions. * @see Position */ - protected Position position (int row, int col) { + Position position (int row, int col) { // Boundary checks assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; assert (col >= 0 && col< Session.boardSize) : "Column coordinate must be in the range [0, Session.boardSize)"; @@ -115,7 +115,7 @@ class Supply { * @note This function also returns the Position to help in chained expressions. * @see Position */ - protected Position position (int tileId) { + Position position (int tileId) { // Boundary check assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; @@ -126,7 +126,6 @@ class Supply { this.supplyTileId = p.getId(); // =tileId; return p; } - /** @} */ /** @@ -136,23 +135,23 @@ class Supply { * We have added a bit of logic however, in order to make it a bit more safe. */ /** @{ */ - protected int getSupplyId () { return supplyId; } - protected int getX() { return x; } - protected int getY() { return y; } - protected int getSupplyTileId(){ return supplyTileId; } - - protected void setSupplyId(int Id) { supplyId = Id; } - protected void setX(int x) { - assert (x >= 0 && x< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)"; + int getSupplyId () { return supplyId; } + int getX() { return x; } + int getY() { return y; } + int getSupplyTileId(){ return supplyTileId; } + + void setSupplyId(int Id) { supplyId = Id; } + void setX(int x) { + assert (x >= 0 && x< Session.boardSize) : "X(column) coordinate must be in the range [0, Session.boardSize)"; this.x = x; this.supplyTileId = Position.toID(this.x, this.y); } - protected void setY(int y) { - assert (y >= 0 && y< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)"; + void setY(int y) { + assert (y >= 0 && y< Session.boardSize) : "Y(row) coordinate must be in the range [0, Session.boardSize)"; this.y = y; this.supplyTileId = Position.toID(this.x, this.y); } - protected void setSupplyTileId(int tileId) { + void setSupplyTileId(int tileId) { assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; this.supplyTileId = tileId; diff --git a/src/net/hoo2/auth/labyrinth/Tile.java b/src/net/hoo2/auth/labyrinth/Tile.java index 8e67601..9fbdfde 100644 --- a/src/net/hoo2/auth/labyrinth/Tile.java +++ b/src/net/hoo2/auth/labyrinth/Tile.java @@ -29,7 +29,7 @@ class Tile { * @param left The existence of wall left of the tile * @param right The existence of wall right of the tile */ - protected Tile(int row, int col, boolean up, boolean down, boolean left, boolean right) { + Tile(int row, int col, boolean up, boolean down, boolean left, boolean right) { // Boundary checks assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; assert (col >= 0 && col< Session.boardSize) : "Column coordinate must be in the range [0, Session.boardSize)"; @@ -53,7 +53,7 @@ class Tile { * @param left The existence of wall left of the tile * @param right The existence of wall right of the tile */ - protected Tile(int id, boolean up, boolean down, boolean left, boolean right) { + Tile(int id, boolean up, boolean down, boolean left, boolean right) { // Boundary check assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; @@ -70,7 +70,7 @@ class Tile { /** * A deep copy constructor. */ - protected Tile (Tile t) { + Tile (Tile t) { this.tileId = t.tileId; this.x = t.x; this.y = t.y; @@ -89,7 +89,7 @@ class Tile { * @return the position of the tile as a Position object * @see Position */ - protected Position position () { return new Position (tileId); } + Position position () { return new Position (tileId); } /** * Set the position of the tile from a (row, column) pair @@ -99,7 +99,7 @@ class Tile { * @note This function also returns the supplyId to help in chained expressions. * @see Position */ - protected Position position (int row, int col) { + Position position (int row, int col) { // Boundary checks assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; assert (col >= 0 && col< Session.boardSize) : "Column coordinate must be in the range [0, Session.boardSize)"; @@ -118,7 +118,7 @@ class Tile { * @note This function also returns the supplyId to help in chained expressions. * @see Position */ - protected Position position (int tileId) { + Position position (int tileId) { // Boundary check assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; @@ -131,21 +131,29 @@ class Tile { } /** - * Set the tile's walls - * @param up Request for north wall (winter is coming) - * @param down Request for south wall - * @param left Request for west wall - * @param right Request for east wall + * Sets the tile's wall in the requested direction. + * @param up The direction for the wall. */ - protected void setWalls (boolean up, boolean down, boolean left, boolean right) { - assert ( - ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)) <=2 - ) : "A tile can have at most 2 walls"; - - this.up = (up) ? true : this.up; - this.down = (down) ? true : this.down; - this.left = (left) ? true : this.left; - this.right = (right)? true : this.right; + void setWall (int direction) { + switch (direction) { + case Direction.UP: this.up = true; break; + case Direction.DOWN: this.down = true; break; + case Direction.LEFT: this.left = true; break; + case Direction.RIGHT:this.right = true; break; + } + } + + /** + * Clears the tile's wall in the requested direction. + * @param up The direction for the wall + */ + void clearWall (int direction) { + switch (direction) { + case Direction.UP: this.up = false; break; + case Direction.DOWN: this.down = false; break; + case Direction.LEFT: this.left = false; break; + case Direction.RIGHT:this.right = false; break; + } } /** @@ -153,7 +161,7 @@ class Tile { * @param direction The direction to check * @return True if there is a wall */ - protected boolean hasWall (int direction) { + boolean hasWall (int direction) { switch (direction) { case Direction.UP: return up; case Direction.RIGHT: return right; @@ -167,11 +175,11 @@ class Tile { * Checks if the tile has walls and return the number of them * @return The number of walls */ - protected int hasWalls () { + int hasWalls () { return ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); } - protected int hasSupply (Supply[] supplies) { + int hasSupply (Supply[] supplies) { for (Supply s: supplies) if (s.position().getId() == position().getId()) return s.getSupplyId(); @@ -186,35 +194,35 @@ class Tile { * We have added a bit of logic however, in order to make it a bit more safe. */ /** @{ */ - protected int getTileId () { return tileId; } - protected int getX () { return x; } - protected int getY () { return y; } - protected boolean getUp () { return up; } - protected boolean getDown () { return down; } - protected boolean getLeft () { return left; } - protected boolean getRight () { return right; } - - protected void setTileId(int tileId) { + int getTileId () { return tileId; } + int getX () { return x; } + int getY () { return y; } + boolean getUp () { return up; } + boolean getDown () { return down; } + boolean getLeft () { return left; } + boolean getRight () { return right; } + + void setTileId(int tileId) { assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) : "TileId must be in the range of [0, Session.boardSize^2)"; this.tileId = tileId; this.x = Position.toCol(tileId); this.y = Position.toRow(tileId); } - protected void setX(int x) { - assert (x >= 0 && x< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)"; + void setX(int x) { + assert (x >= 0 && x< Session.boardSize) : "X(column) coordinate must be in the range [0, Session.boardSize)"; this.x = x; this.tileId = Position.toID(this.x, this.y); } - protected void setY(int y) { - assert (y >= 0 && y< Session.boardSize) : "Y coordinate must be in the range [0, Session.boardSize)"; + void setY(int y) { + assert (y >= 0 && y< Session.boardSize) : "Y(row) coordinate must be in the range [0, Session.boardSize)"; this.y = y; this.tileId = Position.toID(this.x, this.y); } - protected void setUp(boolean up) { this.up = up; } - protected void setDown(boolean down) { this.down = down; } - protected void setRight(boolean right) { this.right = right; } - protected void setLeft(boolean left) { this.left = left; } + void setUp(boolean up) { this.up = up; } + void setDown(boolean down) { this.down = down; } + void setRight(boolean right) { this.right = right; } + void setLeft(boolean left) { this.left = left; } /** @} */ /** @name Class data */