@@ -16,14 +16,14 @@ import java.util.function.IntFunction; | |||||
* The board is the square arrangement of the tiles. This class is also | * The board is the square arrangement of the tiles. This class is also | ||||
* the owner of the tile and supply objects. | * the owner of the tile and supply objects. | ||||
*/ | */ | ||||
public class Board { | |||||
class Board { | |||||
/** @name Constructors */ | /** @name Constructors */ | ||||
/** @{ */ | /** @{ */ | ||||
/** | /** | ||||
* The empty constructor for default initialization | * The empty constructor for default initialization | ||||
*/ | */ | ||||
protected Board() { | |||||
Board() { | |||||
this.N = this.S = this.W = 0; | this.N = this.S = this.W = 0; | ||||
this.tiles = null; | this.tiles = null; | ||||
this.supplies =null; | this.supplies =null; | ||||
@@ -35,7 +35,7 @@ public class Board { | |||||
* @param S The number of supplies on the board | * @param S The number of supplies on the board | ||||
* @param W The number of walls 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 ) | 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]"; | : "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 | * 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... | * 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 | // Copy primitives | ||||
this.N = b.N; | this.N = b.N; | ||||
this.S = b.S; | 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<supplies.length ; ++i) { | |||||
do | |||||
tileId = rand.get(); | |||||
while (tileId == theseusTile || tileId == minotaurTile); | |||||
supplies[i] = new Supply(i, tileId); | |||||
} | |||||
} | |||||
protected void createBoard(int theseusTile, int minotaurTile) { | |||||
/** | |||||
* Creates the board with all the requested walls and supplies. | |||||
* | |||||
* @param theseusTile | |||||
* @param minotaurTile | |||||
*/ | |||||
void createBoard(int theseusTile, int minotaurTile) throws Exception { | |||||
createTiles(); | createTiles(); | ||||
createSupplies(theseusTile, minotaurTile); | createSupplies(theseusTile, minotaurTile); | ||||
} | } | ||||
protected String[][] getStringRepresentation(int theseusTile, int minotaurTile) { | |||||
/** | |||||
* Returns a 2-D array with the string representation of the board. | |||||
* | |||||
* The rows of the array represent the Y-coordinate and the columns the X-coordinate. | |||||
* The only difference is that between each row there is an extra row with the possible | |||||
* walls. This way the number of rows of the returning array are 2N+1 and the number of | |||||
* columns N+1.\n | |||||
* So each tile of the board is represented by 3 strings. One for the north wall, one for | |||||
* the body and one for the south wall. | |||||
* | |||||
* @param theseusTile The current Theseus tile | |||||
* @param minotaurTile The current Minotaur tile | |||||
* @return The string representation of the board | |||||
*/ | |||||
String[][] getStringRepresentation(int theseusTile, int minotaurTile) { | |||||
String[][] frame = new String[2*N+1][N]; | String[][] frame = new String[2*N+1][N]; | ||||
for (int row=0 ; row<N ; ++row) { | for (int row=0 ; row<N ; ++row) { | ||||
@@ -106,16 +110,22 @@ public class Board { | |||||
return frame; | return frame; | ||||
} | } | ||||
protected void printBoard (String[][] sBoard) { | |||||
/** | |||||
* Print board utility. | |||||
* @param sBoard Reference to string representation of the board to print. | |||||
* | |||||
* @note | |||||
* As the lower row addresses of the string representation of the board contain | |||||
* the south rows, in order to view the board correctly we have to print the rows | |||||
* in the opposite order. | |||||
*/ | |||||
void printBoard (String[][] sBoard) { | |||||
for (int i=sBoard.length-1 ; i>=0 ; --i) { | for (int i=sBoard.length-1 ; i>=0 ; --i) { | ||||
for (String it : sBoard[i]) | for (String it : sBoard[i]) | ||||
System.out.print(it); | System.out.print(it); | ||||
System.out.println(); | 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 :( | * 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". | * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure". | ||||
* <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a> | * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a> | ||||
* @return Reference to inner tiles array. | * @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". | * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure". | ||||
* <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a> | * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a> | ||||
* @return Reference to inner supplies array. | * @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. | * @param tiles Reference to tiles that we want to act as replacement for the inner tiles array. | ||||
* @note Use with care. | * @note Use with care. | ||||
* Any call to this function will probably add memory for the garbage collector. | * 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. | * @param supplies Reference to supplies that we want to act as replacement for the inner supplies array. | ||||
* @note Use with care. | * @note Use with care. | ||||
* Any call to this function will probably add memory for the garbage collector. | * 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<supplies.length ; ++i) { | |||||
// Pick a tile as long as there is no player in it | |||||
do | |||||
tileId = rand.get(); | |||||
while (tileId == theseusTile || tileId == minotaurTile); | |||||
supplies[i] = new Supply(i, tileId); | |||||
} | |||||
} | |||||
/** @name Sentinel predicates */ | |||||
/** @{ */ | |||||
private boolean isLeftSentinel (int tileId) { return (Position.toCol(tileId) == 0); } | |||||
private boolean isRightSentinel (int tileId) { return (Position.toCol(tileId) == N-1); } | |||||
private boolean isUpSentinel (int tileId) { return (Position.toRow(tileId) == N-1); } | |||||
private boolean isDownSentinel (int tileId) { return (Position.toRow(tileId) == 0); } | |||||
/** @} */ | /** @} */ | ||||
/** | |||||
* Predicate to check if a tile direction is `Wallable`. | |||||
* | |||||
* A `wallable` direction is a tile direction where: | |||||
* <ul> | |||||
* <li>The wall is not the DOWN wall from tile (0, 0). | |||||
* <li>There is not already a wall in the desired direction. (Implies no sentinel tile). | |||||
* <li>The neighbor in this direction has at most `Const.maxTileWalls -1` walls. | |||||
* </ul> | |||||
* | |||||
* @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: | |||||
* <ul> | |||||
* <li>The tile has at most `Const.maxTileWalls -1` walls. | |||||
* <li>There is at least one wallable direction on the tile. | |||||
* </ul> | |||||
* @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 () { | private int createBasicTileWalls () { | ||||
int tileCount =0; | int tileCount =0; | ||||
// Create basic tiles and outer walls | |||||
for (int i =0 ; i< tiles.length ; ++i) { | 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)); | tileCount += ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); | ||||
tiles[i] = new Tile (i, up, down, left, right); | tiles[i] = new Tile (i, up, down, left, right); | ||||
} | } | ||||
return tileCount; | 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); | ShuffledRange randTiles = new ShuffledRange(0, N*N); | ||||
for (int tileId, i =0 ; i<wallPool ; ++i) { | |||||
// randomly pick a tile with less than 2 walls | |||||
for (int tileId, i =0, shuffleMark =0 ; i<walls ; ++i) { | |||||
// randomly pick a wallable tile. | |||||
do { | do { | ||||
tileId = randTiles.get(); | |||||
if (tileId == Const.noTileId) | |||||
return 0; | |||||
} while (tiles[tileId].hasWalls() >= 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; | 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) { | private String getTileBody (int row, int col, int theseusTile, int minotaurTile) { | ||||
int tileId = Position.toID(row, col); | int tileId = Position.toID(row, col); | ||||
boolean T = (tileId == theseusTile) ? true : false; | boolean T = (tileId == theseusTile) ? true : false; | ||||
@@ -227,6 +350,15 @@ public class Board { | |||||
else return " "; | 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) { | private void renderTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile) { | ||||
IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | ||||
@@ -237,7 +369,16 @@ public class Board { | |||||
frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---" : "+ "; | 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 ) { | private void renderSentinelTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile ) { | ||||
IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | ||||
@@ -248,6 +389,15 @@ public class Board { | |||||
+ (tiles[tileId].hasWall(Direction.RIGHT)? "|" : " "); | + (tiles[tileId].hasWall(Direction.RIGHT)? "|" : " "); | ||||
frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---+" : "+ +"; | frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---+" : "+ +"; | ||||
} | } | ||||
/** @} */ | |||||
/** @name Neighbor access lambdas */ | |||||
/** @{ */ | |||||
private IntFunction<Integer> leftTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)-1); }; | |||||
private IntFunction<Integer> rightTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)+1); }; | |||||
private IntFunction<Integer> upTileId = (id) -> { return Position.toID(Position.toRow(id)+1, Position.toCol(id) ); }; | |||||
private IntFunction<Integer> downTileId = (id) -> { return Position.toID(Position.toRow(id)-1, Position.toCol(id) ); }; | |||||
/** @} */ | |||||
/** @name Class data */ | /** @name Class data */ | ||||
/** @{ */ | /** @{ */ | ||||
@@ -9,15 +9,19 @@ package net.hoo2.auth.labyrinth; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
/** | |||||
* Class to hold constant values for entire application | |||||
*/ | |||||
class Const { | 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. | * Application wide object to hold settings like values for the session. | ||||
*/ | */ | ||||
class 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 RIGHT =3; /**< East direction */ | ||||
static final int DOWN =5; /**< South direction */ | static final int DOWN =5; /**< South direction */ | ||||
static final int LEFT =7; /**< West 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 { | class Position { | ||||
/** | /** | ||||
* Basic constructor from col-row coordinates | |||||
* Basic constructor from row-column coordinates | |||||
* @param row The row coordinate | * @param row The row coordinate | ||||
* @param col The column coordinate | * @param col The column coordinate | ||||
*/ | */ | ||||
protected Position(int row, int col) { | |||||
Position(int row, int col) { | |||||
this.id = toID(row, col); | this.id = toID(row, col); | ||||
} | } | ||||
@@ -57,15 +68,33 @@ class Position { | |||||
* Basic constructor from Id | * Basic constructor from Id | ||||
* @param tileId The id of tile | * @param tileId The id of tile | ||||
*/ | */ | ||||
protected Position(int tileId) { | |||||
Position(int tileId) { | |||||
this.id = 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 */ | /** @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 */ | /** @name Static convention utilities */ | ||||
@@ -76,7 +105,7 @@ class Position { | |||||
* @param col The column coordinate | * @param col The column coordinate | ||||
* @return The converted value | * @return The converted value | ||||
*/ | */ | ||||
protected static int toID(int row, int col) { | |||||
static int toID(int row, int col) { | |||||
return row * Session.boardSize + col; | return row * Session.boardSize + col; | ||||
} | } | ||||
@@ -85,7 +114,7 @@ class Position { | |||||
* @param id The id coordinate | * @param id The id coordinate | ||||
* @return The row coordinate | * @return The row coordinate | ||||
*/ | */ | ||||
protected static int toRow(int id){ | |||||
static int toRow(int id){ | |||||
return id / Session.boardSize; | return id / Session.boardSize; | ||||
} | } | ||||
/** | /** | ||||
@@ -93,7 +122,7 @@ class Position { | |||||
* @param id The id coordinate | * @param id The id coordinate | ||||
* @return The column coordinate | * @return The column coordinate | ||||
*/ | */ | ||||
protected static int toCol(int id) { | |||||
static int toCol(int id) { | |||||
return id % Session.boardSize; | return id % Session.boardSize; | ||||
} | } | ||||
/** @} */ | /** @} */ | ||||
@@ -104,36 +133,42 @@ class Position { | |||||
/** @} */ | /** @} */ | ||||
} | } | ||||
class ShuffledRange { | |||||
ShuffledRange() { | |||||
numbers = new ArrayList<Integer>(); | |||||
} | |||||
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<Integer>(); | numbers = new ArrayList<Integer>(); | ||||
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<Integer>(); | numbers = new ArrayList<Integer>(); | ||||
init (begin, step, end); | |||||
} | |||||
void init (int begin, int end) { | |||||
numbers.clear(); | |||||
for (int i=begin ; i<end ; ++i) | |||||
numbers.add(i); | |||||
Collections.shuffle(numbers); | |||||
init (begin, end, step); | |||||
} | } | ||||
void init (int begin, int step, int end) { | |||||
/** | |||||
* Common utility to create the range for all constructors | |||||
*/ | |||||
private void init (int begin, int end, int step) { | |||||
numbers.clear(); | numbers.clear(); | ||||
for (int i=begin ; i<end ; i+=step) | for (int i=begin ; i<end ; i+=step) | ||||
numbers.add(i); | numbers.add(i); | ||||
Collections.shuffle(numbers); | |||||
} | } | ||||
/** | |||||
* Extract and return the first item from the range. | |||||
* @return The first item of the range or Const.noTileId if there is none. | |||||
*/ | |||||
int get () { | int get () { | ||||
try { | try { | ||||
return numbers.remove(0); | return numbers.remove(0); | ||||
@@ -143,5 +178,32 @@ class ShuffledRange { | |||||
} | } | ||||
} | } | ||||
private ArrayList<Integer> numbers; | |||||
protected ArrayList<Integer> 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); | |||||
} | |||||
} | } |
@@ -13,12 +13,16 @@ package net.hoo2.auth.labyrinth; | |||||
public class Game { | public class Game { | ||||
public static void main(String[] args) { | 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,5 +1,48 @@ | |||||
package net.hoo2.auth.labyrinth; | package net.hoo2.auth.labyrinth; | ||||
/** | |||||
* @brief | |||||
* This class represents the game's player | |||||
*/ | |||||
class 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 */ | |||||
/** @} */ | |||||
} | } |
@@ -27,7 +27,7 @@ class Supply { | |||||
* @param row The row coordinate to place the supply | * @param row The row coordinate to place the supply | ||||
* @param col The column 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 | // Boundary checks | ||||
assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; | 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)"; | 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 id The Id of the created supply | ||||
* @param tileId The linear combination of (row, column) | * @param tileId The linear combination of (row, column) | ||||
*/ | */ | ||||
protected Supply(int id, int tileId) { | |||||
Supply(int id, int tileId) { | |||||
// Boundary check | // Boundary check | ||||
assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "TileId must be in the range of [0, Session.boardSize^2)"; | ||||
@@ -60,7 +60,7 @@ class Supply { | |||||
/** | /** | ||||
* A deep copy constructor. | * A deep copy constructor. | ||||
*/ | */ | ||||
protected Supply (Supply s) { | |||||
Supply (Supply s) { | |||||
this.supplyId = s.supplyId; | this.supplyId = s.supplyId; | ||||
this.x = s.x; | this.x = s.x; | ||||
this.y = s.y; | this.y = s.y; | ||||
@@ -73,20 +73,20 @@ class Supply { | |||||
/** @{ */ | /** @{ */ | ||||
/** @return the supplyId */ | /** @return the supplyId */ | ||||
protected int supplyId () { return supplyId; } | |||||
int supplyId () { return supplyId; } | |||||
/** | /** | ||||
* Set the supplyId | * Set the supplyId | ||||
* @param sId The Id to set | * @param sId The Id to set | ||||
* @return The supplyId | * @return The supplyId | ||||
* @note This function also returns the supplyId to help in chained expressions. | * @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 | * @return the position of the supply as a Position object | ||||
* @see Position | * @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 | * 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. | * @note This function also returns the Position to help in chained expressions. | ||||
* @see Position | * @see Position | ||||
*/ | */ | ||||
protected Position position (int row, int col) { | |||||
Position position (int row, int col) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; | 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)"; | 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. | * @note This function also returns the Position to help in chained expressions. | ||||
* @see Position | * @see Position | ||||
*/ | */ | ||||
protected Position position (int tileId) { | |||||
Position position (int tileId) { | |||||
// Boundary check | // Boundary check | ||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "TileId must be in the range of [0, Session.boardSize^2)"; | ||||
@@ -126,7 +126,6 @@ class Supply { | |||||
this.supplyTileId = p.getId(); // =tileId; | this.supplyTileId = p.getId(); // =tileId; | ||||
return p; | 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. | * 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.x = x; | ||||
this.supplyTileId = Position.toID(this.x, this.y); | 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.y = y; | ||||
this.supplyTileId = Position.toID(this.x, this.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)) | assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "TileId must be in the range of [0, Session.boardSize^2)"; | ||||
this.supplyTileId = tileId; | this.supplyTileId = tileId; | ||||
@@ -29,7 +29,7 @@ class Tile { | |||||
* @param left The existence of wall left of the tile | * @param left The existence of wall left of the tile | ||||
* @param right The existence of wall right 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 | // Boundary checks | ||||
assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; | 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)"; | 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 left The existence of wall left of the tile | ||||
* @param right The existence of wall right 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 | // Boundary check | ||||
assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "TileId must be in the range of [0, Session.boardSize^2)"; | ||||
@@ -70,7 +70,7 @@ class Tile { | |||||
/** | /** | ||||
* A deep copy constructor. | * A deep copy constructor. | ||||
*/ | */ | ||||
protected Tile (Tile t) { | |||||
Tile (Tile t) { | |||||
this.tileId = t.tileId; | this.tileId = t.tileId; | ||||
this.x = t.x; | this.x = t.x; | ||||
this.y = t.y; | this.y = t.y; | ||||
@@ -89,7 +89,7 @@ class Tile { | |||||
* @return the position of the tile as a Position object | * @return the position of the tile as a Position object | ||||
* @see Position | * @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 | * 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. | * @note This function also returns the supplyId to help in chained expressions. | ||||
* @see Position | * @see Position | ||||
*/ | */ | ||||
protected Position position (int row, int col) { | |||||
Position position (int row, int col) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (row >= 0 && row< Session.boardSize) : "Row coordinate must be in the range [0, Session.boardSize)"; | 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)"; | 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. | * @note This function also returns the supplyId to help in chained expressions. | ||||
* @see Position | * @see Position | ||||
*/ | */ | ||||
protected Position position (int tileId) { | |||||
Position position (int tileId) { | |||||
// Boundary check | // Boundary check | ||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "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 | * @param direction The direction to check | ||||
* @return True if there is a wall | * @return True if there is a wall | ||||
*/ | */ | ||||
protected boolean hasWall (int direction) { | |||||
boolean hasWall (int direction) { | |||||
switch (direction) { | switch (direction) { | ||||
case Direction.UP: return up; | case Direction.UP: return up; | ||||
case Direction.RIGHT: return right; | case Direction.RIGHT: return right; | ||||
@@ -167,11 +175,11 @@ class Tile { | |||||
* Checks if the tile has walls and return the number of them | * Checks if the tile has walls and return the number of them | ||||
* @return The number of walls | * @return The number of walls | ||||
*/ | */ | ||||
protected int hasWalls () { | |||||
int hasWalls () { | |||||
return ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); | 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) | for (Supply s: supplies) | ||||
if (s.position().getId() == position().getId()) | if (s.position().getId() == position().getId()) | ||||
return s.getSupplyId(); | 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. | * 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)) | assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | ||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | : "TileId must be in the range of [0, Session.boardSize^2)"; | ||||
this.tileId = tileId; | this.tileId = tileId; | ||||
this.x = Position.toCol(tileId); | this.x = Position.toCol(tileId); | ||||
this.y = Position.toRow(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.x = x; | ||||
this.tileId = Position.toID(this.x, this.y); | 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.y = y; | ||||
this.tileId = Position.toID(this.x, this.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 */ | /** @name Class data */ | ||||