Refactor expandBoard() method
This commit is contained in:
@@ -1,12 +1,86 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a cardinal direction.
|
||||||
|
*
|
||||||
|
* This enumeration represents a cardinal direction (N, S, E, W, ...) as well as
|
||||||
|
* operations on cardinals, such as rotation and inverse cardinals.
|
||||||
|
*/
|
||||||
public enum Cardinal {
|
public enum Cardinal {
|
||||||
N,
|
N (0),
|
||||||
NE,
|
NE (1),
|
||||||
E,
|
E (2),
|
||||||
SE,
|
SE (3),
|
||||||
S,
|
S (4),
|
||||||
SW,
|
SW (5),
|
||||||
W,
|
W (6),
|
||||||
NW;
|
NW (7);
|
||||||
|
|
||||||
|
/** Integer representation of the cardinal (starting at 0 for North) */
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/** Private constructor for the enumeration */
|
||||||
|
private Cardinal(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the integer representation of the cardinal direction.
|
||||||
|
* @return the integer representing the cardinal direction
|
||||||
|
* (starting at 0 for North)
|
||||||
|
*/
|
||||||
|
public int asInt() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cardinal direction corresponding to the given integer.
|
||||||
|
* @param value integer representing a cardinal direction
|
||||||
|
* @return a cardinal corresponding to the integer parameter
|
||||||
|
* @throws IllegalArgumentException when the integer value is not valid
|
||||||
|
* (not in the range 0-7)
|
||||||
|
*/
|
||||||
|
public static Cardinal fromInt(int value) {
|
||||||
|
for (Cardinal cardinal : Cardinal.values()) {
|
||||||
|
if (cardinal.value == value) {
|
||||||
|
return cardinal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Invalid value: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the opposite cardinal direction.
|
||||||
|
* @return the opposite cardinal direction of this cardinal
|
||||||
|
*/
|
||||||
|
public Cardinal inverse() {
|
||||||
|
return fromInt((this.value + 4) % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the cardinal direction by a given number of steps.
|
||||||
|
* @param steps the number of steps to rotate (positive for clockwise,
|
||||||
|
* negative for counterclockwise)
|
||||||
|
* @return the new cardinal direction after rotation
|
||||||
|
* @throws IllegalArgumentException when the number of steps is not valid
|
||||||
|
* (not in the range -7 to 7)
|
||||||
|
*/
|
||||||
|
public Cardinal rotate(int steps) {
|
||||||
|
return fromInt((this.value + steps + 8) % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the cardinal direction 90 degrees clockwise.
|
||||||
|
* @return the new cardinal direction after a 90-degree clockwise rotation
|
||||||
|
*/
|
||||||
|
public Cardinal rotate90CW() {
|
||||||
|
return rotate(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the cardinal direction 90 degrees counterclockwise.
|
||||||
|
* @return the new cardinal direction after a 90-degree counterclockwise rotation
|
||||||
|
*/
|
||||||
|
public Cardinal rotate90CCW() {
|
||||||
|
return rotate(-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,15 +24,22 @@ public class GomokuBoard{
|
|||||||
test.get(1,1).setState(Color.BLACK);
|
test.get(1,1).setState(Color.BLACK);
|
||||||
System.out.println(test);
|
System.out.println(test);
|
||||||
System.out.println(test.getPlayableCells());
|
System.out.println(test.getPlayableCells());
|
||||||
test.expandBoard(Cardinal.SW);
|
|
||||||
test.expandBoard(Cardinal.SW);
|
System.out.println(Cardinal.NE.rotate90CW());
|
||||||
test.expandBoard(Cardinal.SW);
|
System.out.println(Cardinal.NE.rotate90CCW());
|
||||||
test.expandBoard(Cardinal.SW);
|
System.out.println(Cardinal.NE.rotate(1));
|
||||||
test.expandBoard(Cardinal.SW);
|
System.out.println(Cardinal.NE.rotate(-1));
|
||||||
test.expandBoard(Cardinal.SW);
|
System.out.println(Cardinal.NE.inverse());
|
||||||
test.expandBoard(Cardinal.SW);
|
|
||||||
|
System.out.println(test);
|
||||||
|
test.expandBoardv2(Cardinal.N);
|
||||||
|
System.out.println(test);
|
||||||
|
test.expandBoardv2(Cardinal.S);
|
||||||
|
System.out.println(test);
|
||||||
|
test.expandBoardv2(Cardinal.W);
|
||||||
|
System.out.println(test);
|
||||||
|
test.expandBoardv2(Cardinal.SE);
|
||||||
System.out.println(test);
|
System.out.println(test);
|
||||||
System.out.println(test.getPlayableCells());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------Constructors--------------------------
|
//------------------Constructors--------------------------
|
||||||
@@ -56,17 +63,17 @@ public class GomokuBoard{
|
|||||||
this.firstCell = new GomokuCell(Color.NIL);
|
this.firstCell = new GomokuCell(Color.NIL);
|
||||||
this.boardWidth = width;
|
this.boardWidth = width;
|
||||||
this.boardHeight = height;
|
this.boardHeight = height;
|
||||||
this.genCells(width, height, colors);
|
this.generateCells(width, height, colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method gen all cells in the board and link each other.
|
* This method generate all cells in the board and link each other.
|
||||||
* @param width Size of width.
|
* @param width Size of width.
|
||||||
* @param height Size of height.
|
* @param height Size of height.
|
||||||
* @param colors Array of Color.
|
* @param colors Array of Color.
|
||||||
*/
|
*/
|
||||||
private void genCells(int width, int height, Color[][] colors){
|
private void generateCells(int width, int height, Color[][] colors){
|
||||||
this.firstCell = new GomokuCell(colors == null ? Color.NIL : colors[0][0]);
|
this.firstCell = new GomokuCell(colors == null ? Color.NIL : colors[0][0]);
|
||||||
GomokuCell act = this.firstCell;
|
GomokuCell act = this.firstCell;
|
||||||
GomokuCell top = null;
|
GomokuCell top = null;
|
||||||
@@ -111,9 +118,9 @@ public class GomokuBoard{
|
|||||||
while (i != x || j != y){
|
while (i != x || j != y){
|
||||||
Cardinal c = Cardinal.SE;
|
Cardinal c = Cardinal.SE;
|
||||||
if (i < x) i++;
|
if (i < x) i++;
|
||||||
else c = Cardinal.E;
|
|
||||||
if (j < y) j++;
|
|
||||||
else c = Cardinal.S;
|
else c = Cardinal.S;
|
||||||
|
if (j < y) j++;
|
||||||
|
else c = Cardinal.E;
|
||||||
act = act.getNeighbour(c);
|
act = act.getNeighbour(c);
|
||||||
}
|
}
|
||||||
return act;
|
return act;
|
||||||
@@ -124,7 +131,7 @@ public class GomokuBoard{
|
|||||||
* This method return all cells in the board in the order.
|
* This method return all cells in the board in the order.
|
||||||
* @return All cells with a array 2D.
|
* @return All cells with a array 2D.
|
||||||
*/
|
*/
|
||||||
private GomokuCell[][] getAllsCells(){
|
private GomokuCell[][] getAllCells(){
|
||||||
GomokuCell[][] cells = new GomokuCell[this.boardHeight][this.boardWidth];
|
GomokuCell[][] cells = new GomokuCell[this.boardHeight][this.boardWidth];
|
||||||
GomokuCell act = this.firstCell;
|
GomokuCell act = this.firstCell;
|
||||||
GomokuCell nextLine = this.firstCell.getNeighbour(Cardinal.S);
|
GomokuCell nextLine = this.firstCell.getNeighbour(Cardinal.S);
|
||||||
@@ -148,7 +155,7 @@ public class GomokuBoard{
|
|||||||
|
|
||||||
public List<GomokuCell> getPlayableCells(){
|
public List<GomokuCell> getPlayableCells(){
|
||||||
List<GomokuCell> output = new ArrayList<>();
|
List<GomokuCell> output = new ArrayList<>();
|
||||||
for (GomokuCell[] line : this.getAllsCells()) {
|
for (GomokuCell[] line : this.getAllCells()) {
|
||||||
for (GomokuCell c : line) {
|
for (GomokuCell c : line) {
|
||||||
if (c.isPlayable() && c.getState() == Color.NIL)
|
if (c.isPlayable() && c.getState() == Color.NIL)
|
||||||
output.add(c);
|
output.add(c);
|
||||||
@@ -300,6 +307,95 @@ public class GomokuBoard{
|
|||||||
this.firstCell = newOrigin;
|
this.firstCell = newOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands the board in the specified direction.
|
||||||
|
* This method is used to add a new row, column, or both to the board.
|
||||||
|
* It creates new cells in the specified direction and links them to the existing cells.
|
||||||
|
* It also updates the board dimensions accordingly.
|
||||||
|
* @param direction The cardinal direction in which to expand the board.
|
||||||
|
* @see Cardinal
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
public void expandBoardv2(Cardinal direction) {
|
||||||
|
// for composed directions, expand in both components
|
||||||
|
// e.g. SE -> expand in S and E
|
||||||
|
if ((direction.asInt() % 2) != 0) {
|
||||||
|
// if the direction is not even, it is a composed direction
|
||||||
|
// call the same function in both components
|
||||||
|
this.expandBoardv2(direction.rotate(-1));
|
||||||
|
this.expandBoardv2(direction.rotate(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the suitable corner cell to expand from
|
||||||
|
Cardinal cornerCellDirection = direction.rotate(-1);
|
||||||
|
|
||||||
|
// move to the corner cell
|
||||||
|
// go to the center of the board
|
||||||
|
GomokuCell cornerCell = this.get(this.boardWidth / 2, this.boardHeight / 2);
|
||||||
|
GomokuCell nextCell;
|
||||||
|
// move while possible to the desired corner of the board
|
||||||
|
do {
|
||||||
|
nextCell = cornerCell.getNeighbour(cornerCellDirection);
|
||||||
|
// if the next cell is null, then attempt to move
|
||||||
|
// in the original direction
|
||||||
|
if (nextCell == null) {
|
||||||
|
cornerCellDirection = direction;
|
||||||
|
nextCell = cornerCell.getNeighbour(cornerCellDirection);
|
||||||
|
// if we already reached the end of the board, try the
|
||||||
|
// direction perpendicular to the original direction
|
||||||
|
if (nextCell == null) {
|
||||||
|
cornerCellDirection = direction.rotate90CCW();
|
||||||
|
nextCell = cornerCell.getNeighbour(cornerCellDirection);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cornerCell = nextCell;
|
||||||
|
}
|
||||||
|
} while (nextCell != null);
|
||||||
|
|
||||||
|
// then, add (n - 1) cells in the direction rotated by 90 degrees CW,
|
||||||
|
// where n is either the board width or board height.
|
||||||
|
// e.g. for an expansion to the North, add (n - 1) cells to the EAST
|
||||||
|
// of the anchor cell
|
||||||
|
GomokuCell anchor = new GomokuCell(Color.NIL);
|
||||||
|
GomokuCell nextTo = cornerCell;
|
||||||
|
GomokuCell before = cornerCell.getNeighbour(direction.rotate90CCW());
|
||||||
|
GomokuCell after = cornerCell.getNeighbour(direction.rotate90CW());
|
||||||
|
Cardinal forwardDirection = direction.rotate90CW();
|
||||||
|
|
||||||
|
while (nextTo != null) {
|
||||||
|
// link the anchor cell with its neighbours
|
||||||
|
GomokuCell.link(before, anchor, direction.rotate(1));
|
||||||
|
GomokuCell.link(nextTo, anchor, direction);
|
||||||
|
GomokuCell.link(after, anchor, direction.rotate(-1));
|
||||||
|
// add a new cell next to the anchor and link it to the anchor,
|
||||||
|
// if the end of the board is not reached (to avoid creating an
|
||||||
|
// additional cell)
|
||||||
|
nextCell = null;
|
||||||
|
if (after != null) nextCell = new GomokuCell(Color.NIL);
|
||||||
|
GomokuCell.link(anchor, nextCell, forwardDirection);
|
||||||
|
// set the anchor to the next cell and update the neighbours
|
||||||
|
anchor = nextCell;
|
||||||
|
before = nextTo;
|
||||||
|
nextTo = after;
|
||||||
|
if (after != null) after = after.getNeighbour(forwardDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the board dimensions;
|
||||||
|
if (direction == Cardinal.N || direction == Cardinal.S) {
|
||||||
|
this.boardHeight++;
|
||||||
|
} else {
|
||||||
|
this.boardWidth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for the North and West expansions, update the first cell
|
||||||
|
// (top-left cell reference) of the entire board
|
||||||
|
if (direction == Cardinal.N || direction == Cardinal.W) {
|
||||||
|
this.firstCell = this.firstCell.getNeighbour(direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------Overides--------------------------
|
//------------------Overides--------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,7 +405,7 @@ public class GomokuBoard{
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
GomokuCell[][] cells = this.getAllsCells();
|
GomokuCell[][] cells = this.getAllCells();
|
||||||
for (GomokuCell[] line : cells) {
|
for (GomokuCell[] line : cells) {
|
||||||
for (GomokuCell c : line) {
|
for (GomokuCell c : line) {
|
||||||
out.append(c.toString());
|
out.append(c.toString());
|
||||||
|
|||||||
Reference in New Issue
Block a user