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