mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +00:00
refactored the file structure. nothing works :)
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.toop</groupId>
|
||||
@@ -12,9 +12,9 @@
|
||||
<maven.compiler.source>24</maven.compiler.source>
|
||||
<maven.compiler.target>24</maven.compiler.target>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<main-class>org.toop.Main</main-class>
|
||||
<main-class>org.toop.Main</main-class>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
package org.toop;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
|
||||
/**
|
||||
* Utility class for configuring logging levels dynamically at runtime using Log4j 2.
|
||||
*
|
||||
* <p>Provides methods to enable or disable logs globally or per class, with support for specifying
|
||||
* log levels either via {@link Level} enums or string names.
|
||||
*/
|
||||
public final class Logging {
|
||||
|
||||
/** Disables all logging globally by setting the root logger level to {@link Level#OFF}. */
|
||||
public static void disableAllLogs() {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(Level.OFF);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/** Enables all logging globally by setting the root logger level to {@link Level#ALL}. */
|
||||
public static void enableAllLogs() {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(Level.ALL);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables global logging at a specific level by setting the root logger.
|
||||
*
|
||||
* @param level the logging level to enable for all logs
|
||||
*/
|
||||
public static void enableAllLogs(Level level) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(level);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies whether the provided string corresponds to a valid class name.
|
||||
*
|
||||
* @param className fully-qualified class name to check
|
||||
* @return true if the class exists, false otherwise
|
||||
*/
|
||||
private static boolean verifyStringIsActualClass(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helper to disable logs for a specific class by name.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
*/
|
||||
private static void disableLogsForClassInternal(String className) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
config.removeLogger(className);
|
||||
LoggerConfig specificConfig = new LoggerConfig(className, Level.OFF, false);
|
||||
config.addLogger(className, specificConfig);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables logs for a specific class.
|
||||
*
|
||||
* @param class_ the class for which logs should be disabled
|
||||
* @param <T> type of the class
|
||||
*/
|
||||
public static <T> void disableLogsForClass(Class<T> class_) {
|
||||
disableLogsForClassInternal(class_.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables logs for a class specified by fully-qualified name, if the class exists.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
*/
|
||||
public static void disableLogsForClass(String className) {
|
||||
if (verifyStringIsActualClass(className)) {
|
||||
disableLogsForClassInternal(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helper to enable logs for a specific class at a specific level.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param level logging level to set
|
||||
*/
|
||||
private static void enableLogsForClassInternal(String className, Level level) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig loggerConfig = config.getLoggers().get(className);
|
||||
if (loggerConfig == null) {
|
||||
loggerConfig = new LoggerConfig(className, level, false);
|
||||
config.addLogger(className, loggerConfig);
|
||||
} else {
|
||||
loggerConfig.setLevel(level);
|
||||
}
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class at a specific level.
|
||||
*
|
||||
* @param class_ class to configure
|
||||
* @param levelToLog the logging level to set
|
||||
* @param <T> type of the class
|
||||
*/
|
||||
public static <T> void enableLogsForClass(Class<T> class_, Level levelToLog) {
|
||||
enableLogsForClassInternal(class_.getName(), levelToLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class specified by name at a specific level, if the class exists.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param levelToLog the logging level to set
|
||||
*/
|
||||
public static void enableLogsForClass(String className, Level levelToLog) {
|
||||
if (verifyStringIsActualClass(className)) {
|
||||
enableLogsForClassInternal(className, levelToLog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class specified by name at a specific level using a string.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param levelToLog name of the logging level (e.g., "DEBUG", "INFO")
|
||||
*/
|
||||
public static void enableLogsForClass(String className, String levelToLog) {
|
||||
Level level = Level.valueOf(levelToLog.trim().toUpperCase());
|
||||
if (level != null && verifyStringIsActualClass(className)) {
|
||||
enableLogsForClassInternal(className, level);
|
||||
}
|
||||
}
|
||||
|
||||
/** Convenience methods for enabling logs at specific levels for classes. */
|
||||
public static <T> void enableAllLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.ALL);
|
||||
}
|
||||
|
||||
public static void enableAllLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.ALL);
|
||||
}
|
||||
|
||||
public static <T> void enableDebugLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.DEBUG);
|
||||
}
|
||||
|
||||
public static void enableDebugLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.DEBUG);
|
||||
}
|
||||
|
||||
public static <T> void enableErrorLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.ERROR);
|
||||
}
|
||||
|
||||
public static void enableErrorLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.ERROR);
|
||||
}
|
||||
|
||||
public static <T> void enableFatalLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.FATAL);
|
||||
}
|
||||
|
||||
public static void enableFatalLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.FATAL);
|
||||
}
|
||||
|
||||
public static <T> void enableInfoLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.INFO);
|
||||
}
|
||||
|
||||
public static void enableInfoLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.INFO);
|
||||
}
|
||||
|
||||
public static <T> void enableTraceLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.TRACE);
|
||||
}
|
||||
|
||||
public static void enableTraceLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.TRACE);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,6 @@
|
||||
package org.toop;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.backend.tictactoe.ServerManager;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.events.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.frontend.UI.LocalServerSelector;
|
||||
import org.toop.frontend.networking.NetworkingClientManager;
|
||||
|
||||
public class Main {
|
||||
private static final Logger logger = LogManager.getLogger(Main.class);
|
||||
private static boolean running = false;
|
||||
|
||||
public static void main(String[] args) throws ExecutionException, InterruptedException {
|
||||
// Logging.disableAllLogs();
|
||||
Logging.enableAllLogsForClass(EventRegistry.class);
|
||||
// Logging.enableLogsForClass(ServerManager.class, Level.ALL);
|
||||
// Logging.enableLogsForClass(TicTacToeServer.class, Level.ALL);
|
||||
// Logging.enableLogsForClass(TcpClient.class, Level.ALL);
|
||||
// Logging.enableLogsForClass(NetworkingClientManager.class, Level.ALL);
|
||||
|
||||
initSystems();
|
||||
registerEvents();
|
||||
|
||||
CompletableFuture<String> serverIdFuture = new CompletableFuture<>();
|
||||
GlobalEventBus.post(
|
||||
new Events.ServerEvents.StartServerRequest(5001, "tictactoe", serverIdFuture));
|
||||
var serverId = serverIdFuture.get();
|
||||
|
||||
var a = new MainTest();
|
||||
|
||||
javax.swing.SwingUtilities.invokeLater(LocalServerSelector::new);
|
||||
|
||||
}
|
||||
|
||||
private static void initSystems() {
|
||||
new ServerManager();
|
||||
new NetworkingClientManager();
|
||||
}
|
||||
|
||||
private static void registerEvents() {
|
||||
new EventPublisher().onEvent(Events.WindowEvents.OnQuitRequested.class).perform(_ -> quit());
|
||||
new EventPublisher().onEvent(Events.WindowEvents.OnMouseMove.class).perform(_ -> {});
|
||||
}
|
||||
|
||||
private static void quit() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public static void setRunning(boolean running) {
|
||||
Main.running = running;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
57
src/main/java/org/toop/app/GameBase.java
Normal file
57
src/main/java/org/toop/app/GameBase.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package org.toop.app;
|
||||
|
||||
// Todo: refactor
|
||||
public abstract class GameBase {
|
||||
public enum State {
|
||||
INVALID,
|
||||
|
||||
NORMAL,
|
||||
DRAW,
|
||||
WIN,
|
||||
}
|
||||
|
||||
public static char EMPTY = '-';
|
||||
|
||||
protected int size;
|
||||
public char[] grid;
|
||||
|
||||
protected Player[] players;
|
||||
public int currentPlayer;
|
||||
|
||||
public GameBase(int size, Player player1, Player player2) {
|
||||
this.size = size;
|
||||
grid = new char[size * size];
|
||||
|
||||
for (int i = 0; i < grid.length; i++) {
|
||||
grid[i] = EMPTY;
|
||||
}
|
||||
|
||||
players = new Player[2];
|
||||
players[0] = player1;
|
||||
players[1] = player2;
|
||||
|
||||
currentPlayer = 0;
|
||||
}
|
||||
|
||||
public boolean isInside(int index) {
|
||||
return index >= 0 && index < size * size;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public char[] getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public Player[] getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public Player getCurrentPlayer() {
|
||||
return players[currentPlayer];
|
||||
}
|
||||
|
||||
public abstract State play(int index);
|
||||
}
|
||||
20
src/main/java/org/toop/app/Player.java
Normal file
20
src/main/java/org/toop/app/Player.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package org.toop.app;
|
||||
|
||||
// Todo: refactor
|
||||
public class Player {
|
||||
String name;
|
||||
char symbol;
|
||||
|
||||
Player(String name, char symbol) {
|
||||
this.name = name;
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public char getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.UI;
|
||||
package org.toop.app.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalGameSelector">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.LocalGameSelector">
|
||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
@@ -1,10 +1,11 @@
|
||||
package org.toop.frontend.UI;
|
||||
package org.toop.app.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.frontend.games.LocalTicTacToe;
|
||||
import org.toop.app.tictactoe.LocalTicTacToe;
|
||||
import org.toop.app.tictactoe.gui.UIGameBoard;
|
||||
|
||||
public class LocalGameSelector extends JFrame {
|
||||
private static final Logger logger = LogManager.getLogger(LocalGameSelector.class);
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalServerSelector">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.LocalServerSelector">
|
||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.UI;
|
||||
package org.toop.app.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.RemoteGameSelector">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.RemoteGameSelector">
|
||||
<grid id="27dc6" binding="mainMenu" layout-manager="GridLayoutManager" row-count="10" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="10" bottom="10" right="10"/>
|
||||
<constraints>
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.UI;
|
||||
package org.toop.app.gui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Objects;
|
||||
@@ -7,11 +7,12 @@ import java.util.concurrent.ExecutionException;
|
||||
import javax.swing.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.eventbus.events.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.eventbus.events.NetworkEvents;
|
||||
import org.toop.frontend.games.LocalTicTacToe;
|
||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
||||
import org.toop.framework.eventbus.events.Events;
|
||||
import org.toop.framework.eventbus.GlobalEventBus;
|
||||
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||
import org.toop.app.tictactoe.LocalTicTacToe;
|
||||
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||
import org.toop.app.tictactoe.gui.UIGameBoard;
|
||||
|
||||
public class RemoteGameSelector {
|
||||
private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class);
|
||||
@@ -1,29 +1,25 @@
|
||||
package org.toop.frontend.games;
|
||||
package org.toop.app.tictactoe;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import jdk.jfr.Event;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.events.Events;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.eventbus.events.NetworkEvents;
|
||||
import org.toop.frontend.UI.UIGameBoard;
|
||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
||||
import org.toop.game.tictactoe.GameBase;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
import org.toop.framework.eventbus.events.Events;
|
||||
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||
import org.toop.app.tictactoe.gui.UIGameBoard;
|
||||
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||
import org.toop.app.GameBase;
|
||||
import org.toop.game.tictactoe.ai.MinMaxTicTacToe;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
/**
|
||||
* A representation of a local tic-tac-toe game. Calls are made to a server for information about
|
||||
* current game state. MOST OF THIS CODE IS TRASH, THROW IT OUT OF THE WINDOW AFTER DEMO.
|
||||
*/
|
||||
// Todo: refactor
|
||||
public class LocalTicTacToe { // TODO: Implement runnable
|
||||
private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.toop.game.tictactoe;
|
||||
package org.toop.app.tictactoe;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.app.GameBase;
|
||||
import org.toop.app.Player;
|
||||
import org.toop.backend.tictactoe.ParsedCommand;
|
||||
import org.toop.backend.tictactoe.TicTacToeServerCommand;
|
||||
|
||||
// Todo: refactor
|
||||
public class TicTacToe extends GameBase implements Runnable {
|
||||
|
||||
protected static final Logger logger = LogManager.getLogger(TicTacToe.class);
|
||||
139
src/main/java/org/toop/app/tictactoe/TicTacToeAI.java
Normal file
139
src/main/java/org/toop/app/tictactoe/TicTacToeAI.java
Normal file
@@ -0,0 +1,139 @@
|
||||
package org.toop.app.tictactoe;
|
||||
|
||||
import org.toop.app.GameBase;
|
||||
|
||||
// Todo: refactor
|
||||
public class TicTacToeAI {
|
||||
/**
|
||||
* This method tries to find the best move by seeing if it can set a winning move, if not, it
|
||||
* will do a minimax.
|
||||
*/
|
||||
public int findBestMove(TicTacToe game) {
|
||||
int bestVal = -100; // set bestVal to something impossible
|
||||
int bestMove = 10; // set bestMove to something impossible
|
||||
|
||||
int winningMove = -5;
|
||||
|
||||
boolean empty = true;
|
||||
for (char cell : game.grid) {
|
||||
if (!(cell == GameBase.EMPTY)) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) { // start in a random corner
|
||||
return switch ((int) (Math.random() * 4)) {
|
||||
case 1 -> 2;
|
||||
case 2 -> 6;
|
||||
case 3 -> 8;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
// simulate all possible moves on the field
|
||||
for (int i = 0; i < game.grid.length; i++) {
|
||||
|
||||
if (game.validateMove(i)) { // check if the move is legal here
|
||||
TicTacToe copyGame = game.copyBoard(); // make a copy of the game
|
||||
GameBase.State result = copyGame.play(i); // play a move on the copy board
|
||||
|
||||
int thisMoveValue;
|
||||
|
||||
if (result == GameBase.State.WIN) {
|
||||
return i; // just return right away if you can win on the next move
|
||||
}
|
||||
|
||||
for (int index = 0; index < game.grid.length; index++) {
|
||||
if (game.validateMove(index)) {
|
||||
TicTacToe opponentCopy = copyGame.copyBoard();
|
||||
GameBase.State opponentResult = opponentCopy.play(index);
|
||||
if (opponentResult == GameBase.State.WIN) {
|
||||
winningMove = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thisMoveValue =
|
||||
doMinimax(copyGame, game.movesLeft, false); // else look at other moves
|
||||
if (thisMoveValue
|
||||
> bestVal) { // if better move than the current best, change the move
|
||||
bestVal = thisMoveValue;
|
||||
bestMove = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (winningMove > -5) {
|
||||
return winningMove;
|
||||
}
|
||||
return bestMove; // return the best move when we've done everything
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simulates all the possible future moves in the game through a copy in search of
|
||||
* the best move.
|
||||
*/
|
||||
public int doMinimax(TicTacToe game, int depth, boolean maximizing) {
|
||||
boolean state = game.checkWin(); // check for a win (base case stuff)
|
||||
|
||||
if (state) {
|
||||
if (maximizing) {
|
||||
// it's the maximizing players turn and someone has won. this is not good, so return
|
||||
// a negative value
|
||||
return -10 + depth;
|
||||
} else {
|
||||
// it is the turn of the AI and it has won! this is good for us, so return a
|
||||
// positive value above 0
|
||||
return 10 - depth;
|
||||
}
|
||||
} else {
|
||||
boolean empty = false;
|
||||
for (char cell :
|
||||
game.grid) { // else, look at draw conditions. we check per cell if it's empty
|
||||
// or not
|
||||
if (cell == GameBase.EMPTY) {
|
||||
empty = true; // if a thing is empty, set to true
|
||||
break; // break the loop
|
||||
}
|
||||
}
|
||||
if (!empty
|
||||
|| depth == 0) { // if the grid is full or the depth is 0 (both meaning game is
|
||||
// over) return 0 for draw
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int bestVal; // set the value to the highest possible
|
||||
if (maximizing) { // it's the maximizing players turn, the AI
|
||||
bestVal = -100;
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
int value =
|
||||
doMinimax(copyGame, depth - 1, false); // keep going with the minimax
|
||||
bestVal =
|
||||
Math.max(
|
||||
bestVal,
|
||||
value); // select the best value for the maximizing player (the
|
||||
// AI)
|
||||
}
|
||||
}
|
||||
} else { // it's the minimizing players turn, the player
|
||||
bestVal = 100;
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
int value = doMinimax(copyGame, depth - 1, true); // keep miniMaxing
|
||||
bestVal =
|
||||
Math.min(
|
||||
bestVal,
|
||||
value); // select the lowest score for the minimizing player,
|
||||
// they want to make it hard for us
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestVal;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.UIGameBoard">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.tictactoe.gui.UIGameBoard">
|
||||
<grid id="27dc6" binding="tttPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="10" bottom="10" right="10"/>
|
||||
<constraints>
|
||||
@@ -1,12 +1,14 @@
|
||||
package org.toop.frontend.UI;
|
||||
package org.toop.app.tictactoe.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.frontend.games.LocalTicTacToe;
|
||||
import org.toop.game.tictactoe.GameBase;
|
||||
import org.toop.app.gui.LocalGameSelector;
|
||||
import org.toop.app.gui.RemoteGameSelector;
|
||||
import org.toop.app.tictactoe.LocalTicTacToe;
|
||||
import org.toop.app.GameBase;
|
||||
|
||||
public class UIGameBoard {
|
||||
private static final int TICTACTOE_SIZE = 3;
|
||||
@@ -1,3 +0,0 @@
|
||||
package org.toop.eventbus.events;
|
||||
|
||||
public interface IEvent {}
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.toop.eventbus.events;
|
||||
|
||||
public class ServerEvents {
|
||||
}
|
||||
202
src/main/java/org/toop/framework/Logging.java
Normal file
202
src/main/java/org/toop/framework/Logging.java
Normal file
@@ -0,0 +1,202 @@
|
||||
package org.toop.framework;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
|
||||
/**
|
||||
* Utility class for configuring logging levels dynamically at runtime using Log4j 2.
|
||||
*
|
||||
* <p>Provides methods to enable or disable logs globally or per class, with support for specifying
|
||||
* log levels either via {@link Level} enums or string names.
|
||||
*/
|
||||
// Todo: refactor
|
||||
public final class Logging {
|
||||
|
||||
/** Disables all logging globally by setting the root logger level to {@link Level#OFF}. */
|
||||
public static void disableAllLogs() {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(Level.OFF);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/** Enables all logging globally by setting the root logger level to {@link Level#ALL}. */
|
||||
public static void enableAllLogs() {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(Level.ALL);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables global logging at a specific level by setting the root logger.
|
||||
*
|
||||
* @param level the logging level to enable for all logs
|
||||
*/
|
||||
public static void enableAllLogs(Level level) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig rootLoggerConfig = config.getRootLogger();
|
||||
rootLoggerConfig.setLevel(level);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies whether the provided string corresponds to a valid class name.
|
||||
*
|
||||
* @param className fully-qualified class name to check
|
||||
* @return true if the class exists, false otherwise
|
||||
*/
|
||||
private static boolean verifyStringIsActualClass(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helper to disable logs for a specific class by name.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
*/
|
||||
private static void disableLogsForClassInternal(String className) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
config.removeLogger(className);
|
||||
LoggerConfig specificConfig = new LoggerConfig(className, Level.OFF, false);
|
||||
config.addLogger(className, specificConfig);
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables logs for a specific class.
|
||||
*
|
||||
* @param class_ the class for which logs should be disabled
|
||||
* @param <T> type of the class
|
||||
*/
|
||||
public static <T> void disableLogsForClass(Class<T> class_) {
|
||||
disableLogsForClassInternal(class_.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables logs for a class specified by fully-qualified name, if the class exists.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
*/
|
||||
public static void disableLogsForClass(String className) {
|
||||
if (verifyStringIsActualClass(className)) {
|
||||
disableLogsForClassInternal(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helper to enable logs for a specific class at a specific level.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param level logging level to set
|
||||
*/
|
||||
private static void enableLogsForClassInternal(String className, Level level) {
|
||||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
Configuration config = ctx.getConfiguration();
|
||||
LoggerConfig loggerConfig = config.getLoggers().get(className);
|
||||
if (loggerConfig == null) {
|
||||
loggerConfig = new LoggerConfig(className, level, false);
|
||||
config.addLogger(className, loggerConfig);
|
||||
} else {
|
||||
loggerConfig.setLevel(level);
|
||||
}
|
||||
ctx.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class at a specific level.
|
||||
*
|
||||
* @param class_ class to configure
|
||||
* @param levelToLog the logging level to set
|
||||
* @param <T> type of the class
|
||||
*/
|
||||
public static <T> void enableLogsForClass(Class<T> class_, Level levelToLog) {
|
||||
enableLogsForClassInternal(class_.getName(), levelToLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class specified by name at a specific level, if the class exists.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param levelToLog the logging level to set
|
||||
*/
|
||||
public static void enableLogsForClass(String className, Level levelToLog) {
|
||||
if (verifyStringIsActualClass(className)) {
|
||||
enableLogsForClassInternal(className, levelToLog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables logging for a class specified by name at a specific level using a string.
|
||||
*
|
||||
* @param className fully-qualified class name
|
||||
* @param levelToLog name of the logging level (e.g., "DEBUG", "INFO")
|
||||
*/
|
||||
public static void enableLogsForClass(String className, String levelToLog) {
|
||||
Level level = Level.valueOf(levelToLog.trim().toUpperCase());
|
||||
if (level != null && verifyStringIsActualClass(className)) {
|
||||
enableLogsForClassInternal(className, level);
|
||||
}
|
||||
}
|
||||
|
||||
/** Convenience methods for enabling logs at specific levels for classes. */
|
||||
public static <T> void enableAllLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.ALL);
|
||||
}
|
||||
|
||||
public static void enableAllLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.ALL);
|
||||
}
|
||||
|
||||
public static <T> void enableDebugLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.DEBUG);
|
||||
}
|
||||
|
||||
public static void enableDebugLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.DEBUG);
|
||||
}
|
||||
|
||||
public static <T> void enableErrorLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.ERROR);
|
||||
}
|
||||
|
||||
public static void enableErrorLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.ERROR);
|
||||
}
|
||||
|
||||
public static <T> void enableFatalLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.FATAL);
|
||||
}
|
||||
|
||||
public static void enableFatalLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.FATAL);
|
||||
}
|
||||
|
||||
public static <T> void enableInfoLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.INFO);
|
||||
}
|
||||
|
||||
public static void enableInfoLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.INFO);
|
||||
}
|
||||
|
||||
public static <T> void enableTraceLogsForClass(Class<T> class_) {
|
||||
enableLogsForClass(class_, Level.TRACE);
|
||||
}
|
||||
|
||||
public static void enableTraceLogsForClass(String className) {
|
||||
enableLogsForClass(className, Level.TRACE);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.toop.eventbus;
|
||||
package org.toop.framework.eventbus;
|
||||
|
||||
import org.toop.eventbus.events.EventWithUuid;
|
||||
import org.toop.eventbus.events.IEvent;
|
||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||
import org.toop.framework.eventbus.events.IEvent;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.toop.eventbus;
|
||||
package org.toop.framework.eventbus;
|
||||
|
||||
import org.toop.eventbus.events.EventWithUuid;
|
||||
import org.toop.eventbus.events.IEvent;
|
||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||
import org.toop.framework.eventbus.events.IEvent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.eventbus.events;
|
||||
package org.toop.framework.eventbus.events;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
package org.toop.eventbus.events;
|
||||
|
||||
import org.apache.logging.log4j.core.jmx.Server;
|
||||
package org.toop.framework.eventbus.events;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
@@ -0,0 +1,3 @@
|
||||
package org.toop.framework.eventbus.events;
|
||||
|
||||
public interface IEvent {}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.toop.eventbus.events;
|
||||
package org.toop.framework.eventbus.events;
|
||||
|
||||
import org.toop.backend.tictactoe.TicTacToeServer;
|
||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
||||
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||
|
||||
import java.lang.reflect.RecordComponent;
|
||||
import java.util.*;
|
||||
@@ -0,0 +1,4 @@
|
||||
package org.toop.framework.eventbus.events;
|
||||
|
||||
public class ServerEvents {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.networking;
|
||||
package org.toop.framework.networking;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.networking;
|
||||
package org.toop.framework.networking;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -7,8 +7,7 @@ import java.util.function.Supplier;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.toop.eventbus.EventPublisher;
|
||||
import org.toop.eventbus.GlobalEventBus;
|
||||
import org.toop.eventbus.events.NetworkEvents;
|
||||
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||
|
||||
public class NetworkingClientManager {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.toop.frontend.networking;
|
||||
package org.toop.framework.networking;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.Services">
|
||||
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.toop.frontend.UI;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class Services {}
|
||||
@@ -1,56 +0,0 @@
|
||||
package org.toop.game.tictactoe;
|
||||
|
||||
public abstract class GameBase {
|
||||
public enum State {
|
||||
INVALID,
|
||||
|
||||
NORMAL,
|
||||
DRAW,
|
||||
WIN,
|
||||
}
|
||||
|
||||
public static char EMPTY = '-';
|
||||
|
||||
protected int size;
|
||||
public char[] grid;
|
||||
|
||||
protected Player[] players;
|
||||
public int currentPlayer;
|
||||
|
||||
public GameBase(int size, Player player1, Player player2) {
|
||||
this.size = size;
|
||||
grid = new char[size * size];
|
||||
|
||||
for (int i = 0; i < grid.length; i++) {
|
||||
grid[i] = EMPTY;
|
||||
}
|
||||
|
||||
players = new Player[2];
|
||||
players[0] = player1;
|
||||
players[1] = player2;
|
||||
|
||||
currentPlayer = 0;
|
||||
}
|
||||
|
||||
public boolean isInside(int index) {
|
||||
return index >= 0 && index < size * size;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public char[] getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public Player[] getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public Player getCurrentPlayer() {
|
||||
return players[currentPlayer];
|
||||
}
|
||||
|
||||
public abstract State play(int index);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.toop.game.tictactoe;
|
||||
|
||||
public class Player {
|
||||
|
||||
String name;
|
||||
char symbol;
|
||||
|
||||
Player(String name, char symbol) {
|
||||
this.name = name;
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public char getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
package org.toop.game.tictactoe.ai;
|
||||
|
||||
import org.toop.game.tictactoe.GameBase;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
|
||||
public class MinMaxTicTacToe {
|
||||
|
||||
/**
|
||||
* This method tries to find the best move by seeing if it can set a winning move, if not, it
|
||||
* will do a minimax.
|
||||
*/
|
||||
public int findBestMove(TicTacToe game) {
|
||||
int bestVal = -100; // set bestVal to something impossible
|
||||
int bestMove = 10; // set bestMove to something impossible
|
||||
|
||||
int winningMove = -5;
|
||||
|
||||
boolean empty = true;
|
||||
for (char cell : game.grid) {
|
||||
if (!(cell == GameBase.EMPTY)) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) { // start in a random corner
|
||||
return switch ((int) (Math.random() * 4)) {
|
||||
case 1 -> 2;
|
||||
case 2 -> 6;
|
||||
case 3 -> 8;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
// simulate all possible moves on the field
|
||||
for (int i = 0; i < game.grid.length; i++) {
|
||||
|
||||
if (game.validateMove(i)) { // check if the move is legal here
|
||||
TicTacToe copyGame = game.copyBoard(); // make a copy of the game
|
||||
GameBase.State result = copyGame.play(i); // play a move on the copy board
|
||||
|
||||
int thisMoveValue;
|
||||
|
||||
if (result == GameBase.State.WIN) {
|
||||
return i; // just return right away if you can win on the next move
|
||||
}
|
||||
|
||||
for (int index = 0; index < game.grid.length; index++) {
|
||||
if (game.validateMove(index)) {
|
||||
TicTacToe opponentCopy = copyGame.copyBoard();
|
||||
GameBase.State opponentResult = opponentCopy.play(index);
|
||||
if (opponentResult == GameBase.State.WIN) {
|
||||
winningMove = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thisMoveValue =
|
||||
doMinimax(copyGame, game.movesLeft, false); // else look at other moves
|
||||
if (thisMoveValue
|
||||
> bestVal) { // if better move than the current best, change the move
|
||||
bestVal = thisMoveValue;
|
||||
bestMove = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (winningMove > -5) {
|
||||
return winningMove;
|
||||
}
|
||||
return bestMove; // return the best move when we've done everything
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simulates all the possible future moves in the game through a copy in search of
|
||||
* the best move.
|
||||
*/
|
||||
public int doMinimax(TicTacToe game, int depth, boolean maximizing) {
|
||||
boolean state = game.checkWin(); // check for a win (base case stuff)
|
||||
|
||||
if (state) {
|
||||
if (maximizing) {
|
||||
// it's the maximizing players turn and someone has won. this is not good, so return
|
||||
// a negative value
|
||||
return -10 + depth;
|
||||
} else {
|
||||
// it is the turn of the AI and it has won! this is good for us, so return a
|
||||
// positive value above 0
|
||||
return 10 - depth;
|
||||
}
|
||||
} else {
|
||||
boolean empty = false;
|
||||
for (char cell :
|
||||
game.grid) { // else, look at draw conditions. we check per cell if it's empty
|
||||
// or not
|
||||
if (cell == GameBase.EMPTY) {
|
||||
empty = true; // if a thing is empty, set to true
|
||||
break; // break the loop
|
||||
}
|
||||
}
|
||||
if (!empty
|
||||
|| depth == 0) { // if the grid is full or the depth is 0 (both meaning game is
|
||||
// over) return 0 for draw
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int bestVal; // set the value to the highest possible
|
||||
if (maximizing) { // it's the maximizing players turn, the AI
|
||||
bestVal = -100;
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
int value =
|
||||
doMinimax(copyGame, depth - 1, false); // keep going with the minimax
|
||||
bestVal =
|
||||
Math.max(
|
||||
bestVal,
|
||||
value); // select the best value for the maximizing player (the
|
||||
// AI)
|
||||
}
|
||||
}
|
||||
} else { // it's the minimizing players turn, the player
|
||||
bestVal = 100;
|
||||
for (int i = 0; i < game.grid.length; i++) { // loop through the grid
|
||||
if (game.validateMove(i)) {
|
||||
TicTacToe copyGame = game.copyBoard();
|
||||
copyGame.play(i); // play the move on a copy board
|
||||
int value = doMinimax(copyGame, depth - 1, true); // keep miniMaxing
|
||||
bestVal =
|
||||
Math.min(
|
||||
bestVal,
|
||||
value); // select the lowest score for the minimizing player,
|
||||
// they want to make it hard for us
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestVal;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.framework.Logging;
|
||||
|
||||
public class LoggingTest {
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package org.toop.eventbus;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.eventbus.events.EventWithUuid;
|
||||
import org.toop.framework.eventbus.GlobalEventBus;
|
||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
@@ -2,12 +2,10 @@ package org.toop.eventbus;
|
||||
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.eventbus.events.EventWithUuid;
|
||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.toop.eventbus;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.eventbus.events.EventWithUuid;
|
||||
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.app.GameBase;
|
||||
import org.toop.app.Player;
|
||||
|
||||
class GameBaseTest {
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.app.Player;
|
||||
|
||||
class PlayerTest {
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.game.tictactoe.GameBase;
|
||||
import org.toop.game.tictactoe.TicTacToe;
|
||||
import org.toop.app.GameBase;
|
||||
import org.toop.app.tictactoe.TicTacToe;
|
||||
|
||||
/** Unit tests for MinMaxTicTacToe AI. */
|
||||
public class MinMaxTicTacToeTest {
|
||||
|
||||
Reference in New Issue
Block a user