From 8fc1867d9e005cb1aecc6e9c742cc894bd75621b Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 21 Feb 2021 23:01:30 +0100 Subject: [PATCH] Made game playable --- Client/Client.iml | 1 + Client/src/game/TicTacToe_Client.java | 55 ++++-- Client/src/networking/Client.java | 18 +- Server/res/META-INF/MANIFEST.MF | 2 +- Server/src/META-INF/MANIFEST.MF | 2 +- Server/src/game/TicTacToe_Server.java | 119 ++++++++++- Server/src/networking/MultiPlayerServer.java | 185 ++++++++++++++++++ Server/src/networking/SinglePlayerServer.java | 185 ++++++++++++++++++ Server/src/tests/GenerateAllGameStates.java | 107 ++++++++++ 9 files changed, 653 insertions(+), 21 deletions(-) create mode 100644 Server/src/networking/MultiPlayerServer.java create mode 100644 Server/src/networking/SinglePlayerServer.java create mode 100644 Server/src/tests/GenerateAllGameStates.java diff --git a/Client/Client.iml b/Client/Client.iml index 17ba59d..de33418 100644 --- a/Client/Client.iml +++ b/Client/Client.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/Client/src/game/TicTacToe_Client.java b/Client/src/game/TicTacToe_Client.java index aee4a00..098836a 100644 --- a/Client/src/game/TicTacToe_Client.java +++ b/Client/src/game/TicTacToe_Client.java @@ -6,16 +6,22 @@ import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.input.MouseEvent; import javafx.scene.layout.GridPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Line; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.stage.Stage; import networking.Client; +import java.util.Arrays; +import java.util.LinkedList; + public class TicTacToe_Client extends Application { GridPane grid; Client client; + Scene scene; private void initializeGrid(){ grid = new GridPane(); @@ -23,7 +29,6 @@ public class TicTacToe_Client extends Application { grid.setAlignment(Pos.CENTER); grid.setHgap(150); grid.setVgap(75); - grid.setGridLinesVisible(true); } private void drawCross(int column, int row){ @@ -39,8 +44,8 @@ public class TicTacToe_Client extends Application { } private void drawEmptyField(int column, int row) { - Text emptyField = new Text(" "); - emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); + Text emptyField = new Text(" "); + emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 220)); grid.add(emptyField, column, row); } @@ -64,27 +69,49 @@ public class TicTacToe_Client extends Application { } private Scene setScene(){ - Scene scene = new Scene(grid, 900, 900); + scene = new Scene(grid, 900, 900); scene.getStylesheets().add (TicTacToe_Client.class.getResource("TicTacToe_Client.css").toExternalForm()); scene.setOnMousePressed(new EventHandler() { @Override public void handle(MouseEvent event) { - client.sendToServer("update"); - client.sendToServer(String.format("%f|%f", event.getX(), event.getY())); - String gameState = client.getResponse(); - if (gameState.length() == 9) { - drawBoard(gameState); - } else { - int column = (int) event.getX() / 300; - int row = (int) event.getY() / 300; - System.err.printf("You are not allowed to place at %f|%f%n", column, row); - } + onMouseClick(event); } }); return scene; } + private void onMouseClick(MouseEvent event){ + client.sendToServer("update"); + client.sendToServer(String.format("%f|%f", event.getX(), event.getY())); + String gameState = client.getResponse(); + if (gameState.length() == 9) { + drawBoard(gameState); + if (!client.getGameEnded()){ + gameState = client.getResponse(); + drawBoard(gameState); + } else { + LinkedList winCoordinates = new LinkedList<>(); + String response = client.getResponse(); + for (String s: Arrays.copyOfRange(response.split(";"),0, 4)) { + winCoordinates.add(Integer.valueOf(s) * 300); + } + this.drawWinningLine(winCoordinates); + client.exitProcess(); + } + } else { + int column = (int) event.getX() / 300; + int row = (int) event.getY() / 300; + System.err.printf("You are not allowed to place at %d|%d%n", column, row); + } + } + + private void drawWinningLine(LinkedListwinCoordinates){ + Line winningLine = new Line(winCoordinates.get(0), winCoordinates.get(1), winCoordinates.get(2), winCoordinates.get(3)); + winningLine.setFill(Color.RED); + grid.add(winningLine, winCoordinates.get(0)/300, winCoordinates.get(1)/300, 3, 3); + } + @Override public void start(Stage primaryStage) { client = new Client("localhost", 2589, "TestClient"); diff --git a/Client/src/networking/Client.java b/Client/src/networking/Client.java index ebb1a7c..a2bc568 100644 --- a/Client/src/networking/Client.java +++ b/Client/src/networking/Client.java @@ -3,7 +3,6 @@ package networking; import logging.ClientLogger; import logging.LogType; -import javax.swing.*; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -75,12 +74,29 @@ public class Client { return ""; } + public boolean getBooleanResponse(String value){ + try { + boolean booleanResponse = in.readBoolean(); + clientLogger.printLog(String.format(value + ": %b", booleanResponse), serverName, booleanResponse, LogType.Log); + return booleanResponse; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + public String getGameState() { this.sendToServer("gameState"); String gameState = this.getResponse(); return gameState; } + public boolean getGameEnded() { + this.sendToServer("gameEnded"); + boolean gameEnded = this.getBooleanResponse("Game ended"); + return gameEnded; + } + public void exitProcess(){ try { out.writeUTF("exit()"); diff --git a/Server/res/META-INF/MANIFEST.MF b/Server/res/META-INF/MANIFEST.MF index 9ae8574..b764489 100644 --- a/Server/res/META-INF/MANIFEST.MF +++ b/Server/res/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: networking.Server +Main-Class: networking.SinglePlayerServer diff --git a/Server/src/META-INF/MANIFEST.MF b/Server/src/META-INF/MANIFEST.MF index 9ae8574..b764489 100644 --- a/Server/src/META-INF/MANIFEST.MF +++ b/Server/src/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: networking.Server +Main-Class: networking.SinglePlayerServer diff --git a/Server/src/game/TicTacToe_Server.java b/Server/src/game/TicTacToe_Server.java index f7220fa..f21b925 100644 --- a/Server/src/game/TicTacToe_Server.java +++ b/Server/src/game/TicTacToe_Server.java @@ -1,10 +1,15 @@ package game; +import java.awt.*; import java.nio.charset.StandardCharsets; +import java.util.LinkedList; +import java.util.Random; public class TicTacToe_Server { private String gameState; + private Integer[][] board; + Point startWin, endWin; public TicTacToe_Server(){ gameState = "---------"; @@ -18,24 +23,130 @@ public class TicTacToe_Server { return gameState; } + private void makeMoveOnBoard(int index, int player){ + byte[] gameStateBytes = gameState.getBytes(); + if (player == 0){ + gameStateBytes[index] = (byte) 'x'; + } else if (player == 1) { + gameStateBytes[index] = (byte) 'o'; + } + gameState = new String(gameStateBytes, StandardCharsets.UTF_8); + board = this.convertToNumbers(gameState); + } + public int makeClientMove(String input) { int column = Double.valueOf(input.split("\\|")[0]).intValue() / 300; int row = Double.valueOf(input.split("\\|")[1]).intValue() / 300; int index = column * 3 + row; if (isLegalMove(column, row)) { - byte[] gameStateBytes = gameState.getBytes(); - gameStateBytes[index] = (byte) 'x'; - gameState = new String(gameStateBytes, StandardCharsets.UTF_8); + makeMoveOnBoard(index, 0); return 200; } else { return 404; } } + public void makeServerMove(){ + LinkedList emptySpaces = getEmptySpaces(); + if (emptySpaces.size() > 0) { + Random random = new Random(); + int index = emptySpaces.get(random.nextInt(emptySpaces.size())); + makeMoveOnBoard(index, 1); + } + } + + private LinkedList getEmptySpaces(){ + LinkedList emptySpaces = new LinkedList<>(); + for (int column = 0; column < 3; column++){ + for (int row = 0; row < 3; row++){ + if (isLegalMove(column, row)){ + emptySpaces.add(column * 3 + row); + } + } + } + return emptySpaces; + } + private boolean isLegalMove(int column, int row){ int index = column * 3 + row; return gameState.charAt(index) == '-'; } -} + private Integer[][] convertToNumbers(String gameState){ + Integer[][] board = new Integer[3][3]; + for (int i = 0; i < 3; i++){ + for (int k = 0; k < 3; k++){ + char currentChar = gameState.charAt(i*3+k); + if (currentChar == 'x'){ + board[i][k] = 1; + } else if (currentChar == 'o'){ + board[i][k] = -1; + } else if (currentChar == '-'){ + board[i][k] = 0; + } + } + } + return board; + } + + private boolean diagonalWin(){ + int sumLeftUp = 0; + int sumLeftDown = 0; + for (int i = 0; i < 3; i++){ + sumLeftUp += board[i][i]; + sumLeftDown += board[i][2-i]; + } + if (sumLeftDown == 3 || sumLeftDown == -3){ + startWin = new Point(2,0); + endWin = new Point(0,2); + return true; + } else if (sumLeftUp == 3 || sumLeftUp == -3){ + startWin = new Point(0,0); + endWin = new Point(2,2); + return true; + } else { + return false; + } + } + + private boolean horizontalWin(){ + for (int row = 0; row < 3; row++){ + int sum = 0; + for (int column = 0; column < 3; column++){ + sum += board[row][column]; + } + if (sum == 3 || sum == -3){ + startWin = new Point(row, 0); + endWin = new Point(row, 0); + return true; + } + } + return false; + } + + private boolean verticalWin(){ + for (int column = 0; column < 3; column++){ + int sum = 0; + for (int row = 0; row < 3; row++){ + sum += board[row][column]; + } + if (sum == 3 || sum == -3){ + startWin = new Point(0, column); + endWin = new Point(2, column); + return true; + } + } + return false; + } + + public boolean gameEnded(){ + return horizontalWin() || verticalWin() || diagonalWin(); + } + + + public Point[] getWinCoordinates(){ + return new Point[]{startWin, endWin}; + } + +} \ No newline at end of file diff --git a/Server/src/networking/MultiPlayerServer.java b/Server/src/networking/MultiPlayerServer.java new file mode 100644 index 0000000..d369556 --- /dev/null +++ b/Server/src/networking/MultiPlayerServer.java @@ -0,0 +1,185 @@ +package networking; + +import game.TicTacToe_Server; +import logging.LogType; +import logging.ServerLogger; + +import java.awt.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.HashMap; +import java.util.Scanner; + +public class MultiPlayerServer { + private ServerSocket serverSocket; + private HashMap clients; + private HashMap clientNames; + private HashMap outstreams; + private HashMap instreams; + private TicTacToe_Server ticTacToe_server; + private ServerLogger serverLogger; + private Scanner scanner; + private int requiredConnections; + + public MultiPlayerServer(int port) { + try { + serverSocket = new ServerSocket(port); + clients = new HashMap<>(); + clientNames = new HashMap<>(); + outstreams = new HashMap<>(); + instreams = new HashMap<>(); + ticTacToe_server = new TicTacToe_Server(); + scanner = new Scanner(System.in); + serverLogger = new ServerLogger(); + requiredConnections = 2; + + serverLogger.printLog("Server started successfully", LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void connectClients() { + try { + int id = 0; + serverLogger.printLog(String.format("Waiting for %d clients to connect ...", requiredConnections), LogType.Log); + while (clients.size() < requiredConnections) { + Socket momentaryClient = serverSocket.accept(); + clients.put(id, momentaryClient); + outstreams.put(momentaryClient, new DataOutputStream(momentaryClient.getOutputStream())); + instreams.put(momentaryClient, new DataInputStream(momentaryClient.getInputStream())); + id++; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void handshake() { + for (Socket client : clients.values()) { + try { + int handshakeValue = instreams.get(client).readInt(); + if (handshakeValue == 165313125) { + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + clientNames.put(client, instreams.get(client).readUTF()); + outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress() + ":" + serverSocket.getLocalPort()); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log); + } else { + outstreams.get(client).writeInt(403); + outstreams.get(client).flush(); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void ticTacToe_gameloop() { + for (Socket client : clients.values()) { + try { + while (!client.isClosed()) { + String message = instreams.get(client).readUTF(); + serverLogger.printLog(message, clientNames.get(client), LogType.Message); + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); + this.gameFlow(message, client); + } + } catch (IOException e) { + e.printStackTrace(); + try { + client.close(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + } + } + } + + public void gameFlow(String input, Socket client) { + switch (input) { + case "gameState": + try { + outstreams.get(client).writeUTF(ticTacToe_server.getGameState()); + outstreams.get(client).flush(); + serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log); + break; + } catch (IOException e) { + e.printStackTrace(); + } + + case "update": + try { + String position = instreams.get(client).readUTF(); + serverLogger.printLog(position, clientNames.get(client), LogType.Message); + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); + int verificationCode = ticTacToe_server.makeClientMove(position); + if (verificationCode == 200) { + String gameState = ticTacToe_server.getGameState(); + outstreams.get(client).writeUTF(gameState); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); + break; + } else { + outstreams.get(client).writeUTF(" "); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error); + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + + case "gameEnded": + try { + boolean gameEnded = ticTacToe_server.gameEnded(); + outstreams.get(client).writeBoolean(gameEnded); + if (gameEnded) { + String coordinates = ""; + for (Point point : ticTacToe_server.getWinCoordinates()) { + coordinates += point.x + ";" + point.y + ";"; + } + outstreams.get(client).writeUTF(coordinates); + break; + } else { + ticTacToe_server.makeServerMove(); + String gameState = ticTacToe_server.getGameState(); + outstreams.get(client).writeUTF(gameState); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + + case "exit()": + try { + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + outstreams.get(client).close(); + instreams.get(client).close(); + client.close(); + serverLogger.printLog(String.format("%s closed the connection", clientNames.get(client)), LogType.Log); + break; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + MultiPlayerServer server = new MultiPlayerServer(2589); + server.connectClients(); + server.handshake(); + server.ticTacToe_gameloop(); + } +} diff --git a/Server/src/networking/SinglePlayerServer.java b/Server/src/networking/SinglePlayerServer.java new file mode 100644 index 0000000..b75cd1b --- /dev/null +++ b/Server/src/networking/SinglePlayerServer.java @@ -0,0 +1,185 @@ +package networking; + +import game.TicTacToe_Server; +import logging.LogType; +import logging.ServerLogger; + +import java.awt.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.HashMap; +import java.util.Scanner; + +public class SinglePlayerServer { + private ServerSocket serverSocket; + private HashMap clients; + private HashMap clientNames; + private HashMap outstreams; + private HashMap instreams; + private TicTacToe_Server ticTacToe_server; + private ServerLogger serverLogger; + private Scanner scanner; + private int requiredConnections; + + public SinglePlayerServer(int port){ + try { + serverSocket = new ServerSocket(port); + clients = new HashMap<>(); + clientNames = new HashMap<>(); + outstreams = new HashMap<>(); + instreams = new HashMap<>(); + ticTacToe_server = new TicTacToe_Server(); + scanner = new Scanner(System.in); + serverLogger = new ServerLogger(); + requiredConnections = 1; + + serverLogger.printLog("Server started successfully", LogType.Log); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void connectClients(){ + try { + int id = 0; + serverLogger.printLog(String.format("Waiting for %d clients to connect ...", requiredConnections), LogType.Log); + while(clients.size() < requiredConnections) { + Socket momentaryClient = serverSocket.accept(); + clients.put(id, momentaryClient); + outstreams.put(momentaryClient, new DataOutputStream(momentaryClient.getOutputStream())); + instreams.put(momentaryClient, new DataInputStream(momentaryClient.getInputStream())); + id++; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void handshake(){ + for (Socket client: clients.values()) { + try { + int handshakeValue = instreams.get(client).readInt(); + if (handshakeValue == 165313125) { + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + clientNames.put(client, instreams.get(client).readUTF()); + outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress()+":"+serverSocket.getLocalPort()); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log); + } else { + outstreams.get(client).writeInt(403); + outstreams.get(client).flush(); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void ticTacToe_gameloop(){ + for (Socket client: clients.values()) { + try { + while (!client.isClosed()) { + String message = instreams.get(client).readUTF(); + serverLogger.printLog(message, clientNames.get(client), LogType.Message); + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); + this.gameFlow(message, client); + } + } catch (IOException e) { + e.printStackTrace(); + try { + client.close(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + } + } + } + + public void gameFlow(String input, Socket client){ + switch (input){ + case "gameState": + try { + outstreams.get(client).writeUTF(ticTacToe_server.getGameState()); + outstreams.get(client).flush(); + serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log); + break; + } catch (IOException e) { + e.printStackTrace(); + } + + case "update": + try { + String position = instreams.get(client).readUTF(); + serverLogger.printLog(position, clientNames.get(client), LogType.Message); + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log); + int verificationCode = ticTacToe_server.makeClientMove(position); + if (verificationCode == 200) { + String gameState = ticTacToe_server.getGameState(); + outstreams.get(client).writeUTF(gameState); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); + break; + } else { + outstreams.get(client).writeUTF(" "); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error); + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + + case "gameEnded": + try { + boolean gameEnded = ticTacToe_server.gameEnded(); + outstreams.get(client).writeBoolean(gameEnded); + if (gameEnded) { + String coordinates = ""; + for (Point point: ticTacToe_server.getWinCoordinates()) { + coordinates += point.x + ";" + point.y + ";"; + } + outstreams.get(client).writeUTF(coordinates); + break; + } else { + ticTacToe_server.makeServerMove(); + String gameState = ticTacToe_server.getGameState(); + outstreams.get(client).writeUTF(gameState); + outstreams.get(client).flush(); + serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log); + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + + case "exit()": + try { + outstreams.get(client).writeInt(200); + outstreams.get(client).flush(); + outstreams.get(client).close(); + instreams.get(client).close(); + client.close(); + serverLogger.printLog(String.format("%s closed the connection",clientNames.get(client)), LogType.Log); + break; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + SinglePlayerServer server = new SinglePlayerServer(2589); + server.connectClients(); + server.handshake(); + server.ticTacToe_gameloop(); + } +} \ No newline at end of file diff --git a/Server/src/tests/GenerateAllGameStates.java b/Server/src/tests/GenerateAllGameStates.java new file mode 100644 index 0000000..9aaea71 --- /dev/null +++ b/Server/src/tests/GenerateAllGameStates.java @@ -0,0 +1,107 @@ +package tests; + +import java.util.LinkedList; + +public class GenerateAllGameStates { + + public static void main(String[] args) { + GenerateAllGameStates testGame = new GenerateAllGameStates(); + LinkedList gameStates = testGame.getAllPossibleBoards(); + System.out.printf("All possible boards: %d%n", gameStates.size()); + LinkedList gameStateBoards = new LinkedList<>(); + for (String gameState: gameStates) { + gameStateBoards.add(testGame.convertToNumbers(gameState)); + } + } + + private Integer[][] convertToNumbers(String gameState){ + Integer[][] board = new Integer[3][3]; + for (int i = 0; i < 3; i++){ + for (int k = 0; k < 3; k++){ + char currentChar = gameState.charAt(i*3+k); + if (currentChar == 'x'){ + board[i][k] = 1; + } else if (currentChar == 'o'){ + board[i][k] = -1; + } else if (currentChar == '-'){ + board[i][k] = 0; + } + } + } + return board; + } + + private boolean diagonalWin(Integer[][] board){ + int sumLeftUp = 0; + int sumLeftDown = 0; + for (int i = 0; i < 3; i++){ + sumLeftUp += board[i][i]; + sumLeftDown += board[i][2-i]; + } + return (sumLeftDown == 3 || sumLeftDown == -3) || (sumLeftUp == 3 || sumLeftUp == -3); + } + + private boolean horizontalWin(Integer[][] board){ + for (int row = 0; row < 3; row++){ + int sum = 0; + for (int column = 0; column < 3; column++){ + sum += board[row][column]; + } + if (sum == 3 || sum == -3){ + return true; + } + } + return false; + } + + private boolean verticalWin(Integer[][] board){ + for (int column = 0; column < 3; column++){ + int sum = 0; + for (int row = 0; row < 3; row++){ + sum += board[row][column]; + } + if (sum == 3 || sum == -3){ + return true; + } + } + return false; + } + + public LinkedList getAllPossibleBoards(){ + LinkedList possibleGameStates = new LinkedList<>(); + + String[] possibleChars = new String[]{"x","o","-"}; + + for (int c1r1 = 0; c1r1 < 3; c1r1++){ + String s1 = possibleChars[c1r1]; + for (int c1r2 = 0; c1r2 < 3; c1r2++){ + String s2 = possibleChars[c1r2]; + for (int c1r3 = 0; c1r3 < 3; c1r3++){ + String s3 = possibleChars[c1r3]; + for (int c2r1 = 0; c2r1 < 3; c2r1++){ + String s4 = possibleChars[c2r1]; + for (int c2r2 = 0; c2r2 < 3; c2r2++){ + String s5 = possibleChars[c2r2]; + for(int c2r3 = 0; c2r3 <3; c2r3++){ + String s6 = possibleChars[c2r3]; + for (int c3r1 = 0; c3r1 < 3; c3r1++){ + String s7 = possibleChars[c3r1]; + for (int c3r2 = 0; c3r2 < 3; c3r2++){ + String s8 = possibleChars[c3r2]; + for (int c3r3 = 0; c3r3 < 3; c3r3++){ + String s9 = possibleChars[c3r3]; + String gameState = s1+s2+s3+s4+s5+s6+s7+s8+s9; + possibleGameStates.add(gameState); + } + } + } + } + } + } + } + } + } + return possibleGameStates; + } + +}