@@ -1,14 +1,260 @@ | |||||
/** | |||||
* @file Board.java | |||||
* | |||||
* @author Christos Choutouridis AEM:8997 | |||||
* @email cchoutou@ece.auth.gr | |||||
*/ | |||||
package net.hoo2.auth.labyrinth; | package net.hoo2.auth.labyrinth; | ||||
import java.util.function.IntFunction; | |||||
/** | |||||
* @brief | |||||
* This class is the representation of the games's board | |||||
* | |||||
* The board is the square arrangement of the tiles. This class is also | |||||
* the owner of the tile and supply objects. | |||||
*/ | |||||
public class Board { | public class Board { | ||||
/** @name Constructors */ | |||||
/** @{ */ | |||||
/** | |||||
* The empty constructor for default initialization | |||||
*/ | |||||
protected Board() { | |||||
this.N = this.S = this.W = 0; | |||||
this.tiles = null; | |||||
this.supplies =null; | |||||
} | |||||
/** | |||||
* The main constructor for the application | |||||
* @param N The size of each edge of the board | |||||
* @param S The number of supplies on the board | |||||
* @param W The number of walls on the board | |||||
*/ | |||||
protected Board(int N, int S, int W) { | |||||
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]"; | |||||
this.N = Session.boardSize = N; | |||||
this.S = S; | |||||
this.W = W; | |||||
tiles = new Tile[N*N]; | |||||
supplies = new Supply[S]; | |||||
} | |||||
/** | |||||
* Deep copy constructor | |||||
* @param b The board to copy | |||||
* | |||||
* @note | |||||
* The lack of value semantics in java is (in author's opinion) one of the greatest | |||||
* weakness of the language and one of the reasons why it will never be a language | |||||
* to care about. To quote Alexander Stepanof's words in "elements of programming" section 1.5: | |||||
* "Assignment is a procedure that takes two objects of the same type and makes the first | |||||
* object equal to the second without modifying the second". | |||||
* In this class we try to cope with this situation knowing that we can not do anything about | |||||
* assignment operator. We just add value semantics to the copy constructor and go on with our lifes... | |||||
*/ | |||||
protected Board(Board b) { | |||||
// Copy primitives | |||||
this.N = b.N; | |||||
this.S = b.S; | |||||
this.W = b.W; | |||||
// Clone arrays | |||||
this.tiles = b.tiles.clone(); | |||||
this.supplies = b.supplies.clone(); | |||||
} | |||||
/** @} */ | |||||
/** @name Supply'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) { | |||||
createTiles(); | |||||
createSupplies(theseusTile, minotaurTile); | |||||
} | |||||
protected String[][] getStringRepresentation(int theseusTile, int minotaurTile) { | |||||
String[][] frame = new String[2*N+1][N]; | |||||
for (int row=0 ; row<N ; ++row) { | |||||
int col; | |||||
for (col =0 ; col<N-1 ; ++col) | |||||
renderTile(frame, row, col, theseusTile, minotaurTile); | |||||
renderSentinelTile(frame, row, col, theseusTile, minotaurTile); | |||||
} | |||||
return frame; | |||||
} | |||||
protected void printBoard (String[][] sBoard) { | |||||
for (int i=sBoard.length-1 ; i>=0 ; --i) { | |||||
for (String it : sBoard[i]) | |||||
System.out.print(it); | |||||
System.out.println(); | |||||
} | |||||
} | |||||
int size() { return N; } | int size() { return N; } | ||||
private int N; | |||||
private int S; | |||||
private int W; | |||||
private Tile[] tiles; | |||||
private Supply[] supplies; | |||||
/** @} */ | |||||
/** | |||||
* @name Accessor/Mutator interface | |||||
* @note | |||||
* 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; } | |||||
/** | |||||
* @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> | |||||
* @return Reference to inner tiles array. | |||||
*/ | |||||
protected Tile[] getTiles() { return tiles; } | |||||
/** | |||||
* @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> | |||||
* @return Reference to inner supplies array. | |||||
*/ | |||||
protected 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; } | |||||
/** | |||||
* @param tiles Reference to tiles that we want to act as replacement for the inner tiles array. | |||||
* @note Use with care. | |||||
* Any call to this function will probably add memory for the garbage collector. | |||||
*/ | |||||
protected void setTiles(Tile[] tiles) { this.tiles = tiles; } | |||||
/** | |||||
* @param supplies Reference to supplies that we want to act as replacement for the inner supplies array. | |||||
* @note Use with care. | |||||
* Any call to this function will probably add memory for the garbage collector. | |||||
*/ | |||||
protected void setSupplies(Supply[] supplies) { this.supplies= supplies; } | |||||
/** @} */ | |||||
private int createBasicTileWalls () { | |||||
int tileCount =0; | |||||
// Create basic tiles and outer walls | |||||
for (int i =0 ; i< tiles.length ; ++i) { | |||||
int r = Position.toRow(i); | |||||
int c = Position.toCol(i); | |||||
boolean up = (r == N-1) ? true : false; | |||||
boolean down = (r == 0 && c != 0) ? true : false; | |||||
boolean left = (c == 0) ? true : false; | |||||
boolean right = (c == N-1) ? true : false; | |||||
tileCount += ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); | |||||
tiles[i] = new Tile (i, up, down, left, right); | |||||
} | |||||
return tileCount; | |||||
} | |||||
private int createInnerWalls (int wallPool) { | |||||
// Create inner walls for the rest of the desired walls | |||||
ShuffledRange randTiles = new ShuffledRange(0, N*N); | |||||
for (int tileId, i =0 ; i<wallPool ; ++i) { | |||||
// randomly pick a tile with less than 2 walls | |||||
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; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
private String getTileBody (int row, int col, int theseusTile, int minotaurTile) { | |||||
int tileId = Position.toID(row, col); | |||||
boolean T = (tileId == theseusTile) ? true : false; | |||||
boolean M = (tileId == minotaurTile) ? true : false; | |||||
int S = tiles[tileId].hasSupply(supplies); | |||||
if (T && !M) return " T "; | |||||
else if (M && !T) return " M "; | |||||
else if (T && M) return "T+M"; | |||||
else if (S != Const.noSupply) | |||||
return String.format("s%02d", S+1); | |||||
else return " "; | |||||
} | |||||
private void renderTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile) { | |||||
IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | |||||
int tileId = Position.toID(row, col); | |||||
frame[toframe.apply(row)+1][col] = tiles[tileId].hasWall(Direction.UP) ? "+---" : "+ "; | |||||
frame[toframe.apply(row) ][col] = (tiles[tileId].hasWall(Direction.LEFT)? "|" : " ") | |||||
+ getTileBody(row, col, theseusTile, minotaurTile); | |||||
frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---" : "+ "; | |||||
} | |||||
private void renderSentinelTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile ) { | |||||
IntFunction<Integer> toframe = (r)->{ return 2*r+1; }; | |||||
int tileId = Position.toID(row, col); | |||||
frame[toframe.apply(row)+1][col] = tiles[tileId].hasWall(Direction.UP) ? "+---+" : "+ +"; | |||||
frame[toframe.apply(row) ][col] = (tiles[tileId].hasWall(Direction.LEFT)? "|" : " ") | |||||
+ getTileBody(row, col, theseusTile, minotaurTile) | |||||
+ (tiles[tileId].hasWall(Direction.RIGHT)? "|" : " "); | |||||
frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---+" : "+ +"; | |||||
} | |||||
/** @name Class data */ | |||||
/** @{ */ | |||||
private int N; /**< The size of each edge of the board */ | |||||
private int S; /**< The number of the supplies on the board */ | |||||
private int W; /**< The number of walls on the board */ | |||||
private Tile[] tiles; /**< Array to hold all the tiles for the board */ | |||||
private Supply[] supplies; /**< Array to hold all the supplies on the board */ | |||||
/** @} */ | |||||
} | } |
@@ -6,10 +6,17 @@ | |||||
*/ | */ | ||||
package net.hoo2.auth.labyrinth; | package net.hoo2.auth.labyrinth; | ||||
import java.util.ArrayList; | |||||
import java.util.Collections; | |||||
class Const { | |||||
static final int noSupply =-1; | |||||
static final int noTileId =-1; | |||||
} | |||||
/** | /** | ||||
* Application wide object to hold settings like values for the session. | * Application wide object to hold settings like values for the session. | ||||
*/ | */ | ||||
class Defaults { | |||||
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) */ | ||||
} | } | ||||
@@ -21,26 +28,29 @@ 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; | |||||
} | } | ||||
/** | /** | ||||
* @brief | * @brief | ||||
* An Application wide board position implementation holding just the coordinates | |||||
* An Application wide board position implementation holding just the id coordinate. | |||||
* | * | ||||
* Position is a helper class to enable us cope with the redundant position data (id and coordinates). | * Position is a helper class to enable us cope with the redundant position data (id and coordinates). | ||||
* This class provide both static conversion functionalities between id and coordinates | * This class provide both static conversion functionalities between id and coordinates | ||||
* and data representation in the coordinates system. | * and data representation in the coordinates system. | ||||
* For clarity we adopt a row-column naming convention. | |||||
*/ | */ | ||||
class Position { | class Position { | ||||
/** | /** | ||||
* Basic constructor from coordinates | |||||
* @param x The x coordinate | |||||
* @param y The y coordinate | |||||
* Basic constructor from col-row coordinates | |||||
* @param row The row coordinate | |||||
* @param col The column coordinate | |||||
*/ | */ | ||||
protected Position(int x, int y) { | |||||
this.x = x; | |||||
this.y = y; | |||||
protected Position(int row, int col) { | |||||
this.id = toID(row, col); | |||||
} | } | ||||
/** | /** | ||||
@@ -48,52 +58,90 @@ class Position { | |||||
* @param tileId The id of tile | * @param tileId The id of tile | ||||
*/ | */ | ||||
protected Position(int tileId) { | protected Position(int tileId) { | ||||
this.x = toX(tileId); | |||||
this.y = toY(tileId); | |||||
this.id = tileId; | |||||
} | } | ||||
/** @name non-static API */ | /** @name non-static API */ | ||||
/** @{ */ | /** @{ */ | ||||
protected int getX() { return x; } /**< Read access to x coordinate */ | |||||
protected int getY() { return y; } /**< Read access to y coordinate */ | |||||
protected int getID(){ return toID(x, y); } /**< Virtual read access to id coordinate */ | |||||
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 */ | |||||
/** @} */ | /** @} */ | ||||
/** @name Static convention utilities */ | /** @name Static convention utilities */ | ||||
/** @{ */ | /** @{ */ | ||||
/** | /** | ||||
* Takes x and y coordinates and return the calculated Id coordinate | |||||
* @param x The x coordinate | |||||
* @param y The y coordinate | |||||
* Takes row and column coordinates and return the calculated Id coordinate | |||||
* @param row The row coordinate | |||||
* @param col The column coordinate | |||||
* @return The converted value | * @return The converted value | ||||
*/ | */ | ||||
protected static int toID(int x, int y) { | |||||
return y * Defaults.boardSize + x; | |||||
protected static int toID(int row, int col) { | |||||
return row * Session.boardSize + col; | |||||
} | } | ||||
/** | /** | ||||
* Takes Id coordinate and return the corresponding x coordinate | |||||
* Takes Id coordinate and return the corresponding row coordinate | |||||
* @param id The id coordinate | * @param id The id coordinate | ||||
* @return The x coordinate | |||||
* @return The row coordinate | |||||
*/ | */ | ||||
protected static int toX(int id){ | |||||
return id % Defaults.boardSize; | |||||
protected static int toRow(int id){ | |||||
return id / Session.boardSize; | |||||
} | } | ||||
/** | /** | ||||
* Takes Id coordinate and return the corresponding y coordinate | |||||
* Takes Id coordinate and return the corresponding column coordinate | |||||
* @param id The id coordinate | * @param id The id coordinate | ||||
* @return The y coordinate | |||||
* @return The column coordinate | |||||
*/ | */ | ||||
protected static int toY(int id) { | |||||
return id / Defaults.boardSize; | |||||
protected static int toCol(int id) { | |||||
return id % Session.boardSize; | |||||
} | } | ||||
/** @} */ | /** @} */ | ||||
/** @name private data types */ | /** @name private data types */ | ||||
/** @{ */ | /** @{ */ | ||||
private int x; /**< The x coordinate of the constructed Position object */ | |||||
private int y; /**< The y coordinate of the constructed Position object */ | |||||
private int id; /**< The id coordinate of the constructed Position object */ | |||||
/** @} */ | /** @} */ | ||||
} | } | ||||
class ShuffledRange { | |||||
ShuffledRange() { | |||||
numbers = new ArrayList<Integer>(); | |||||
} | |||||
ShuffledRange(int begin, int end) { | |||||
numbers = new ArrayList<Integer>(); | |||||
init (begin, end); | |||||
} | |||||
ShuffledRange(int begin, int step, int end) { | |||||
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); | |||||
} | |||||
void init (int begin, int step, int end) { | |||||
numbers.clear(); | |||||
for (int i=begin ; i<end ; i+=step) | |||||
numbers.add(i); | |||||
Collections.shuffle(numbers); | |||||
} | |||||
int get () { | |||||
try { | |||||
return numbers.remove(0); | |||||
} | |||||
catch (IndexOutOfBoundsException e) { | |||||
return Const.noTileId; | |||||
} | |||||
} | |||||
private ArrayList<Integer> numbers; | |||||
} |
@@ -15,7 +15,10 @@ public class Game { | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
// TODO Auto-generated method stub | // TODO Auto-generated method stub | ||||
System.out.println("Lets begin"); | 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); | |||||
} | } | ||||
} | } |
@@ -21,39 +21,40 @@ class Supply { | |||||
/** @{ */ | /** @{ */ | ||||
/** | /** | ||||
* The main constructor of the Supply constructed from (x,y) | |||||
* The main constructor of the Supply constructed from (row,column) | |||||
* | * | ||||
* @param id The Id of the created supply | * @param id The Id of the created supply | ||||
* @param x The x coordinate to place the supply | |||||
* @param y The y coordinate to place the supply | |||||
* @param row The row coordinate to place the supply | |||||
* @param col The column coordinate to place the supply | |||||
*/ | */ | ||||
protected Supply(int id, int x, int y) { | |||||
protected Supply(int id, int row, int col) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Defaults.boardSize) : "Y coordinate must be in the range [0, Defaults.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)"; | |||||
// Initialization | // Initialization | ||||
this.supplyId =id; | |||||
this.x =x; | |||||
this.y =y; | |||||
this.supplyTileId = Position.toID(x, y); | |||||
this.supplyId =id; | |||||
this.x =col; | |||||
this.y =row; | |||||
this.supplyTileId = Position.toID(row, col); | |||||
} | } | ||||
/** | /** | ||||
* A second constructor of the Supply constructed from supplyTileId | * A second constructor of the Supply constructed from supplyTileId | ||||
* | * | ||||
* @param id The Id of the created supply | * @param id The Id of the created supply | ||||
* @param tileId The linear combination of (x, y) | |||||
* @param tileId The linear combination of (row, column) | |||||
*/ | */ | ||||
protected Supply(int id, int tileId) { | protected Supply(int id, int tileId) { | ||||
// Boundary check | // Boundary check | ||||
assert (id >= 0 && id <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
// Initialization | // Initialization | ||||
this.supplyId =id; | |||||
this.supplyId = id; | |||||
this.supplyTileId = tileId; | this.supplyTileId = tileId; | ||||
this.x = Position.toX(tileId); | |||||
this.y = Position.toY(tileId); | |||||
this.x = Position.toCol(tileId); | |||||
this.y = Position.toRow(tileId); | |||||
} | } | ||||
/** | /** | ||||
@@ -85,24 +86,25 @@ class Supply { | |||||
* @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 (x, y); } | |||||
protected Position position () { return new Position (supplyTileId); } | |||||
/** | /** | ||||
* Set the position of the supply from a (x, y) pair | |||||
* @param x The x coordinate of the tile | |||||
* @param y The y coordinate of the tile | |||||
* Set the position of the supply from a (row, column) pair | |||||
* @param row The row coordinate of the tile | |||||
* @param col The column coordinate of the tile | |||||
* @return the position of the supply as a Position object | * @return the position of the supply as a Position object | ||||
* @note This function also returns the supplyId 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 x, int y) { | |||||
protected Position position (int row, int col) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Defaults.boardSize) : "Y coordinate must be in the range [0, Defaults.boardSize)"; | |||||
Position p = new Position (x, y); | |||||
this.x = x; | |||||
this.y = y; | |||||
this.supplyTileId = p.getID(); | |||||
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)"; | |||||
Position p = new Position (row, col); | |||||
this.x = p.getCol(); // =col; | |||||
this.y = p.getRow(); // =row; | |||||
this.supplyTileId = p.getId(); | |||||
return p; | return p; | ||||
} | } | ||||
@@ -110,21 +112,20 @@ class Supply { | |||||
* Set the position of the supply from a tileId | * Set the position of the supply from a tileId | ||||
* @param tileId The tileId position | * @param tileId The tileId position | ||||
* @return The position of the supply as Position object | * @return The position of the supply as Position object | ||||
* @note This function also returns the supplyId to help in chained expressions. | |||||
* @note This function also returns the Position to help in chained expressions. | |||||
* @see Position | * @see Position | ||||
*/ | */ | ||||
protected int position (int tileId) { | |||||
protected Position position (int tileId) { | |||||
// Boundary check | // Boundary check | ||||
assert (tileId >= 0 && tileId <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
this.x = Position.toX(tileId); | |||||
this.y = Position.toY(tileId); | |||||
this.supplyTileId = tileId; | |||||
return supplyTileId; | |||||
} | |||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
/** @return The supplyTileId */ | |||||
protected int positionId () { return supplyTileId; } | |||||
Position p = new Position (tileId); | |||||
this.x = p.getCol(); | |||||
this.y = p.getRow(); | |||||
this.supplyTileId = p.getId(); // =tileId; | |||||
return p; | |||||
} | |||||
/** @} */ | /** @} */ | ||||
@@ -142,21 +143,21 @@ class Supply { | |||||
protected void setSupplyId(int Id) { supplyId = Id; } | protected void setSupplyId(int Id) { supplyId = Id; } | ||||
protected void setX(int x) { | protected void setX(int x) { | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Session.boardSize) : "X 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) { | protected void setY(int y) { | ||||
assert (y >= 0 && y< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (y >= 0 && y< Session.boardSize) : "X 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) { | protected void setSupplyTileId(int tileId) { | ||||
assert (tileId >= 0 && tileId <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
this.supplyTileId = tileId; | this.supplyTileId = tileId; | ||||
this.x = Position.toX(tileId); | |||||
this.y = Position.toY(tileId); | |||||
this.x = Position.toCol(tileId); | |||||
this.y = Position.toRow(tileId); | |||||
} | } | ||||
/** @} */ | /** @} */ | ||||
@@ -20,24 +20,24 @@ class Tile { | |||||
/** @{ */ | /** @{ */ | ||||
/** | /** | ||||
* The main constructor of the Tile constructed from (x,y) | |||||
* The main constructor of the Tile constructed from (row,column) | |||||
* | * | ||||
* @param x The x coordinate to place the Tile | |||||
* @param y The y coordinate to place the Tile | |||||
* @param row The row coordinate to place the Tile | |||||
* @param col The column coordinate to place the Tile | |||||
* @param up The existence of wall north of the tile | * @param up The existence of wall north of the tile | ||||
* @param down The existence of wall south of the tile | * @param down The existence of wall south of the 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 x, int y, boolean up, boolean down, boolean left, boolean right) { | |||||
protected Tile(int row, int col, boolean up, boolean down, boolean left, boolean right) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Defaults.boardSize) : "Y coordinate must be in the range [0, Defaults.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)"; | |||||
// Initialization | // Initialization | ||||
this.tileId = Position.toID(x, y); | |||||
this.x =x; | |||||
this.y =y; | |||||
this.tileId = Position.toID(row, col); | |||||
this.x =col; | |||||
this.y =row; | |||||
this.up = up; | this.up = up; | ||||
this.down = down; | this.down = down; | ||||
this.left = left; | this.left = left; | ||||
@@ -55,12 +55,12 @@ class Tile { | |||||
*/ | */ | ||||
protected Tile(int id, boolean up, boolean down, boolean left, boolean right) { | protected Tile(int id, boolean up, boolean down, boolean left, boolean right) { | ||||
// Boundary check | // Boundary check | ||||
assert (id >= 0 && id <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
assert (id >= 0 && id <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
// Initialization | // Initialization | ||||
this.tileId = id; | this.tileId = id; | ||||
this.x =Position.toX(id); | |||||
this.y =Position.toY(id); | |||||
this.x =Position.toCol(id); | |||||
this.y =Position.toRow(id); | |||||
this.up = up; | this.up = up; | ||||
this.down = down; | this.down = down; | ||||
this.left = left; | this.left = left; | ||||
@@ -89,24 +89,25 @@ 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 (x, y); } | |||||
protected Position position () { return new Position (tileId); } | |||||
/** | /** | ||||
* Set the position of the tile from a (x, y) pair | |||||
* @param x The x coordinate of the tile | |||||
* @param y The y coordinate of the tile | |||||
* Set the position of the tile from a (row, column) pair | |||||
* @param row The row coordinate of the tile | |||||
* @param col The column coordinate of the tile | |||||
* @return the position of the supply as a Position object | * @return the position of the supply as a Position object | ||||
* @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 x, int y) { | |||||
protected Position position (int row, int col) { | |||||
// Boundary checks | // Boundary checks | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Defaults.boardSize) : "Y coordinate must be in the range [0, Defaults.boardSize)"; | |||||
Position p = new Position (x, y); | |||||
this.x = x; | |||||
this.y = y; | |||||
this.tileId = p.getID(); | |||||
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)"; | |||||
Position p = new Position (row, col); | |||||
this.x = p.getCol(); // =col; | |||||
this.y = p.getRow(); // =row; | |||||
this.tileId = p.getId(); | |||||
return p; | return p; | ||||
} | } | ||||
@@ -117,18 +118,17 @@ 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 int position (int tileId) { | |||||
protected Position position (int tileId) { | |||||
// Boundary check | // Boundary check | ||||
assert (tileId >= 0 && tileId <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
this.x = Position.toX(tileId); | |||||
this.y = Position.toY(tileId); | |||||
this.tileId = tileId; | |||||
return tileId; | |||||
} | |||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
/** @return The tileId */ | |||||
protected int positionId () { return tileId; } | |||||
Position p = new Position (tileId); | |||||
this.x = p.getCol(); | |||||
this.y = p.getRow(); | |||||
this.tileId = p.getId(); // =tileId; | |||||
return p; | |||||
} | |||||
/** | /** | ||||
* Set the tile's walls | * Set the tile's walls | ||||
@@ -141,10 +141,11 @@ class Tile { | |||||
assert ( | assert ( | ||||
((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)) <=2 | ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)) <=2 | ||||
) : "A tile can have at most 2 walls"; | ) : "A tile can have at most 2 walls"; | ||||
this.up = up; | |||||
this.down = down; | |||||
this.left = left; | |||||
this.right = right; | |||||
this.up = (up) ? true : this.up; | |||||
this.down = (down) ? true : this.down; | |||||
this.left = (left) ? true : this.left; | |||||
this.right = (right)? true : this.right; | |||||
} | } | ||||
/** | /** | ||||
@@ -162,6 +163,20 @@ class Tile { | |||||
return false; | return false; | ||||
} | } | ||||
/** | |||||
* Checks if the tile has walls and return the number of them | |||||
* @return The number of walls | |||||
*/ | |||||
protected int hasWalls () { | |||||
return ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0)); | |||||
} | |||||
protected int hasSupply (Supply[] supplies) { | |||||
for (Supply s: supplies) | |||||
if (s.position().getId() == position().getId()) | |||||
return s.getSupplyId(); | |||||
return Const.noSupply; | |||||
} | |||||
/** @} */ | /** @} */ | ||||
/** | /** | ||||
@@ -180,19 +195,19 @@ class Tile { | |||||
protected boolean getRight () { return right; } | protected boolean getRight () { return right; } | ||||
protected void setTileId(int tileId) { | protected void setTileId(int tileId) { | ||||
assert (tileId >= 0 && tileId <= Position.toID(Defaults.boardSize-1, Defaults.boardSize-1)) | |||||
: "TileId must be in the range of [0, Defaults.boardSize^2)"; | |||||
assert (tileId >= 0 && tileId <= Position.toID(Session.boardSize-1, Session.boardSize-1)) | |||||
: "TileId must be in the range of [0, Session.boardSize^2)"; | |||||
this.tileId = tileId; | this.tileId = tileId; | ||||
this.x = Position.toX(tileId); | |||||
this.y = Position.toY(tileId); | |||||
this.x = Position.toCol(tileId); | |||||
this.y = Position.toRow(tileId); | |||||
} | } | ||||
protected void setX(int x) { | protected void setX(int x) { | ||||
assert (x >= 0 && x< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (x >= 0 && x< Session.boardSize) : "X 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) { | protected void setY(int y) { | ||||
assert (y >= 0 && y< Defaults.boardSize) : "X coordinate must be in the range [0, Defaults.boardSize)"; | |||||
assert (y >= 0 && y< Session.boardSize) : "Y 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); | ||||
} | } | ||||
@@ -208,8 +223,8 @@ class Tile { | |||||
* The unique identifier of the tile. This is the linear combination of | * The unique identifier of the tile. This is the linear combination of | ||||
* x and y coordinates of the tile | * x and y coordinates of the tile | ||||
*/ | */ | ||||
private int x; /**< The x coordinate of the tile as if the board lies in the 1st quadrant */ | |||||
private int y; /**< The y coordinate of the tile as if the board lies in the 1st quadrant */ | |||||
private int x; /**< The x coordinate(column) of the tile as if the board lies in the 1st quadrant */ | |||||
private int y; /**< The y coordinate(row) of the tile as if the board lies in the 1st quadrant */ | |||||
private boolean up; /**< Indicator of a wall in the north side of the tile */ | private boolean up; /**< Indicator of a wall in the north side of the tile */ | ||||
private boolean down; /**< Indicator of a wall in the south side of the tile */ | private boolean down; /**< Indicator of a wall in the south side of the tile */ | ||||
private boolean left; /**< Indicator of a wall in the left side of the tile */ | private boolean left; /**< Indicator of a wall in the left side of the tile */ | ||||