mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +00:00
merged
This commit is contained in:
@@ -8,7 +8,7 @@ import org.toop.framework.networking.NetworkingClientManager;
|
||||
import org.toop.framework.networking.NetworkingInitializationException;
|
||||
|
||||
public final class Main {
|
||||
static void main(String[] args) {
|
||||
public static void main(String[] args) {
|
||||
initSystems();
|
||||
App.run(args);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Stage;
|
||||
import org.toop.framework.asset.AssetManager;
|
||||
import org.toop.framework.asset.resources.CssAsset;
|
||||
|
||||
public final class App extends Application {
|
||||
private static Stage stage;
|
||||
@@ -42,7 +44,7 @@ public final class App extends Application {
|
||||
box.setMaxHeight(200);
|
||||
|
||||
pane = new StackPane(background, box);
|
||||
pane.getStylesheets().add(App.class.getResource("/style/quit.css").toExternalForm());
|
||||
pane.getStylesheets().add(((CssAsset)AssetManager.get("quit.css")).getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ public final class App extends Application {
|
||||
final StackPane root = new StackPane(new MainMenu().getPane());
|
||||
|
||||
final Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(App.class.getResource("/style/app.css").toExternalForm());
|
||||
scene.getStylesheets().add(((CssAsset)AssetManager.get("app.css")).getUrl());
|
||||
|
||||
stage.setTitle("pism");
|
||||
stage.setMinWidth(1080);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.toop.app.menu;
|
||||
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.toop.app.GameType;
|
||||
|
||||
public class GameMenu extends Menu {
|
||||
public GameMenu(GameType type) {
|
||||
final Region background = createBackground();
|
||||
|
||||
ComboBox<String> selectedGame = new ComboBox<>();
|
||||
|
||||
TextField serverIpField = new TextField();
|
||||
serverIpField.setPromptText("Enter here your server ip address");
|
||||
|
||||
VBox box = new VBox(selectedGame, serverIpField);
|
||||
pane = new StackPane(background, box);
|
||||
}
|
||||
}
|
||||
33
app/src/main/java/org/toop/app/menu/GameSelectMenu.java
Normal file
33
app/src/main/java/org/toop/app/menu/GameSelectMenu.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package org.toop.app.menu;
|
||||
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.toop.app.GameType;
|
||||
|
||||
public class GameSelectMenu extends Menu {
|
||||
public GameSelectMenu(GameType type) {
|
||||
final Region background = createBackground();
|
||||
|
||||
final ComboBox<String> selectedGame = new ComboBox<>();
|
||||
selectedGame.getItems().add(GameType.toName(GameType.TICTACTOE));
|
||||
selectedGame.getItems().add(GameType.toName(GameType.REVERSI));
|
||||
selectedGame.setValue(GameType.toName(type));
|
||||
|
||||
final ComboBox<String> selectedMode = new ComboBox<>();
|
||||
selectedMode.getItems().add("Local");
|
||||
selectedMode.getItems().add("Online");
|
||||
selectedMode.setValue("Local");
|
||||
|
||||
final HBox selectedContainer = new HBox(10, selectedGame, selectedMode);
|
||||
|
||||
final TextField serverIpField = new TextField();
|
||||
serverIpField.setPromptText("Enter here your server ip address");
|
||||
|
||||
VBox box = new VBox(selectedContainer, serverIpField);
|
||||
pane = new StackPane(background, box);
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,19 @@ package org.toop.app.menu;
|
||||
|
||||
import org.toop.app.App;
|
||||
import org.toop.app.GameType;
|
||||
import org.toop.app.screen.TicTacToeScreen;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.layout.*;
|
||||
import org.toop.app.menu.game.TicTacToeMenu;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
|
||||
public final class MainMenu extends Menu {
|
||||
public MainMenu() {
|
||||
final Region background = createBackground();
|
||||
|
||||
final Button tictactoe = createButton("Tic Tac Toe", () -> { App.activate(new GameMenu(GameType.TICTACTOE)); });
|
||||
final Button reversi = createButton("Reversi", () -> { App.activate(new GameMenu(GameType.REVERSI)); });
|
||||
final Button tictactoe = createButton("Tic Tac Toe", () -> { App.activate(new TicTacToeMenu(new TicTacToe("player 1", true, "player 2", true))); });
|
||||
final Button reversi = createButton("Reversi", () -> { App.activate(new GameSelectMenu(GameType.REVERSI)); });
|
||||
|
||||
final VBox gamesBox = new VBox(10, tictactoe, reversi);
|
||||
gamesBox.setAlignment(Pos.TOP_LEFT);
|
||||
@@ -32,14 +33,5 @@ public final class MainMenu extends Menu {
|
||||
controlBox.setTranslateX(25);
|
||||
|
||||
pane = new StackPane(background, gamesBox, controlBox);
|
||||
|
||||
tictactoe.setOnMouseEntered(_ -> {
|
||||
final TicTacToeScreen screen = new TicTacToeScreen((int)pane.getHeight());
|
||||
screen.simulate(1000);
|
||||
|
||||
push(screen.getCanvas());
|
||||
});
|
||||
|
||||
tictactoe.setOnMouseExited(_ -> { pop(); });
|
||||
}
|
||||
}
|
||||
@@ -10,14 +10,6 @@ public abstract class Menu {
|
||||
protected Pane pane;
|
||||
public Pane getPane() { return pane; }
|
||||
|
||||
public void push(Node node) {
|
||||
pane.getChildren().addLast(node);
|
||||
}
|
||||
|
||||
public void pop() {
|
||||
pane.getChildren().removeLast();
|
||||
}
|
||||
|
||||
public Region createBackground(String css) {
|
||||
final Region background = new Region();
|
||||
background.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
|
||||
99
app/src/main/java/org/toop/app/menu/game/GameMenu.java
Normal file
99
app/src/main/java/org/toop/app/menu/game/GameMenu.java
Normal file
@@ -0,0 +1,99 @@
|
||||
package org.toop.app.menu.game;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import org.toop.app.App;
|
||||
import org.toop.app.menu.MainMenu;
|
||||
import org.toop.app.menu.Menu;
|
||||
|
||||
public abstract class GameMenu extends Menu {
|
||||
protected final class Cell {
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public Cell(float x, float y, float width, float height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public boolean check(float x, float y) {
|
||||
return x >= this.x && y >= this.y && x <= this.x + width && y <= this.y + height;
|
||||
}
|
||||
}
|
||||
|
||||
protected final int size;
|
||||
|
||||
protected final Canvas canvas;
|
||||
protected final GraphicsContext graphics;
|
||||
|
||||
protected final int rows;
|
||||
protected final int columns;
|
||||
|
||||
protected final int gapSize;
|
||||
|
||||
protected final Cell[] cells;
|
||||
|
||||
protected GameMenu(int rows, int columns, int gapSize) {
|
||||
final int size = Math.min(App.getWidth(), App.getHeight()) / 5 * 4;
|
||||
|
||||
final Canvas canvas = new Canvas(size, size);
|
||||
|
||||
final GraphicsContext graphics = canvas.getGraphicsContext2D();
|
||||
|
||||
this.size = size;
|
||||
|
||||
this.canvas = canvas;
|
||||
this.graphics = graphics;
|
||||
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
|
||||
this.gapSize = gapSize;
|
||||
|
||||
cells = new Cell[rows * columns];
|
||||
|
||||
final float cellWidth = ((float)size - (rows - 1) * gapSize) / rows;
|
||||
final float cellHeight = ((float)size - (columns - 1) * gapSize) / rows;
|
||||
|
||||
for (int y = 0; y < columns; y++) {
|
||||
final float startY = y * cellHeight + y * gapSize;
|
||||
|
||||
for (int x = 0; x < rows; x++) {
|
||||
final float startX = x * cellWidth + x * gapSize;
|
||||
cells[y * rows + x] = new Cell(startX, startY, cellWidth, cellHeight);
|
||||
}
|
||||
}
|
||||
|
||||
final Region background = createBackground();
|
||||
|
||||
final Text player1 = createText("player_1", "Player 1");
|
||||
final Text player2 = createText("player_2", "Player 2");
|
||||
|
||||
final HBox playersContainer = new HBox(100, player1, player2);
|
||||
playersContainer.setAlignment(Pos.TOP_CENTER);
|
||||
playersContainer.setPickOnBounds(false);
|
||||
playersContainer.setTranslateY(50);
|
||||
|
||||
final Button hint = createButton("Hint", () -> {});
|
||||
final Button back = createButton("Back", () -> { App.activate(new MainMenu()); });
|
||||
|
||||
final VBox controlContainer = new VBox(hint, back);
|
||||
StackPane.setAlignment(controlContainer, Pos.BOTTOM_LEFT);
|
||||
controlContainer.setPickOnBounds(false);
|
||||
|
||||
pane = new StackPane(background, canvas, playersContainer, controlContainer);
|
||||
}
|
||||
}
|
||||
137
app/src/main/java/org/toop/app/menu/game/TicTacToeMenu.java
Normal file
137
app/src/main/java/org/toop/app/menu/game/TicTacToeMenu.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package org.toop.app.menu.game;
|
||||
|
||||
import javafx.scene.paint.Color;
|
||||
import org.toop.game.Game;
|
||||
import org.toop.game.Player;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
import org.toop.game.tictactoe.TicTacToeAI;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public final class TicTacToeMenu extends GameMenu {
|
||||
private final TicTacToe game;
|
||||
private final TicTacToeAI ai;
|
||||
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||
private final BlockingQueue<Game.Move> moveQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
public TicTacToeMenu(TicTacToe game) {
|
||||
super(3, 3, 10);
|
||||
|
||||
graphics.setFill(Color.CYAN);
|
||||
|
||||
for (int x = 1; x < rows; x++) {
|
||||
graphics.fillRect(cells[x].x - gapSize, 0, gapSize, size);
|
||||
}
|
||||
|
||||
for (int y = 1; y < columns; y++) {
|
||||
graphics.fillRect(0, cells[y * rows].y - gapSize, size, gapSize);
|
||||
}
|
||||
|
||||
this.game = game;
|
||||
ai = new TicTacToeAI();
|
||||
|
||||
canvas.setOnMouseClicked(event -> {
|
||||
for (int i = 0; i < cells.length; i++) {
|
||||
if (cells[i].check((float) event.getX(), (float) event.getY())) {
|
||||
final Game.Move move = new Game.Move(i, game.getCurrentPlayer().values()[0]);
|
||||
play(move);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.executor.submit(this::gameThread);
|
||||
}
|
||||
|
||||
private void play(Game.Move move) {
|
||||
final Game.Move[] legalMoves = game.getLegalMoves();
|
||||
|
||||
boolean isLegal = false;
|
||||
|
||||
for (final Game.Move legalMove : legalMoves) {
|
||||
if (legalMove.position() == move.position() && legalMove.value() == move.value()) {
|
||||
isLegal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLegal) {
|
||||
return;
|
||||
}
|
||||
|
||||
try { moveQueue.put(move); }
|
||||
catch (InterruptedException _) {}
|
||||
}
|
||||
|
||||
private void placeX(int cell) {
|
||||
graphics.setStroke(Color.ORANGERED);
|
||||
graphics.setLineWidth(gapSize);
|
||||
|
||||
final float x = cells[cell].x + gapSize;
|
||||
final float y = cells[cell].y + gapSize;
|
||||
|
||||
final float width = cells[cell].width - gapSize * 2;
|
||||
final float height = cells[cell].height - gapSize * 2;
|
||||
|
||||
graphics.strokeLine(x, y, x + width, y + height);
|
||||
graphics.strokeLine(x + width, y, x, y + height);
|
||||
}
|
||||
|
||||
private void placeO(int cell) {
|
||||
graphics.setStroke(Color.DEEPSKYBLUE);
|
||||
graphics.setLineWidth(gapSize);
|
||||
|
||||
final float x = cells[cell].x + gapSize;
|
||||
final float y = cells[cell].y + gapSize;
|
||||
|
||||
final float width = cells[cell].width - gapSize * 2;
|
||||
final float height = cells[cell].height - gapSize * 2;
|
||||
|
||||
graphics.strokeOval(x, y, width, height);
|
||||
}
|
||||
|
||||
private void gameThread() {
|
||||
boolean running = true;
|
||||
|
||||
while(running) {
|
||||
final Player currentPlayer = game.getCurrentPlayer();
|
||||
|
||||
try {
|
||||
Game.Move move;
|
||||
|
||||
if (!currentPlayer.isAI()) {
|
||||
try { move = moveQueue.take(); }
|
||||
catch (InterruptedException _) { return; }
|
||||
} else {
|
||||
move = ai.findBestMove(game, 9);
|
||||
}
|
||||
|
||||
assert move != null;
|
||||
final Game.State state = game.play(move);
|
||||
|
||||
if (move.value() == 'X') {
|
||||
placeX(move.position());
|
||||
} else {
|
||||
placeO(move.position());
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case NORMAL: break;
|
||||
|
||||
case DRAW:
|
||||
case LOSE:
|
||||
case WIN:
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
executor.close();
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.toop.app.screen;
|
||||
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
|
||||
public abstract class Screen {
|
||||
protected final class Cell {
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public Cell(float x, float y, float width, float height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public boolean check(int x, int y) {
|
||||
return x >= this.x && y >= this.y && x <= this.x + width && y <= this.y + height;
|
||||
}
|
||||
}
|
||||
|
||||
protected final Canvas canvas;
|
||||
protected final GraphicsContext graphics;
|
||||
|
||||
protected final int width;
|
||||
protected final int height;
|
||||
|
||||
protected final int rowSize;
|
||||
protected final int columnSize;
|
||||
|
||||
protected final int gapSize;
|
||||
|
||||
protected final Cell[] cells;
|
||||
|
||||
protected Screen(int width, int height, int rowSize, int columnSize, int gapSize) {
|
||||
final Canvas canvas = new Canvas(width, height);
|
||||
final GraphicsContext graphics = canvas.getGraphicsContext2D();
|
||||
|
||||
this.canvas = canvas;
|
||||
this.graphics = graphics;
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.rowSize = rowSize;
|
||||
this.columnSize = columnSize;
|
||||
|
||||
this.gapSize = gapSize;
|
||||
|
||||
cells = new Cell[rowSize * columnSize];
|
||||
|
||||
final float cellWidth = ((float)width - (rowSize - 1) * gapSize) / rowSize;
|
||||
final float cellHeight = ((float)height - (columnSize - 1) * gapSize) / rowSize;
|
||||
|
||||
for (int y = 0; y < columnSize; y++) {
|
||||
final float startY = y * cellHeight + y * gapSize;
|
||||
|
||||
for (int x = 0; x < rowSize; x++) {
|
||||
final float startX = x * cellWidth + x * gapSize;
|
||||
cells[y * rowSize + x] = new Cell(startX, startY, cellWidth, cellHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Canvas getCanvas() { return canvas; }
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package org.toop.app.screen;
|
||||
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TicTacToeScreen extends Screen {
|
||||
public TicTacToeScreen(int size) {
|
||||
super(size, size, 3, 3, 10);
|
||||
|
||||
graphics.setFill(Color.CYAN);
|
||||
|
||||
for (int x = 1; x < rowSize; x++) {
|
||||
graphics.fillRect(cells[x].x - gapSize, 0, gapSize, height - gapSize);
|
||||
}
|
||||
|
||||
for (int y = 1; y < columnSize; y++) {
|
||||
graphics.fillRect(0, cells[y * rowSize].y - gapSize, width - gapSize, gapSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void placeX(int cell) {
|
||||
graphics.setFill(Color.WHITE);
|
||||
graphics.setLineWidth(gapSize);
|
||||
|
||||
final float x = cells[cell].x;
|
||||
final float y = cells[cell].y;
|
||||
|
||||
final float width = cells[cell].width;
|
||||
final float height = cells[cell].height;
|
||||
|
||||
graphics.strokeLine(x, y, x + width, y + height);
|
||||
graphics.strokeLine(x + width, y, x, y + height);
|
||||
}
|
||||
|
||||
public void placeO(int cell) {
|
||||
graphics.setFill(Color.WHITE);
|
||||
graphics.setLineWidth(gapSize);
|
||||
|
||||
final float x = cells[cell].x;
|
||||
final float y = cells[cell].y;
|
||||
|
||||
final float width = cells[cell].width;
|
||||
final float height = cells[cell].height;
|
||||
|
||||
graphics.strokeOval(x, y, width, height);
|
||||
}
|
||||
|
||||
public void simulate(int speedInMilliseconds) {
|
||||
final Random random = new Random();
|
||||
|
||||
final List<Integer> playedCells = new ArrayList<>();
|
||||
|
||||
final Timeline timeline = new Timeline(new KeyFrame(Duration.millis(speedInMilliseconds), _ ->{
|
||||
int cell;
|
||||
|
||||
do {
|
||||
cell = random.nextInt(cells.length);
|
||||
} while (playedCells.contains(cell));
|
||||
|
||||
if (playedCells.size() % 2 == 0) {
|
||||
placeX(cell);
|
||||
} else {
|
||||
placeO(cell);
|
||||
}
|
||||
|
||||
playedCells.add(cell);
|
||||
}));
|
||||
|
||||
timeline.setCycleCount(9);
|
||||
timeline.play();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
.background {
|
||||
-fx-background-image: url("/image/lowpoly.png");
|
||||
-fx-background-color: linear-gradient(to bottom right, #21a7b2, #8f32b9);
|
||||
}
|
||||
|
||||
.text {
|
||||
|
||||
Reference in New Issue
Block a user