commit ofzo

This commit is contained in:
Ticho Hidding
2025-10-14 13:12:45 +02:00
parent be26db953e
commit 81abeef843
18 changed files with 58 additions and 27 deletions

View File

@@ -6,9 +6,6 @@ import org.toop.app.layer.Container;
import org.toop.app.layer.Layer;
import org.toop.app.layer.NodeBuilder;
import org.toop.app.layer.containers.VerticalContainer;
import org.toop.framework.audio.VolumeControl;
import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow;
import org.toop.app.layer.layers.game.ReversiLayer;
import org.toop.local.AppContext;
@@ -29,9 +26,9 @@ public final class MainLayer extends Layer {
App.activate(new MultiplayerLayer());
});
final var othelloButton =
final var reversiButton =
NodeBuilder.button(
AppContext.getString("othello"),
AppContext.getString("reversi"),
() -> {
App.activate(new ReversiLayer());
});
@@ -58,7 +55,7 @@ public final class MainLayer extends Layer {
});
final Container gamesContainer = new VerticalContainer(5);
gamesContainer.addNodes(tictactoeButton, othelloButton);
gamesContainer.addNodes(tictactoeButton, reversiButton);
final Container controlContainer = new VerticalContainer(5);
controlContainer.addNodes(creditsButton, optionsButton, quitButton);

View File

@@ -31,7 +31,7 @@ moralSupport=\u062f\u0639\u0645 \u0645\u0639\u0646\u0648\u064a
no=\u0644\u0627
opengl=OpenGL
options=\u0627\u0644\u062e\u064a\u0627\u0631\u0627\u062a
othello=\u0623\u0648\u062a\u064a\u0644\u0648
reversi=\u0623\u0648\u062a\u064a\u0644\u0648
playerName=\u0627\u0633\u0645 \u0627\u0644\u0644\u0627\u0639\u0628
productOwner=\u0645\u0627\u0644\u0643 \u0627\u0644\u0645\u0646\u062a\u062c
quit=\u062e\u0631\u0648\u062c

View File

@@ -31,7 +31,7 @@ moralSupport=Mentale Unterst\u00fctzung
no=Nein
opengl=OpenGL
options=Optionen
othello=Othello
reversi=Othello
playerName=Spielername
productOwner=Produktverantwortlicher
quit=Beenden

View File

@@ -35,7 +35,7 @@ moralSupport=Moral Support
no=No
opengl=OpenGL
options=Options
othello=Othello
reversi=Reversi
playerName=Player Name
productOwner=Product Owner
quit=Quit

View File

@@ -31,7 +31,7 @@ moralSupport=Apoyo moral
no=No
opengl=OpenGL
options=Opciones
othello=Othello
reversi=Othello
playerName=Nombre del Jugador
productOwner=Propietario del Producto
quit=Salir

View File

@@ -31,7 +31,7 @@ moralSupport=Soutien moral
no=Non
opengl=OpenGL
options=Options
othello=Othello
reversi=Othello
playerName=Nom du joueur
productOwner=Responsable du produit
quit=Quitter

View File

@@ -31,7 +31,7 @@ moralSupport=\u0928\u094d\u092e\u093e\u0928\u093f\u0915 \u0938\u092e\u0930\u094d
no=\u0928\u0939\u0940\u0902
opengl=OpenGL
options=\u0935\u093f\u0915\u0932\u094d\u092a
othello=\u0913\u0925\u0940\u0932\u094b
reversi=\u0913\u0925\u0940\u0932\u094b
playerName=\u0915\u0941\u0930\u093e\u0930\u0940 \u0928\u093e\u092e
productOwner=\u0906\u092f\u0947\u0915\u093e \u092e\u093e\u0932\u093f\u0915
quit=\u0938\u094e\u091c\u094d

View File

@@ -31,7 +31,7 @@ moralSupport=Supporto morale
no=No
opengl=OpenGL
options=Opzioni
othello=Othello
reversi=Othello
playerName=Nome del giocatore
productOwner=Proprietario del prodotto
quit=Uscire

View File

@@ -31,7 +31,7 @@ moralSupport=\u6c17\u529b\u652f\u63f4
no=\u3044\u3044\u3048
opengl=OpenGL
options=\u30aa\u30d7\u30b7\u30e7\u30f3
othello=\u30aa\u30bb\u30ed
reversi=\u30aa\u30bb\u30ed
playerName=\u30d7\u30ec\u30a4\u30e4\u30fc\u540d
productOwner=\u30d7\u30ed\u30c0\u30af\u30c8\u30aa\u30fc\u30ca\u30fc
quit=\u7d42\u4e86

View File

@@ -31,7 +31,7 @@ moralSupport=\uc815\uc2e0\uc801 \uc9c0\uc6d0
no=\uc544\ub2c8\uc624
opengl=OpenGL
options=\uc635\uc158
othello=\uc624\ud14c\ub85c
reversi=\uc624\ud14c\ub85c
playerName=\ud50c\ub808\uc774\uc5b4 \uc774\ub984
productOwner=\uc81c\ud488 \uad00\ub9ac\uc790
quit=\uc885\ub8cc

View File

@@ -31,7 +31,7 @@ moralSupport=Moraalsteun
no=Nee
opengl=OpenGL
options=Opties
othello=Othello
reversi=Reversi
playerName=Spelernaam
productOwner=Producteigenaar
quit=Afsluiten

View File

