Added AI
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
@@ -11,6 +11,7 @@ import javafx.scene.text.FontWeight;
|
|||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
@@ -38,22 +39,9 @@ public class Engine extends Application {
|
|||||||
grid.setVgap(75);
|
grid.setVgap(75);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scene setStartingScene(){
|
|
||||||
scene = new Scene(grid, 900, 900);
|
|
||||||
grid.add(new javafx.scene.control.Label("Your Username"), 0, 0);
|
|
||||||
grid.add(new javafx.scene.control.TextField(), 1,0);
|
|
||||||
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
|
|
||||||
@Override
|
|
||||||
public void handle(MouseEvent mouseEvent) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Scene setPlayingScene() {
|
private Scene setPlayingScene() {
|
||||||
scene = new Scene(grid, 900, 900);
|
scene = new Scene(grid, 900, 900);
|
||||||
scene.getStylesheets().add("res/TicTacToe_Client.css");
|
scene.getStylesheets().add("game/TicTacToe_Client.css");
|
||||||
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
|
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MouseEvent event) {
|
public void handle(MouseEvent event) {
|
||||||
@@ -149,7 +137,8 @@ public class Engine extends Application {
|
|||||||
primaryStage.setTitle("Test");
|
primaryStage.setTitle("Test");
|
||||||
primaryStage.setResizable(true);
|
primaryStage.setResizable(true);
|
||||||
this.initializeGrid();
|
this.initializeGrid();
|
||||||
primaryStage.setScene(this.setPlayingScene());
|
this.scene = this.setPlayingScene();
|
||||||
|
primaryStage.setScene(scene);
|
||||||
primaryStage.sizeToScene();
|
primaryStage.sizeToScene();
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 121 KiB |
@@ -1,6 +1,6 @@
|
|||||||
import logging.LogType;
|
import logging.LogType;
|
||||||
import logging.ServerLogger;
|
import logging.ServerLogger;
|
||||||
import res.TicTacToe_GameRules;
|
import game.TicTacToe_GameRules;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@@ -201,12 +201,16 @@ public class TicTacToe_Server {
|
|||||||
sendGameState();
|
sendGameState();
|
||||||
serverLogger.printLog("Trigger computer move", LogType.Log);
|
serverLogger.printLog("Trigger computer move", LogType.Log);
|
||||||
ticTacToe_gameRules.makeComputerMove();
|
ticTacToe_gameRules.makeComputerMove();
|
||||||
|
Thread.sleep(500);
|
||||||
|
if (ticTacToe_gameRules.gameEnded()){
|
||||||
|
sendGameState();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
this.onGameEnd();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
outstreams.get(client).writeUTF("opponentMove");
|
outstreams.get(client).writeUTF("opponentMove");
|
||||||
outstreams.get(client).flush();
|
outstreams.get(client).flush();
|
||||||
sendGameState();
|
sendGameState();
|
||||||
if (ticTacToe_gameRules.gameEnded()){
|
|
||||||
this.onGameEnd();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,6 +221,8 @@ public class TicTacToe_Server {
|
|||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
208
Server/src/ai/MinMax.java
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package ai;
|
||||||
|
// Java program to find the
|
||||||
|
// next optimal move for a player
|
||||||
|
public class MinMax
|
||||||
|
{
|
||||||
|
static char player = 'o', opponent = 'x';
|
||||||
|
|
||||||
|
// This function returns true if there are moves
|
||||||
|
// remaining on the board. It returns false if
|
||||||
|
// there are no moves left to play.
|
||||||
|
static Boolean isMovesLeft(char board[][])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
if (board[i][j] == '-')
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the evaluation function as discussed
|
||||||
|
// in the previous article ( http://goo.gl/sJgv68 )
|
||||||
|
static int evaluate(char b[][])
|
||||||
|
{
|
||||||
|
// Checking for Rows for X or O victory.
|
||||||
|
for (int row = 0; row < 3; row++)
|
||||||
|
{
|
||||||
|
if (b[row][0] == b[row][1] &&
|
||||||
|
b[row][1] == b[row][2])
|
||||||
|
{
|
||||||
|
if (b[row][0] == player)
|
||||||
|
return +10;
|
||||||
|
else if (b[row][0] == opponent)
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking for Columns for X or O victory.
|
||||||
|
for (int col = 0; col < 3; col++)
|
||||||
|
{
|
||||||
|
if (b[0][col] == b[1][col] &&
|
||||||
|
b[1][col] == b[2][col])
|
||||||
|
{
|
||||||
|
if (b[0][col] == player)
|
||||||
|
return +10;
|
||||||
|
|
||||||
|
else if (b[0][col] == opponent)
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking for Diagonals for X or O victory.
|
||||||
|
if (b[0][0] == b[1][1] && b[1][1] == b[2][2])
|
||||||
|
{
|
||||||
|
if (b[0][0] == player)
|
||||||
|
return +10;
|
||||||
|
else if (b[0][0] == opponent)
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b[0][2] == b[1][1] && b[1][1] == b[2][0])
|
||||||
|
{
|
||||||
|
if (b[0][2] == player)
|
||||||
|
return +10;
|
||||||
|
else if (b[0][2] == opponent)
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else if none of them have won then return 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the minimax function. It considers all
|
||||||
|
// the possible ways the game can go and returns
|
||||||
|
// the value of the board
|
||||||
|
static int minimax(char board[][],
|
||||||
|
int depth, Boolean isMax)
|
||||||
|
{
|
||||||
|
int score = evaluate(board);
|
||||||
|
|
||||||
|
// If Maximizer has won the game
|
||||||
|
// return his/her evaluated score
|
||||||
|
if (score == 10)
|
||||||
|
return score;
|
||||||
|
|
||||||
|
// If Minimizer has won the game
|
||||||
|
// return his/her evaluated score
|
||||||
|
if (score == -10)
|
||||||
|
return score;
|
||||||
|
|
||||||
|
// If there are no more moves and
|
||||||
|
// no winner then it is a tie
|
||||||
|
if (isMovesLeft(board) == false)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// If this maximizer's move
|
||||||
|
if (isMax)
|
||||||
|
{
|
||||||
|
int best = -1000;
|
||||||
|
|
||||||
|
// Traverse all cells
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
// Check if cell is empty
|
||||||
|
if (board[i][j]=='-')
|
||||||
|
{
|
||||||
|
// Make the move
|
||||||
|
board[i][j] = player;
|
||||||
|
|
||||||
|
// Call minimax recursively and choose
|
||||||
|
// the maximum value
|
||||||
|
best = Math.max(best, minimax(board,
|
||||||
|
depth + 1, !isMax));
|
||||||
|
|
||||||
|
// Undo the move
|
||||||
|
board[i][j] = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this minimizer's move
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int best = 1000;
|
||||||
|
|
||||||
|
// Traverse all cells
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
// Check if cell is empty
|
||||||
|
if (board[i][j] == '-')
|
||||||
|
{
|
||||||
|
// Make the move
|
||||||
|
board[i][j] = opponent;
|
||||||
|
|
||||||
|
// Call minimax recursively and choose
|
||||||
|
// the minimum value
|
||||||
|
best = Math.min(best, minimax(board,
|
||||||
|
depth + 1, !isMax));
|
||||||
|
|
||||||
|
// Undo the move
|
||||||
|
board[i][j] = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will return the best possible
|
||||||
|
// move for the player
|
||||||
|
public int findBestMove(char board[][])
|
||||||
|
{
|
||||||
|
int bestVal = -1000;
|
||||||
|
int row = -1;
|
||||||
|
int col = -1;
|
||||||
|
|
||||||
|
// Traverse all cells, evaluate minimax function
|
||||||
|
// for all empty cells. And return the cell
|
||||||
|
// with optimal value.
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
// Check if cell is empty
|
||||||
|
if (board[i][j] == '-')
|
||||||
|
{
|
||||||
|
// Make the move
|
||||||
|
board[i][j] = player;
|
||||||
|
|
||||||
|
// compute evaluation function for this
|
||||||
|
// move.
|
||||||
|
int moveVal = minimax(board, 0, false);
|
||||||
|
|
||||||
|
// Undo the move
|
||||||
|
board[i][j] = '-';
|
||||||
|
|
||||||
|
// If the value of the current move is
|
||||||
|
// more than the best value, then update
|
||||||
|
// best/
|
||||||
|
if (moveVal > bestVal)
|
||||||
|
{
|
||||||
|
row = i;
|
||||||
|
col = j;
|
||||||
|
bestVal = moveVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return col*3+row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[][] convertBoard(String gameState){
|
||||||
|
char board[][] = new char[3][3];
|
||||||
|
for (int i = 0; i < gameState.length(); i++) {
|
||||||
|
int column = i / 3;
|
||||||
|
int row = i % 3;
|
||||||
|
board[row][column] = gameState.charAt(i);
|
||||||
|
}
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
package res;
|
package game;
|
||||||
|
|
||||||
|
import ai.MinMax;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class TicTacToe_GameRules {
|
public class TicTacToe_GameRules {
|
||||||
|
|
||||||
private String gameState;
|
private String gameState;
|
||||||
private Integer[][] board;
|
private Integer[][] board;
|
||||||
|
private MinMax ai;
|
||||||
Point startWin, endWin;
|
Point startWin, endWin;
|
||||||
|
|
||||||
public TicTacToe_GameRules(){
|
public TicTacToe_GameRules(){
|
||||||
gameState = "---------";
|
gameState = "---------";
|
||||||
|
ai = new MinMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetGameState() {
|
public void resetGameState() {
|
||||||
@@ -55,13 +58,9 @@ public class TicTacToe_GameRules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void makeComputerMove(){
|
public void makeComputerMove(){
|
||||||
LinkedList<Integer> emptySpaces = getEmptySpaces();
|
int index = ai.findBestMove(ai.convertBoard(this.getGameState()));
|
||||||
if (emptySpaces.size() > 0) {
|
|
||||||
Random random = new Random();
|
|
||||||
int index = emptySpaces.get(random.nextInt(emptySpaces.size()));
|
|
||||||
makeMoveOnBoard(index, 1);
|
makeMoveOnBoard(index, 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private LinkedList<Integer> getEmptySpaces(){
|
private LinkedList<Integer> getEmptySpaces(){
|
||||||
LinkedList<Integer> emptySpaces = new LinkedList<>();
|
LinkedList<Integer> emptySpaces = new LinkedList<>();
|
||||||
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 137 KiB |
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cp ~/Code/ArcadeMachine/out/artifacts/Client_jar/Client.jar ~/Code/ArcadeMachine/deployment/client/package
|
cp ~/Code/ArcadeMachine/out/artifacts/Client_jar/Client.jar ~/Code/ArcadeMachine/deployment/client/package
|
||||||
cd /var/www/html
|
cd /var/www/html
|
||||||
scp * root@server:/var/www/html/
|
scp index.css index.html root@server:/var/www/html/
|
||||||
scp files/* root@server:/var/www/html/files
|
scp files/Client.jar files/startClient.bat root@server:/var/www/html/files
|
||||||
ssh root@server systemctl restart apache2
|
ssh root@server systemctl restart apache
|
||||||
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 130 KiB |