Merge remote-tracking branch 'origin/Alpha' into UI

# Conflicts:
#	app/src/main/java/org/toop/app/menu/MainMenu.java
#	app/src/main/java/org/toop/app/menu/QuitMenu.java
This commit is contained in:
lieght
2025-10-01 15:56:42 +02:00
10 changed files with 171 additions and 61 deletions

2
.idea/misc.xml generated
View File

@@ -13,7 +13,7 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -0,0 +1,33 @@
.main-button {
-fx-background-color: transparent;
-fx-background-image: url("card-default.jpg"); /* fallback image */
-fx-background-size: cover;
-fx-background-position: center;
-fx-pref-width: 250px;
-fx-pref-height: 180px;
-fx-border-radius: 15;
-fx-background-radius: 15;
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 15, 0.4, 0, 4);
-fx-cursor: hand;
-fx-padding: 0;
}
.card-label {
-fx-background-color: rgba(0, 0, 0, 0.5);
-fx-font-size: 20px;
-fx-font-weight: bold;
-fx-text-fill: white;
-fx-padding: 10px;
-fx-alignment: top-center;
-fx-background-radius: 15 15 0 0;
-fx-opacity: 0;
-fx-transition: all 0.3s ease;
}
.main-button:hover {
-fx-effect: dropshadow(gaussian, #00ffff, 15, 0.5, 0, 0);
}
.main-button:hover .card-label {
-fx-opacity: 1;
}

View File

@@ -0,0 +1,33 @@
.quit-background {
-fx-background-color: rgba(0, 0, 0, 0.6);
}
.quit-box {
-fx-background-color: rgba(30, 30, 30, 0.95);
-fx-background-radius: 15;
-fx-padding: 30;
-fx-effect: dropshadow(gaussian, black, 20, 0.6, 0, 4);
}
.quit-text {
-fx-fill: white;
-fx-font-size: 28px;
-fx-font-weight: 600;
-fx-font-family: "Segoe UI", sans-serif;
}
.quit-button {
-fx-font-size: 16px;
-fx-text-fill: white;
-fx-background-color: transparent;
-fx-border-color: white;
-fx-border-radius: 5;
-fx-padding: 8 20;
-fx-cursor: hand;
}
.quit-button:hover {
-fx-text-fill: #00ffff;
-fx-border-color: #00ffff;
-fx-effect: dropshadow(gaussian, #00ffff, 8, 0.5, 0, 0);
}

View File

@@ -0,0 +1,20 @@
.root {
-fx-background-color: #2d2d2d;
-fx-font-size: 28px;
-fx-font-weight: 600;
-fx-font-family: "Segoe UI", sans-serif;
}
.button {
-fx-background-color: transparent;
-fx-text-fill: white;
-fx-border-color: transparent;
-fx-padding: 10 20;
-fx-cursor: hand;
-fx-effect: null;
}
.button:hover {
-fx-effect: dropshadow(gaussian, #00ffff, 10, 0.3, 0, 0);
}

View File

@@ -6,79 +6,103 @@ import org.toop.game.Player;
import java.util.ArrayList; import java.util.ArrayList;
public final class TicTacToe extends Game { public final class TicTacToe extends Game {
private int movesLeft; private int movesLeft;
public TicTacToe(String player1, String player2) { public TicTacToe(String player1, String player2) {
super(3, 3, new Player(player1, 'X'), new Player(player2, 'O')); super(3, 3, new Player(player1, 'X'), new Player(player2, 'O'));
movesLeft = board.length; movesLeft = board.length;
} }
public TicTacToe(TicTacToe other) { public TicTacToe(TicTacToe other) {
super(other); super(other);
movesLeft = other.movesLeft; movesLeft = other.movesLeft;
} }
@Override @Override
public Move[] getLegalMoves() { public Move[] getLegalMoves() {
final ArrayList<Move> legalMoves = new ArrayList<>(); final ArrayList<Move> legalMoves = new ArrayList<>();
for (int i = 0; i < board.length; i++) { for (int i = 0; i < board.length; i++) {
if (board[i] == EMPTY) { if (board[i] == EMPTY) {
legalMoves.add(new Move(i, getCurrentPlayer().values()[0])); legalMoves.add(new Move(i, getCurrentPlayer().values()[0]));
} }
} }
return legalMoves.toArray(new Move[0]); return legalMoves.toArray(new Move[0]);
} }
@Override @Override
public State play(Move move) { public State play(Move move) {
assert move != null; assert move != null;
assert move.position() >= 0 && move.position() < board.length; assert move.position() >= 0 && move.position() < board.length;
assert move.value() == getCurrentPlayer().values()[0]; assert move.value() == getCurrentPlayer().values()[0];
board[move.position()] = move.value(); board[move.position()] = move.value();
movesLeft--; movesLeft--;
if (checkForWin()) { if (checkForWin()) {
return State.WIN; return State.WIN;
} }
if (movesLeft <= 0) { nextPlayer();
return State.DRAW;
}
nextPlayer(); if (movesLeft <= 2) {
return State.NORMAL; if (checkDraw(new TicTacToe(this))) {
} return State.DRAW;
}
}
return State.NORMAL;
}
private boolean checkForWin() { private boolean checkForWin() {
// Horizontal // Horizontal
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
final int index = i * 3; final int index = i * 3;
if (board[index] != EMPTY if (board[index] != EMPTY
&& board[index] == board[index + 1] && board[index] == board[index + 1]
&& board[index] == board[index + 2]) { && board[index] == board[index + 2]) {
return true; return true;
} }
} }
// Vertical // Vertical
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (board[i] != EMPTY if (board[i] != EMPTY
&& board[i] == board[i + 3] && board[i] == board[i + 3]
&& board[i] == board[i + 6]) { && board[i] == board[i + 6]) {
return true; return true;
} }
} }
// B-Slash // B-Slash
if (board[0] != EMPTY && board[0] == board[4] && board[0] == board[8]) { if (board[0] != EMPTY && board[0] == board[4] && board[0] == board[8]) {
return true; return true;
} }
// F-Slash // F-Slash
return board[2] != EMPTY && board[2] == board[4] && board[2] == board[6]; return board[2] != EMPTY && board[2] == board[4] && board[2] == board[6];
} }
public boolean checkDraw(TicTacToe game) {
if (game.checkForWin()) {
return false;
}
if (game.movesLeft == 0) {
return true;
}
// try every move on a legal copy
for (Move move : game.getLegalMoves()) {
TicTacToe copy = new TicTacToe(game);
State result = copy.play(move);
if (result == State.WIN) {
return false;
}
if (!checkDraw(copy)) {
return false;
}
}
return true;
}
} }