WIP: 2nd draft of the board
This commit is contained in:
parent
c4bb683797
commit
737849c690
@ -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;
|
* Creates the board with all the requested walls and supplies.
|
||||||
wallPool -= createBasicTileWalls ();
|
*
|
||||||
createInnerWalls(wallPool);
|
* @param theseusTile
|
||||||
}
|
* @param minotaurTile
|
||||||
|
*/
|
||||||
protected void createSupplies(int theseusTile, int minotaurTile) {
|
void createBoard(int theseusTile, int minotaurTile) throws Exception {
|
||||||
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) {
|
|
||||||
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; }
|
int getN() { return N; }
|
||||||
protected int getS() { return S; }
|
int getS() { return S; }
|
||||||
protected int getW() { return W; }
|
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; }
|
void setN(int N) { this.N = N; }
|
||||||
protected void setS(int S) { this.S = S; }
|
void setS(int S) { this.S = S; }
|
||||||
protected void setW(int W) { this.W = W; }
|
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);
|
boolean up = isUpSentinel(i);
|
||||||
int c = Position.toCol(i);
|
boolean down = isDownSentinel(i) && (i != 0);
|
||||||
boolean up = (r == N-1) ? true : false;
|
boolean left = isLeftSentinel(i);
|
||||||
boolean down = (r == 0 && c != 0) ? true : false;
|
boolean right = isRightSentinel(i);
|
||||||
boolean left = (c == 0) ? true : false;
|
|
||||||
boolean right = (c == N-1) ? true : false;
|
|
||||||
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) {
|
for (int tileId, i =0, shuffleMark =0 ; i<walls ; ++i) {
|
||||||
// randomly pick a tile with less than 2 walls
|
// randomly pick a wallable tile.
|
||||||
do {
|
do {
|
||||||
tileId = randTiles.get();
|
if ((tileId = randTiles.get())== Const.noTileId) {
|
||||||
if (tileId == Const.noTileId)
|
if (i == shuffleMark) // Wallable tiles exhausted.
|
||||||
return 0;
|
return walls - i;
|
||||||
} while (tiles[tileId].hasWalls() >= 2); //XXX: Predicate : can put wall
|
else { // Re-shuffle and continue.
|
||||||
// Randomly pick a not used direction in that tile
|
randTiles = new ShuffledRange(0, N*N);
|
||||||
ShuffledRange randDirections = new ShuffledRange(Direction.Begin, Direction.Step, Direction.End);
|
shuffleMark =i;
|
||||||
Position tilePos = new Position(tileId);
|
}
|
||||||
int dir;
|
}
|
||||||
do
|
} while (!isWallable(tileId));
|
||||||
dir = randDirections.get();
|
createInnerWall(tileId);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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 maxTileWalls = 2; /**< Number of maximum walls for each tile on the board */
|
||||||
static final int noTileId =-1;
|
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 Begin =1; /**< Iterator style begin of range direction (starting north) */
|
||||||
static final int End =8;
|
static final int End =8; /**< Iterator style end of range direction (one place after the last) */
|
||||||
static final int Step =2;
|
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 */
|
int getRow() { return toRow(id); } /**< Read access to virtual row coordinate */
|
||||||
protected int getCol() { return toCol(id); } /**< Read access to virtual column coordinate */
|
int getCol() { return toCol(id); } /**< Read access to virtual column coordinate */
|
||||||
protected int getId() { return id; } /**< Read access to id 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 {
|
/**
|
||||||
|
* Class to create ranges of numbers
|
||||||
ShuffledRange() {
|
*/
|
||||||
|
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, 1);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
ShuffledRange(int begin, 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, end);
|
init (begin, end, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShuffledRange(int begin, int step, int end) {
|
/**
|
||||||
numbers = new ArrayList<Integer>();
|
* Common utility to create the range for all constructors
|
||||||
init (begin, step, end);
|
*/
|
||||||
}
|
private void init (int begin, int end, int step) {
|
||||||
|
|
||||||
void init (int begin, int end) {
|
|
||||||
numbers.clear();
|
|
||||||
for (int i=begin ; i<end ; ++i)
|
|
||||||
numbers.add(i);
|
|
||||||
Collections.shuffle(numbers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init (int begin, int step, int end) {
|
|
||||||
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
|
try {
|
||||||
System.out.println("Lets begin");
|
Board board = new Board(7, 3, 60);
|
||||||
Board board = new Board(7, 3, 42);
|
board.createBoard(0, Position.toID(3, 3));
|
||||||
board.createBoard(0, Position.toID(3, 3));
|
String[][] frame = board.getStringRepresentation(0, Position.toID(3, 3));
|
||||||
String[][] frame = board.getStringRepresentation(0, Position.toID(3, 3));
|
board.printBoard(frame);
|
||||||
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; }
|
int getSupplyId () { return supplyId; }
|
||||||
protected int getX() { return x; }
|
int getX() { return x; }
|
||||||
protected int getY() { return y; }
|
int getY() { return y; }
|
||||||
protected int getSupplyTileId(){ return supplyTileId; }
|
int getSupplyTileId(){ return supplyTileId; }
|
||||||
|
|
||||||
protected void setSupplyId(int Id) { supplyId = Id; }
|
void setSupplyId(int Id) { supplyId = Id; }
|
||||||
protected void setX(int x) {
|
void setX(int x) {
|
||||||
assert (x >= 0 && x< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)";
|
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) {
|
void setY(int y) {
|
||||||
assert (y >= 0 && y< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)";
|
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
|
* Sets the tile's wall in the requested direction.
|
||||||
* @param up Request for north wall (winter is coming)
|
* @param up The direction for the wall.
|
||||||
* @param down Request for south wall
|
|
||||||
* @param left Request for west wall
|
|
||||||
* @param right Request for east wall
|
|
||||||
*/
|
*/
|
||||||
protected void setWalls (boolean up, boolean down, boolean left, boolean right) {
|
void setWall (int direction) {
|
||||||
assert (
|
switch (direction) {
|
||||||
((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)) <=2
|
case Direction.UP: this.up = true; break;
|
||||||
) : "A tile can have at most 2 walls";
|
case Direction.DOWN: this.down = true; break;
|
||||||
|
case Direction.LEFT: this.left = true; break;
|
||||||
|
case Direction.RIGHT:this.right = true; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.up = (up) ? true : this.up;
|
/**
|
||||||
this.down = (down) ? true : this.down;
|
* Clears the tile's wall in the requested direction.
|
||||||
this.left = (left) ? true : this.left;
|
* @param up The direction for the wall
|
||||||
this.right = (right)? true : this.right;
|
*/
|
||||||
|
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; }
|
int getTileId () { return tileId; }
|
||||||
protected int getX () { return x; }
|
int getX () { return x; }
|
||||||
protected int getY () { return y; }
|
int getY () { return y; }
|
||||||
protected boolean getUp () { return up; }
|
boolean getUp () { return up; }
|
||||||
protected boolean getDown () { return down; }
|
boolean getDown () { return down; }
|
||||||
protected boolean getLeft () { return left; }
|
boolean getLeft () { return left; }
|
||||||
protected boolean getRight () { return right; }
|
boolean getRight () { return right; }
|
||||||
|
|
||||||
protected void setTileId(int tileId) {
|
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) {
|
void setX(int x) {
|
||||||
assert (x >= 0 && x< Session.boardSize) : "X coordinate must be in the range [0, Session.boardSize)";
|
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) {
|
void setY(int y) {
|
||||||
assert (y >= 0 && y< Session.boardSize) : "Y coordinate must be in the range [0, Session.boardSize)";
|
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; }
|
void setUp(boolean up) { this.up = up; }
|
||||||
protected void setDown(boolean down) { this.down = down; }
|
void setDown(boolean down) { this.down = down; }
|
||||||
protected void setRight(boolean right) { this.right = right; }
|
void setRight(boolean right) { this.right = right; }
|
||||||
protected void setLeft(boolean left) { this.left = left; }
|
void setLeft(boolean left) { this.left = left; }
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** @name Class data */
|
/** @name Class data */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user