Created a somewhat generic TurnBasedGame thread. Temporary UI that only works for TicTacToe rn. Added a LocalPlayer with the intent to add more players

This commit is contained in:
2025-11-27 21:44:55 +01:00
parent 0cb025edb9
commit 3b6017b369
9 changed files with 319 additions and 4 deletions

View File

@@ -0,0 +1,24 @@
package org.toop.app.game;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class LocalPlayer extends Player{
private BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
public LocalPlayer() {}
@Override
public int getMove() {
try {
return queue.take();
}catch (InterruptedException e){
return -1;
}
}
public void enqueueMove(int move) {
System.out.println(move);
queue.offer(move);
}
}

View File

@@ -0,0 +1,8 @@
package org.toop.app.game;
import org.toop.game.records.Move;
public interface MoveBehaviour
{
int getMove();
}

View File

@@ -0,0 +1,6 @@
package org.toop.app.game;
import org.toop.game.records.Move;
public abstract class Player implements MoveBehaviour{
}

View File

@@ -0,0 +1,92 @@
package org.toop.app.game;
import javafx.geometry.Pos;
import javafx.scene.paint.Color;
import org.toop.app.App;
import org.toop.app.canvas.GameCanvas;
import org.toop.app.canvas.TicTacToeCanvas;
import org.toop.app.widget.WidgetContainer;
import org.toop.app.widget.view.GameView;
import org.toop.game.TurnBasedGameR;
import org.toop.game.enumerators.GameState;
import org.toop.game.records.Move;
import org.toop.game.tictactoe.TicTacToe;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
public class TurnBasedGameThread implements Runnable {
private final Player[] players; // List of players, can't be changed.
private final TurnBasedGameR game; // Reference to game instance
private final AtomicBoolean isRunning = new AtomicBoolean();
// TODO: Seperate this from game Thread
private final GameView primary = new GameView(null, null, null);
private final TicTacToeCanvas canvas;
public TurnBasedGameThread(Player[] players, TurnBasedGameR game) {
// Make sure player list matches expected size
if (players.length != game.getPlayerCount()){
throw new IllegalArgumentException("players and game's players must have same length");
}
this.players = players;
this.game = game;
Thread thread = new Thread(this::run);
thread.start();
// UI SHIZ TO MOVE
canvas = new TicTacToeCanvas(Color.GRAY,
(App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3,(c) -> {if (players[game.getCurrentTurn()] instanceof LocalPlayer lp) {lp.enqueueMove(c);}});
primary.add(Pos.CENTER, canvas.getCanvas());
WidgetContainer.getCurrentView().transitionNext(primary);
}
// Move to UI shiz
private void drawMove(int move) {
if (game.getCurrentTurn() == 1) canvas.drawX(Color.RED, move);
else canvas.drawO(Color.BLUE, move);
}
public void run() {
isRunning.set(true);
// Game logic loop
while(isRunning.get()) {
// Get current player
Player currentPlayer = players[game.getCurrentTurn()];
// Get this player's valid moves
Integer[] validMoves = game.getLegalMoves();
// Get player's move, reask if Move is invalid
// TODO: Limit amount of retries?
int move = currentPlayer.getMove();
while (!Arrays.asList(validMoves).contains(move)) {
System.out.println("Invalid move");;
move = currentPlayer.getMove();
}
// Make move
GameState state = game.play(move);
drawMove(move);
if (state != GameState.NORMAL) {
if (state == GameState.WIN) {
// Someone won
} else if (state == GameState.DRAW) {
// THere was a draw
}
isRunning.set(false);
}
}
}
private void updateUI(){
}
}

View File

@@ -1,13 +1,14 @@
package org.toop.app.widget.view;
import org.toop.app.GameInformation;
import org.toop.app.game.Connect4Game;
import org.toop.app.game.ReversiGame;
import org.toop.app.game.TicTacToeGameThread;
import org.toop.app.game.*;
import org.toop.app.widget.Primitive;
import org.toop.app.widget.complex.PlayerInfoWidget;
import org.toop.app.widget.complex.ViewWidget;
import org.toop.app.widget.popup.ErrorPopup;
import org.toop.game.tictactoe.TicTacToe;
import org.toop.game.tictactoe.TicTacToeAI;
import org.toop.game.tictactoe.TicTacToeR;
import org.toop.local.AppContext;
import javafx.geometry.Pos;
@@ -32,7 +33,7 @@ public class LocalMultiplayerView extends ViewWidget {
}
switch (information.type) {
case TICTACTOE -> new TicTacToeGameThread(information);
case TICTACTOE -> new TurnBasedGameThread(new Player[]{new LocalPlayer(), new LocalPlayer()}, new TicTacToeR());
case REVERSI -> new ReversiGame(information);
case CONNECT4 -> new Connect4Game(information);
// case BATTLESHIP -> new BattleshipGame(information);