@@ -31,7 +31,7 @@ moralSupport=\u041c\u043e\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e
no=\u041d\u0435\u0442
opengl=OpenGL
options=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
othello=\u041e\u0442\u0435\u043b\u043b\u043e
reversi=\u041e\u0442\u0435\u043b\u043b\u043e
playerName=\u0418\u043c\u044f \u0438\u0433\u0440\u043e\u043a\u0430
productOwner=\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430
quit=\u0412\u044b\u0445\u043e\u0434

View File

@@ -31,7 +31,7 @@ moralSupport=\u795e\u7cbe\u652f\u6301
no=\u5426
opengl=OpenGL
options=\u9009\u9879
othello=Othello
reversi=Reversi
playerName=\u73a9\u5bb6\u540d\u79f0
productOwner=\u54c1\u76d8\u4ea7\u54c1\u4eba
quit=\u9000\u51fa

View File

@@ -7,6 +7,7 @@ public abstract class Game {
NORMAL,
DRAW,
WIN,
MOVE_SKIPPED,
}
public record Move(int position, char value) {}

View File

@@ -38,7 +38,7 @@ public final class Reversi extends TurnBasedGame {
private void updateFilledCellsSet() {
for (int i = 0; i < 64; i++) {
if (board[i] == 'W' || board[i] == 'B') {
filledCells.add(new Point(i / 8, i % 8));
filledCells.add(new Point(i % columnSize, i / rowSize));
}
}
}
@@ -49,12 +49,11 @@ public final class Reversi extends TurnBasedGame {
char[][] boardGrid = makeBoardAGrid();
char currentPlayer = (currentTurn==0) ? 'B' : 'W';
Set<Point> adjCell = getAdjacentCells(boardGrid);
for (Point point : adjCell){
Move[] moves = getFlipsForPotentialMove(point,boardGrid,currentPlayer);
int score = moves.length;
if (score > 0){
legalMoves.add(new Move(point.x + point.y * 8, currentPlayer));
legalMoves.add(new Move(point.x + point.y * rowSize, currentPlayer));
}
}
return legalMoves.toArray(new Move[0]);
@@ -107,7 +106,7 @@ public final class Reversi extends TurnBasedGame {
while (isOnBoard(x, y) && boardGrid[y][x] == opponent) {
movesToFlip.add(new Move(x+y*8, currentPlayer));
movesToFlip.add(new Move(x+y*rowSize, currentPlayer));
x += dirX;
y += dirY;
}
@@ -118,13 +117,13 @@ public final class Reversi extends TurnBasedGame {
}
private boolean isOnBoard(int x, int y) {
return x >= 0 && x < 8 && y >= 0 && y < 8;
return x >= 0 && x < columnSize && y >= 0 && y < rowSize;
}
public char[][] makeBoardAGrid() {
char[][] boardGrid = new char[8][8];
char[][] boardGrid = new char[rowSize][columnSize];
for (int i = 0; i < 64; i++) {
boardGrid[i / 8][i % 8] = board[i]; //boardGrid[y / row] [x / column]
boardGrid[i / rowSize][i % columnSize] = board[i]; //boardGrid[y / row] [x / column]
}
return boardGrid;
}
@@ -139,16 +138,22 @@ public final class Reversi extends TurnBasedGame {
}
}
if (moveIsLegal) {
Move[] moves = getFlipsForPotentialMove(new Point(move.position()%8,move.position()/8), makeBoardAGrid(), move.value());
Move[] moves = getFlipsForPotentialMove(new Point(move.position()%columnSize,move.position()/rowSize), makeBoardAGrid(), move.value());
board[move.position()] = move.value();
IO.println(move.position() +" "+ move.value());
for (Move m : moves) {
board[m.position()] = m.value();
}
updateFilledCellsSet();
filledCells.add(new Point(move.position() % rowSize, move.position() / columnSize));
//updateFilledCellsSet();
nextTurn();
if (getLegalMoves().length == 0) {
skipMyTurn();
return State.MOVE_SKIPPED;
}
return State.NORMAL;
}
return null;
}

View File

@@ -105,6 +105,34 @@ class ReversiTest {
}
@Test
void testPlayerMustSkipTurnIfNoValidMoves() {
game.play(new Game.Move(19, 'B'));
game.play(new Game.Move(34, 'W'));
game.play(new Game.Move(45, 'B'));
game.play(new Game.Move(11, 'W'));
game.play(new Game.Move(42, 'B'));
game.play(new Game.Move(54, 'W'));
game.play(new Game.Move(37, 'B'));
game.play(new Game.Move(46, 'W'));
game.play(new Game.Move(63, 'B'));
game.play(new Game.Move(62, 'W'));
game.play(new Game.Move(29, 'B'));
game.play(new Game.Move(50, 'W'));
game.play(new Game.Move(55, 'B'));
game.play(new Game.Move(30, 'W'));
game.play(new Game.Move(53, 'B'));
game.play(new Game.Move(38, 'W'));
game.play(new Game.Move(61, 'B'));
game.play(new Game.Move(52, 'W'));
game.play(new Game.Move(51, 'B'));
game.play(new Game.Move(60, 'W'));
game.play(new Game.Move(59, 'B'));
assertEquals('B', game.getCurrentPlayer());
game.play(ai.findBestMove(game,5));
game.play(ai.findBestMove(game,5));
}
@Test
void testAISelectsLegalMove() {
Game.Move move = ai.findBestMove(game,4);