Refactored Game to follow encapsulation principle

This commit is contained in:
2025-10-29 17:28:43 +01:00
parent 50713c5021
commit 5da0a02cc8
7 changed files with 152 additions and 139 deletions

View File

@@ -11,7 +11,7 @@ public class Connect4 extends TurnBasedGame {
public Connect4() {
super(6, 7, 2);
movesLeft = board.length;
movesLeft = this.getBoard().length;
}
public Connect4(Connect4 other) {
@@ -24,8 +24,8 @@ public class Connect4 extends TurnBasedGame {
final ArrayList<Move> legalMoves = new ArrayList<>();
final char currentValue = getCurrentValue();
for (int i = 0; i < columnSize; i++) {
if (board[i] == EMPTY) {
for (int i = 0; i < this.getColumnSize(); i++) {
if (this.getBoard()[i] == EMPTY) {
legalMoves.add(new Move(i, currentValue));
}
}
@@ -35,19 +35,19 @@ public class Connect4 extends TurnBasedGame {
@Override
public GameState play(Move move) {
assert move != null;
assert move.position() >= 0 && move.position() < board.length;
assert move.position() >= 0 && move.position() < this.getBoard().length;
assert move.value() == getCurrentValue();
int lowestEmptySpot = move.position();
for (int i = 0; i < rowSize; i++) {
int checkMovePosition = move.position() + columnSize * i;
if (checkMovePosition < board.length) {
if (board[checkMovePosition] == EMPTY) {
for (int i = 0; i < this.getRowSize(); i++) {
int checkMovePosition = move.position() + this.getColumnSize() * i;
if (checkMovePosition < this.getBoard().length) {
if (this.getBoard()[checkMovePosition] == EMPTY) {
lowestEmptySpot = checkMovePosition;
}
}
}
board[lowestEmptySpot] = move.value();
this.getBoard()[lowestEmptySpot] = move.value();
movesLeft--;
if (checkForWin()) {
@@ -63,33 +63,33 @@ public class Connect4 extends TurnBasedGame {
private boolean checkForWin() {
char[][] boardGrid = makeBoardAGrid();
for (int row = 0; row < rowSize; row++) {
for (int col = 0; col < columnSize; col++) {
for (int row = 0; row < this.getRowSize(); row++) {
for (int col = 0; col < this.getColumnSize(); col++) {
char cell = boardGrid[row][col];
if (cell == ' ' || cell == 0) continue;
if (col + 3 < columnSize &&
if (col + 3 < this.getColumnSize() &&
cell == boardGrid[row][col + 1] &&
cell == boardGrid[row][col + 2] &&
cell == boardGrid[row][col + 3]) {
return true;
}
if (row + 3 < rowSize &&
if (row + 3 < this.getRowSize() &&
cell == boardGrid[row + 1][col] &&
cell == boardGrid[row + 2][col] &&
cell == boardGrid[row + 3][col]) {
return true;
}
if (row + 3 < rowSize && col + 3 < columnSize &&
if (row + 3 < this.getRowSize() && col + 3 < this.getColumnSize() &&
cell == boardGrid[row + 1][col + 1] &&
cell == boardGrid[row + 2][col + 2] &&
cell == boardGrid[row + 3][col + 3]) {
return true;
}
if (row + 3 < rowSize && col - 3 >= 0 &&
if (row + 3 < this.getRowSize() && col - 3 >= 0 &&
cell == boardGrid[row + 1][col - 1] &&
cell == boardGrid[row + 2][col - 2] &&
cell == boardGrid[row + 3][col - 3]) {
@@ -101,11 +101,11 @@ public class Connect4 extends TurnBasedGame {
}
public char[][] makeBoardAGrid() {
char[][] boardGrid = new char[rowSize][columnSize];
for (int i = 0; i < rowSize*columnSize; i++) {
boardGrid[i / columnSize][i % columnSize] = board[i]; //boardGrid[y -> row] [x -> column]
char[][] boardGrid = new char[this.getRowSize()][this.getColumnSize()];
for (int i = 0; i < this.getRowSize()*this.getColumnSize(); i++) {
boardGrid[i / this.getColumnSize()][i % this.getColumnSize()] = this.getBoard()[i]; //this.getBoard()Grid[y -> row] [x -> column]
}
return boardGrid;
return boardGrid;
}
private char getCurrentValue() {

View File

@@ -1,16 +1,17 @@
package org.toop.game;
import org.toop.game.interfaces.IPlayable;
import org.toop.game.records.Move;
import java.util.Arrays;
public abstract class Game implements IPlayable {
public static final char EMPTY = (char)0;
public static final char EMPTY = (char)0; // Constant
public final int rowSize;
public final int columnSize;
public final char[] board;
private final int rowSize;
private final int columnSize;
private final char[] board;
protected Game(int rowSize, int columnSize) {
assert rowSize > 0 && columnSize > 0;
@@ -27,4 +28,13 @@ public abstract class Game implements IPlayable {
columnSize = other.columnSize;
board = Arrays.copyOf(other.board, other.board.length);
}
public int getRowSize() {return this.rowSize;}
public int getColumnSize() {return this.columnSize;}
public char[] getBoard() {return this.board;}
protected void setBoard(Move move){this.board[move.position()] = move.value();}
}

View File

@@ -33,16 +33,16 @@ public final class Reversi extends TurnBasedGame {
private void addStartPieces() {
board[27] = 'W';
board[28] = 'B';
board[35] = 'B';
board[36] = 'W';
this.setBoard(new Move(27, 'W'));
this.setBoard(new Move(28, 'B'));
this.setBoard(new Move(35, 'B'));
this.setBoard(new Move(36, 'W'));
updateFilledCellsSet();
}
private void updateFilledCellsSet() {
for (int i = 0; i < 64; i++) {
if (board[i] == 'W' || board[i] == 'B') {
filledCells.add(new Point(i % columnSize, i / rowSize));
if (this.getBoard()[i] == 'W' || this.getBoard()[i] == 'B') {
filledCells.add(new Point(i % this.getColumnSize(), i / this.getRowSize()));
}
}
}
@@ -57,7 +57,7 @@ public final class Reversi extends TurnBasedGame {
Move[] moves = getFlipsForPotentialMove(point,boardGrid,currentPlayer);
int score = moves.length;
if (score > 0){
legalMoves.add(new Move(point.x + point.y * rowSize, currentPlayer));
legalMoves.add(new Move(point.x + point.y * this.getRowSize(), currentPlayer));
}
}
return legalMoves.toArray(new Move[0]);
@@ -73,7 +73,7 @@ public final class Reversi extends TurnBasedGame {
|| !isOnBoard(newX, newY)) {
continue;
}
if (boardGrid[newY][newX] == Game.EMPTY) { //check if the cell is empty
if (boardGrid[newY][newX] == EMPTY) { //check if the cell is empty
possibleCells.add(new Point(newX, newY)); //and then add it to the set of possible moves
}
}
@@ -110,7 +110,7 @@ public final class Reversi extends TurnBasedGame {
while (isOnBoard(x, y) && boardGrid[y][x] == opponent) {
movesToFlip.add(new Move(x+y*rowSize, currentPlayer));
movesToFlip.add(new Move(x+y*this.getRowSize(), currentPlayer));
x += dirX;
y += dirY;
}
@@ -121,13 +121,13 @@ public final class Reversi extends TurnBasedGame {
}
private boolean isOnBoard(int x, int y) {
return x >= 0 && x < columnSize && y >= 0 && y < rowSize;
return x >= 0 && x < this.getColumnSize() && y >= 0 && y < this.getRowSize();
}
public char[][] makeBoardAGrid() {
char[][] boardGrid = new char[rowSize][columnSize];
char[][] boardGrid = new char[this.getRowSize()][this.getColumnSize()];
for (int i = 0; i < 64; i++) {
boardGrid[i / rowSize][i % columnSize] = board[i]; //boardGrid[y / row] [x / column]
boardGrid[i / this.getRowSize()][i % this.getColumnSize()] = this.getBoard()[i]; //boardGrid[y / row] [x / column]
}
return boardGrid;
}
@@ -142,13 +142,13 @@ public final class Reversi extends TurnBasedGame {
}
}
if (moveIsLegal) {
Move[] moves = sortMovesFromCenter(getFlipsForPotentialMove(new Point(move.position()%columnSize,move.position()/rowSize), makeBoardAGrid(), move.value()),move);
Move[] moves = sortMovesFromCenter(getFlipsForPotentialMove(new Point(move.position()%this.getColumnSize(),move.position()/this.getRowSize()), makeBoardAGrid(), move.value()),move);
mostRecentlyFlippedPieces = moves;
board[move.position()] = move.value();
this.setBoard(move);
for (Move m : moves) {
board[m.position()] = m.value();
this.setBoard(m);
}
filledCells.add(new Point(move.position() % rowSize, move.position() / columnSize));
filledCells.add(new Point(move.position() % this.getRowSize(), move.position() / this.getColumnSize()));
nextTurn();
if (getLegalMoves().length == 0) {
skipMyTurn();
@@ -196,24 +196,24 @@ public final class Reversi extends TurnBasedGame {
public Score getScore(){
int player1Score = 0, player2Score = 0;
for (int count = 0; count < rowSize * columnSize; count++) {
if (board[count] == 'B') {
for (int count = 0; count < this.getRowSize() * this.getColumnSize(); count++) {
if (this.getBoard()[count] == 'B') {
player1Score += 1;
}
if (board[count] == 'W') {
if (this.getBoard()[count] == 'W') {
player2Score += 1;
}
}
return new Score(player1Score, player2Score);
}
public Move[] sortMovesFromCenter(Move[] moves, Move center) {
int centerX = center.position()%columnSize;
int centerY = center.position()/rowSize;
int centerX = center.position()%this.getColumnSize();
int centerY = center.position()/this.getRowSize();
Arrays.sort(moves, (a, b) -> {
int dxA = a.position()%columnSize - centerX;
int dyA = a.position()/rowSize - centerY;
int dxB = b.position()%columnSize - centerX;
int dyB = b.position()/rowSize - centerY;
int dxA = a.position()%this.getColumnSize() - centerX;
int dyA = a.position()/this.getRowSize() - centerY;
int dxB = b.position()%this.getColumnSize() - centerX;
int dyB = b.position()/this.getRowSize() - centerY;
int distA = dxA * dxA + dyA * dyA;
int distB = dxB * dxB + dyB * dyB;

View File

@@ -10,7 +10,7 @@ public final class TicTacToe extends TurnBasedGame {
public TicTacToe() {
super(3, 3, 2);
movesLeft = board.length;
movesLeft = this.getBoard().length;
}
public TicTacToe(TicTacToe other) {
@@ -23,8 +23,8 @@ public final class TicTacToe extends TurnBasedGame {
final ArrayList<Move> legalMoves = new ArrayList<>();
final char currentValue = getCurrentValue();
for (int i = 0; i < board.length; i++) {
if (board[i] == EMPTY) {
for (int i = 0; i < this.getBoard().length; i++) {
if (this.getBoard()[i] == EMPTY) {
legalMoves.add(new Move(i, currentValue));
}
}
@@ -35,10 +35,11 @@ public final class TicTacToe extends TurnBasedGame {
@Override
public GameState play(Move move) {
assert move != null;
assert move.position() >= 0 && move.position() < board.length;
assert move.position() >= 0 && move.position() < this.getBoard().length;
assert move.value() == getCurrentValue();
board[move.position()] = move.value();
// TODO: Make sure this move is allowed, maybe on the board side?
this.setBoard(move);
movesLeft--;
if (checkForWin()) {
@@ -61,27 +62,27 @@ public final class TicTacToe extends TurnBasedGame {
for (int i = 0; i < 3; i++) {
final int index = i * 3;
if (board[index] != EMPTY
&& board[index] == board[index + 1]
&& board[index] == board[index + 2]) {
if (this.getBoard()[index] != EMPTY
&& this.getBoard()[index] == this.getBoard()[index + 1]
&& this.getBoard()[index] == this.getBoard()[index + 2]) {
return true;
}
}
// Vertical
for (int i = 0; i < 3; i++) {
if (board[i] != EMPTY && board[i] == board[i + 3] && board[i] == board[i + 6]) {
if (this.getBoard()[i] != EMPTY && this.getBoard()[i] == this.getBoard()[i + 3] && this.getBoard()[i] == this.getBoard()[i + 6]) {
return true;
}
}
// B-Slash
if (board[0] != EMPTY && board[0] == board[4] && board[0] == board[8]) {
if (this.getBoard()[0] != EMPTY && this.getBoard()[0] == this.getBoard()[4] && this.getBoard()[0] == this.getBoard()[8]) {
return true;
}
// F-Slash
return board[2] != EMPTY && board[2] == board[4] && board[2] == board[6];
return this.getBoard()[2] != EMPTY && this.getBoard()[2] == this.getBoard()[4] && this.getBoard()[2] == this.getBoard()[6];
}
private boolean checkForEarlyDraw(TicTacToe game) {