From 884ca501ff0ed2cb1d4bfaa2cc8173c1071fbcdb Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 13 Feb 2021 17:32:26 +0100 Subject: [PATCH] Code upload --- .idea/.gitignore | 3 + .idea/misc.xml | 6 ++ .idea/modules.xml | 8 ++ ArcadeMachine.iml | 11 +++ src/client/games/Board.java | 148 ++++++++++++++++++++++++++++++ src/client/games/Executor.java | 28 ++++++ src/client/games/Game.java | 118 ++++++++++++++++++++++++ src/client/games/Painter.java | 75 +++++++++++++++ src/client/networking/Client.java | 72 +++++++++++++++ src/server/networking/Server.java | 103 +++++++++++++++++++++ 10 files changed, 572 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 ArcadeMachine.iml create mode 100644 src/client/games/Board.java create mode 100644 src/client/games/Executor.java create mode 100644 src/client/games/Game.java create mode 100644 src/client/games/Painter.java create mode 100644 src/client/networking/Client.java create mode 100644 src/server/networking/Server.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0548357 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d39f435 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ArcadeMachine.iml b/ArcadeMachine.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/ArcadeMachine.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/client/games/Board.java b/src/client/games/Board.java new file mode 100644 index 0000000..3d7de49 --- /dev/null +++ b/src/client/games/Board.java @@ -0,0 +1,148 @@ +package client.games; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Arrays; + +public class Board extends JPanel implements ActionListener { + + private final int B_WIDTH = 900; + private final int B_HEIGHT = 900; + private final int TILE_X = 300; + private final int TILE_Y = 300; + private final int DELAY = 50; + + private boolean ended = false; + private boolean gameWon = false; + + int[] oldPlayfield; + + private Timer timer; + private Game game; + private Painter painter; + + public Board(){ + initBoard(); + } + + private void initBoard(){ + painter = new Painter(B_WIDTH,B_HEIGHT); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + int column = e.getX()/TILE_X; + int row = e.getY()/TILE_Y; + game.place(column * 3 + row, 1); + } + }); + + setBackground(Color.BLACK); + setFocusable(true); + setPreferredSize(new Dimension(B_WIDTH,B_HEIGHT)); + + initGame(); + } + + private void initGame(){ + game = new Game(); + oldPlayfield = game.getPlayfield().clone(); + timer = new Timer(DELAY, this); + timer.start(); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + painter.paintGrid(g); + updateBoard(g); + } + + private void updateBoard(Graphics g){ + int actions = 0; + for (int column = 0; column < 3; column++) { + for (int row = 0; row < 3; row++) { + if (game.getPlayfield()[actions] == 1) { + painter.drawX(g, column, row); + } else if (game.getPlayfield()[actions] == -1) { + painter.drawO(g, column, row); + } + actions++; + } + } + if (gameWon) { + painter.paintWinnerLine(g); + } + } + + public void resetBoard(){ + for (int i = 0; i < game.getPlayfield().length; i++){ + game.setPlayfield(i, 0); + } + timer.start(); + oldPlayfield = game.getPlayfield().clone(); + game.setTurnTaken(false); + gameWon = false; + repaint(); + } + + public void setWinningLine(){ + painter.setWinningX1(game.getWinningX1()); + painter.setWinningY1(game.getWinningY1()); + painter.setWinningX2(game.getWinningX2()); + painter.setWinningY2(game.getWinningY2()); + } + + //game controlling method + @Override + public void actionPerformed(ActionEvent e) { + Thread actionThread = new Thread(){ + @Override + public void run() { + //check if game state evaluation needs to be done + if (isChanged(oldPlayfield)) { + gameWon = game.checkWin(); + //repaint board if not won + if (!gameWon) { + repaint(); + oldPlayfield = game.getPlayfield().clone(); + } + //stop timer if game won + if (gameWon || game.emptyTiles() == 0) { + if (gameWon) { + setWinningLine(); + } + repaint(); + timer.stop(); + try { + Thread.sleep(1000); + int n = JOptionPane.showConfirmDialog(null, "Do you want to play again?"); + if (n == 0){ + resetBoard(); + } else { + System.exit(0); + } + } catch (InterruptedException interruptedException) { + interruptedException.printStackTrace(); + } + } + } + //check if computer needs to take a turn + if (game.isTurnTaken()){ + game.setTurnTaken(false); + game.computersTurn(); + } + } + }; + actionThread.start(); + } + + private boolean isChanged(int[] playfield){ + return !Arrays.equals(game.getPlayfield(), playfield); + } +} diff --git a/src/client/games/Executor.java b/src/client/games/Executor.java new file mode 100644 index 0000000..0ae9b4c --- /dev/null +++ b/src/client/games/Executor.java @@ -0,0 +1,28 @@ +package client.games; + +import javax.swing.*; + +public class Executor extends JFrame { + public Executor(){ + initUI(); + } + + private void initUI(){ + Board board = new Board(); + setTitle("TicTacToe - MinMax"); + add(board); + pack(); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setLocationRelativeTo(null); + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Executor exc = new Executor(); + exc.setVisible(true); + } + }); + } +} diff --git a/src/client/games/Game.java b/src/client/games/Game.java new file mode 100644 index 0000000..bd6bc30 --- /dev/null +++ b/src/client/games/Game.java @@ -0,0 +1,118 @@ +package client.games; + +import javax.swing.*; + +public class Game { + + private int[] playfield; + private boolean turnTaken = false; + private int winningX1,winningY1,winningX2,winningY2; + + public Game(){ + playfield = new int[9]; + } + + public void place(int position, int player){ + if (playfield[position] == 0){ + playfield[position] = player; + if (player == 1) { + turnTaken = true; + } + } else { + JOptionPane.showInternalMessageDialog(null,"Tile is already taken"); + } + } + + public void computersTurn(){ + boolean isPlaced = false; + try { + Thread.sleep(750); + } catch (InterruptedException e) { + e.printStackTrace(); + } + while(!isPlaced){ + int random = (int) (Math.random() * 9); + // if field is free + if (playfield[random] == 0) { + place(random, -1); + isPlaced = true; + } + } + } + + + public boolean checkWin() { + //only check if winning is possible + if (emptyTiles() < 5) { + for (int i = 0; i < 3; i++) { + //horizontal + if ((playfield[i] == playfield[i + 3] && playfield[i] != 0) && (playfield[i] == playfield[i + 6])) { + winningX1 = 75; + winningX2 = 825; + winningY1 = winningY2 = i * 300 + 150; + return true; + } + //vertical + else if ((playfield[i * 3] == playfield[i * 3 + 1] && playfield[i * 3] != 0) && (playfield[i * 3] == playfield[i * 3 + 2])) { + winningY1 = 75; + winningY2 = 825; + winningX1 = winningX2 = i * 300 + 150; + return true; + } + } + //diagonal + if ((playfield[2] == playfield[4] && playfield[2] != 0) && (playfield[2] == playfield[6])){ + winningX2 = winningY1 = 75; + winningX1 = winningY2 = 825; + return true; + } else if ((playfield[0] == playfield[4] && playfield[0] != 0) && (playfield[0] == playfield[8])){ + winningX1 = winningY1 = 75; + winningX2 = winningY2 = 825; + return true; + } + } + return false; + } + + public int emptyTiles(){ + int n = 9; + for (int i = 0; i < playfield.length; i++){ + if (playfield[i] != 0){ + n -= 1; + } + } + return n; + } + + public boolean isTurnTaken() { + return turnTaken; + } + + public void setTurnTaken(boolean turnTaken) { + this.turnTaken = turnTaken; + } + + public void setPlayfield(int position, int value) { + playfield[position] = value; + } + + public int[] getPlayfield() { + return playfield; + } + + public int getWinningX1() { + return winningX1; + } + + public int getWinningX2() { + return winningX2; + } + + public int getWinningY1() { + return winningY1; + } + + public int getWinningY2() { + return winningY2; + } +} diff --git a/src/client/games/Painter.java b/src/client/games/Painter.java new file mode 100644 index 0000000..cb7b39f --- /dev/null +++ b/src/client/games/Painter.java @@ -0,0 +1,75 @@ +package client.games; + +import java.awt.*; + +public class Painter { + + private final int TILE_X; + private final int TILE_Y; + + private int winningX1, winningY1, winningX2, winningY2; + + public Painter(int boardWidth, int boardHeight){ + TILE_X = boardWidth/3; + TILE_Y = boardHeight/3; + } + + public void drawX(Graphics g, int column, int row) { + Graphics2D g2d = (Graphics2D) g; + + int nextColumn = column + 1; + int nextRow = row + 1; + int x1 = column * TILE_X + 25; + int x2 = nextColumn * TILE_Y - 25; + int y1 = row * TILE_X + 25; + int y2 = nextRow * TILE_Y - 25; + + g2d.setColor(Color.WHITE); + g2d.setStroke(new BasicStroke(5)); + g2d.drawLine(x1, y1, x2, y2); + g2d.drawLine(x1, y2, x2, y1); + } + + public void drawO(Graphics g, int column, int row){ + int x = column * TILE_X + 25; + int y = row * TILE_Y + 25; + g.drawOval(x,y,250,250); + } + + public void paintGrid(Graphics g){ + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.WHITE); + g2d.setStroke(new BasicStroke(10)); + //horizontal + for (int i = 1; i < 3; i++) { + g2d.drawLine(0, TILE_Y*i, TILE_X*3, TILE_Y*i); + } + //vertical + for (int i = 1; i < 3; i++){ + g2d.drawLine(TILE_X*i, 0, TILE_X*i, TILE_Y*3); + } + } + + public void paintWinnerLine(Graphics g){ + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(Color.RED); + g2d.setStroke(new BasicStroke(40)); + g2d.drawLine(winningX1, winningY1, winningX2, winningY2); + } + + public void setWinningX1(int winningX1) { + this.winningX1 = winningX1; + } + + public void setWinningX2(int winningX2) { + this.winningX2 = winningX2; + } + + public void setWinningY1(int winningY1) { + this.winningY1 = winningY1; + } + + public void setWinningY2(int winningY2) { + this.winningY2 = winningY2; + } +} diff --git a/src/client/networking/Client.java b/src/client/networking/Client.java new file mode 100644 index 0000000..a5e3b06 --- /dev/null +++ b/src/client/networking/Client.java @@ -0,0 +1,72 @@ +package client.networking; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; +import java.util.Scanner; + +public class Client { + private DataOutputStream out; + private DataInputStream in; + private static Scanner scanner; + private boolean success; + + public Client(String ip, int port) { + try { + scanner = new Scanner(System.in); + Socket serverSocket = new Socket(ip, port); + out = new DataOutputStream(serverSocket.getOutputStream()); + in = new DataInputStream(serverSocket.getInputStream()); + System.out.println(in.readUTF()); + success = true; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void handshake() { + try { + out.writeUTF("849465467842158"); + out.flush(); + success = in.readInt() == 200; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void oneSidedMessage() { + while (true) { + System.out.print("input> "); + String message = scanner.nextLine(); + try { + out.writeUTF(message); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + if(message.equalsIgnoreCase("exit()")) + break; + } + } + + public void sendToServer(String message) { + try { + out.writeUTF(message); + out.flush(); + success = in.readInt() == 200; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean hasSucceeded() { + return success; + } + + public static void main(String[] args) { + Client client = new Client("localhost", 2589); + client.handshake(); + client.oneSidedMessage(); + } +} \ No newline at end of file diff --git a/src/server/networking/Server.java b/src/server/networking/Server.java new file mode 100644 index 0000000..3a96dca --- /dev/null +++ b/src/server/networking/Server.java @@ -0,0 +1,103 @@ +package server.networking; + +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.HashMap; +import java.util.Scanner; + +public class Server { + private ServerSocket serverSocket; + private HashMap clients; + private HashMap outstreams; + private HashMap instreams; + private Scanner scanner; + private int requiredConnections; + + public Server(int port){ + try { + serverSocket = new ServerSocket(port); + clients = new HashMap<>(); + outstreams = new HashMap<>(); + instreams = new HashMap<>(); + scanner = new Scanner(System.in); + requiredConnections = 2; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void connectClients(){ + try { + int id = 0; + System.out.printf("Waiting for %d clients to connect%n", requiredConnections); + 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++; + System.out.printf("networking.Client %d got connected%n", id); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void handshake(){ + for (Socket client: clients.values()) { + try { + String handshakeValue = instreams.get(client).readUTF(); + if (handshakeValue.equals("849465467842158")) { + outstreams.get(client).writeInt(200); + } else { + outstreams.get(client).writeInt(403); + } + outstreams.get(client).flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + for (Socket client: clients.values()) { + try { + String response = instreams.get(client).readUTF(); + System.out.println(response); + if (response.equals("1")){ + outstreams.get(client).writeUTF("Connection confirmed :)"); + outstreams.get(client).writeUTF("Send me a message ..."); + System.out.println("Connection confirmed :)"); + } else { + outstreams.get(client).writeUTF("Connection failed"); + System.out.println("Connection failed"); + client.close(); + } + outstreams.get(client).flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void getMessage(){ + for (Socket client: clients.values()) { + try { + while (true) { + String message = instreams.get(client).readUTF(); + System.out.println(message); + if(message.equalsIgnoreCase("exit()")) + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + Server server = new Server(2589); + System.out.println("networking.Server got started"); + server.connectClients(); + server.handshake(); + server.getMessage(); + } +} \ No newline at end of file