Refactor expandBoard() method

This commit is contained in:
Dorian HAMDANI
2025-04-03 13:06:58 +02:00
parent 274db2f067
commit 8670e03c80
2 changed files with 195 additions and 25 deletions

View File

@@ -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 {
N,
NE,
E,
SE,
S,
SW,
W,
NW;
N (0),
NE (1),
E (2),
SE (3),
S (4),
SW (5),
W (6),
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);
}
}

View File

@@ -24,15 +24,22 @@ public class GomokuBoard{
test.get(1,1).setState(Color.BLACK);
System.out.println(test);
System.out.println(test.getPlayableCells());
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
test.expandBoard(Cardinal.SW);
System.out.println(Cardinal.NE.rotate90CW());
System.out.println(Cardinal.NE.rotate90CCW());
System.out.println(Cardinal.NE.rotate(1));
System.out.println(Cardinal.NE.rotate(-1));
System.out.println(Cardinal.NE.inverse());
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.getPlayableCells());
}
//------------------Constructors--------------------------
@@ -56,17 +63,17 @@ public class GomokuBoard{
this.firstCell = new GomokuCell(Color.NIL);
this.boardWidth = width;
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 height Size of height.
* @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]);
GomokuCell act = this.firstCell;
GomokuCell top = null;
@@ -111,9 +118,9 @@ public class GomokuBoard{
while (i != x || j != y){
Cardinal c = Cardinal.SE;
if (i < x) i++;
else c = Cardinal.E;
if (j < y) j++;
else c = Cardinal.S;
if (j < y) j++;
else c = Cardinal.E;
act = act.getNeighbour(c);
}
return act;
@@ -124,7 +131,7 @@ public class GomokuBoard{
* This method return all cells in the board in the order.
* @return All cells with a array 2D.
*/
private GomokuCell[][] getAllsCells(){
private GomokuCell[][] getAllCells(){
GomokuCell[][] cells = new GomokuCell[this.boardHeight][this.boardWidth];
GomokuCell act = this.firstCell;
GomokuCell nextLine = this.firstCell.getNeighbour(Cardinal.S);
@@ -148,7 +155,7 @@ public class GomokuBoard{
public List<GomokuCell> getPlayableCells(){
List<GomokuCell> output = new ArrayList<>();
for (GomokuCell[] line : this.getAllsCells()) {
for (GomokuCell[] line : this.getAllCells()) {
for (GomokuCell c : line) {
if (c.isPlayable() && c.getState() == Color.NIL)
output.add(c);
@@ -300,6 +307,95 @@ public class GomokuBoard{
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--------------------------
/**
@@ -309,7 +405,7 @@ public class GomokuBoard{
@Override
public String toString() {
StringBuilder out = new StringBuilder();
GomokuCell[][] cells = this.getAllsCells();
GomokuCell[][] cells = this.getAllCells();
for (GomokuCell[] line : cells) {
for (GomokuCell c : line) {
out.append(c.toString());