- changed the player approach a bit (using a listener now)
- implemented basic networking (caution, still buggy!)
This commit is contained in:
parent
d17ad194e1
commit
b36b0f549f
7 changed files with 408 additions and 50 deletions
|
@ -113,4 +113,13 @@ public class ButtonRow extends JPanel {
|
|||
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
|
||||
for (int i = 0; i < this.buttonCount; i++) {
|
||||
this.inputButtons[i].setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,15 @@
|
|||
package de.itsblue.ConnectFour;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import de.itsblue.ConnectFour.Plate.PlateType;
|
||||
import de.itsblue.ConnectFour.player.Player;
|
||||
import de.itsblue.ConnectFour.player.LocalPlayer;
|
||||
import de.itsblue.ConnectFour.player.*;
|
||||
|
||||
public class ConnectFour extends JFrame {
|
||||
public class ConnectFour extends JFrame implements PlayerMoveListener {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -39,6 +41,8 @@ public class ConnectFour extends JFrame {
|
|||
|
||||
private Player players[] = new Player[2];
|
||||
|
||||
private GameType gameType;
|
||||
|
||||
enum GameType {
|
||||
Local,
|
||||
RemoteServer,
|
||||
|
@ -75,50 +79,48 @@ public class ConnectFour extends JFrame {
|
|||
// finish up
|
||||
this.pack();
|
||||
this.setVisible(true);
|
||||
|
||||
this.startNewGame(GameType.Local);
|
||||
}
|
||||
|
||||
public void startNewGame(GameType type) {
|
||||
this.gameType = type;
|
||||
switch (type) {
|
||||
case Local: {
|
||||
this.players[0] = new LocalPlayer(this, this.buttonRow, PlateType.O);
|
||||
this.players[1] = new LocalPlayer(this, this.buttonRow, PlateType.X);
|
||||
this.players[0] = new LocalPlayer(this.buttonRow, PlateType.O);
|
||||
this.players[0].addMoveListener(this);
|
||||
this.players[1] = new LocalPlayer(this.buttonRow, PlateType.X);
|
||||
this.players[1].addMoveListener(this);
|
||||
|
||||
this.player = 0;
|
||||
this.players[player].setIsMyTurn(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case RemoteClient: {
|
||||
this.players[0] = new LocalPlayer(this.buttonRow, null);
|
||||
this.players[1] = new RemotePlayerClient(this.buttonRow, "localhost", this.players[0]);
|
||||
|
||||
this.players[0].addMoveListener(this);
|
||||
this.players[1].addMoveListener(this);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case RemoteServer: {
|
||||
this.players[0] = new LocalPlayer(this.buttonRow, PlateType.O);
|
||||
this.players[1] = new RemotePlayerServer(this.buttonRow, PlateType.X, this.players[0]);
|
||||
|
||||
this.players[0].addMoveListener(this);
|
||||
this.players[1].addMoveListener(this);
|
||||
|
||||
this.player = 0;
|
||||
this.players[player].setIsMyTurn(true);
|
||||
this.players[1].setIsMyTurn(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to handle the next plate insertion
|
||||
*
|
||||
* @param column The column to insert the plate into
|
||||
*/
|
||||
public void insertNextPlate(int column) {
|
||||
|
||||
String res;
|
||||
|
||||
res = this.gameBoard.insertPlate(new Plate(this.players[player].usingPlateType), column);
|
||||
|
||||
if (res == "err") {
|
||||
// beep in case of error
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
} else if (res != "ok" && res != "err") {
|
||||
PlateType winnerType = PlateType.valueOf(res);
|
||||
System.out.println("A player won: " + winnerType);
|
||||
}
|
||||
|
||||
switchPlayer();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to switch the player
|
||||
*/
|
||||
|
@ -145,6 +147,29 @@ public class ConnectFour extends JFrame {
|
|||
return this.getSize().height < this.getSize().width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch player moves
|
||||
*/
|
||||
@Override
|
||||
public void movePerformed(int column, Player src) {
|
||||
if(this.players[this.player].equals(src) || this.gameType == GameType.RemoteClient) {
|
||||
String res;
|
||||
|
||||
res = this.gameBoard.insertPlate(new Plate(src.usingPlateType), column);
|
||||
|
||||
if (res == "err") {
|
||||
// beep in case of error
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
} else if (res != "ok" && res != "err") {
|
||||
PlateType winnerType = PlateType.valueOf(res);
|
||||
System.out.println("A player won: " + winnerType);
|
||||
}
|
||||
|
||||
if(this.gameType != GameType.RemoteClient)
|
||||
switchPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override validate in order to resacle the components when the window is
|
||||
* rescaled
|
||||
|
@ -167,6 +192,19 @@ public class ConnectFour extends JFrame {
|
|||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
System.out.println(new ConnectFour());
|
||||
ConnectFour game;
|
||||
System.out.println(game = new ConnectFour());
|
||||
|
||||
System.out.println("argc: " + args.length);
|
||||
System.out.println("args[0]: " + args[0]);
|
||||
|
||||
if(args.length <= 0)
|
||||
game.startNewGame(GameType.Local);
|
||||
else if(args[0].equals("server"))
|
||||
game.startNewGame(GameType.RemoteServer);
|
||||
else if(args[0].equals("client"))
|
||||
game.startNewGame(GameType.RemoteClient);
|
||||
else
|
||||
System.out.println("Usage: java ConnectFour.java [server|client]");
|
||||
}
|
||||
}
|
|
@ -34,14 +34,11 @@ public class LocalPlayer extends Player implements ActionListener {
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param playingInGame The game the Player is plaing in The funtion
|
||||
* <code>insertNextPlate()</code> of the game will
|
||||
* be called when a move is done.
|
||||
* @param controlledByButtonRow The button row used to control the player.
|
||||
* @param usingPlateType The type of plate the player is using.
|
||||
*/
|
||||
public LocalPlayer(ConnectFour playingInGame, ButtonRow controlledByButtonRow, PlateType usingPlateType) {
|
||||
super(playingInGame, controlledByButtonRow, usingPlateType);
|
||||
public LocalPlayer(ButtonRow controlledByButtonRow, PlateType usingPlateType) {
|
||||
super(controlledByButtonRow, usingPlateType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
package de.itsblue.ConnectFour.player;
|
||||
|
||||
import de.itsblue.ConnectFour.Plate.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import de.itsblue.ConnectFour.*;
|
||||
|
||||
/**
|
||||
|
@ -29,12 +32,6 @@ import de.itsblue.ConnectFour.*;
|
|||
*/
|
||||
public abstract class Player {
|
||||
|
||||
/**
|
||||
* The game the player is playing in. The funtion <code>insertNextPlate()</code>
|
||||
* of the game will be called when a move is done.
|
||||
*/
|
||||
private ConnectFour playingInGame;
|
||||
|
||||
/**
|
||||
* The button row used to control the game.
|
||||
*/
|
||||
|
@ -45,6 +42,11 @@ public abstract class Player {
|
|||
*/
|
||||
public PlateType usingPlateType;
|
||||
|
||||
/**
|
||||
* An array containing all move listeners
|
||||
*/
|
||||
ArrayList<PlayerMoveListener> playerMoveListeners = new ArrayList<PlayerMoveListener>();
|
||||
|
||||
/**
|
||||
* Whether it is this player's turn
|
||||
*/
|
||||
|
@ -53,14 +55,10 @@ public abstract class Player {
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param playingInGame The game the Player is plaing in The funtion
|
||||
* <code>insertNextPlate()</code> of the game
|
||||
* will be called when a move is done.
|
||||
* @param gameControllingButtonRow The button row used to control the game.
|
||||
* @param usingPlateType The type of plate the player is using.
|
||||
*/
|
||||
public Player(ConnectFour playingInGame, ButtonRow gameControllingButtonRow, PlateType usingPlateType) {
|
||||
this.playingInGame = playingInGame;
|
||||
public Player(ButtonRow gameControllingButtonRow, PlateType usingPlateType) {
|
||||
this.gameControllingButtonRow = gameControllingButtonRow;
|
||||
this.usingPlateType = usingPlateType;
|
||||
}
|
||||
|
@ -82,7 +80,30 @@ public abstract class Player {
|
|||
* @param column the column to insert the plate into
|
||||
*/
|
||||
public void doMove(int column) {
|
||||
if (this.isMyTurn)
|
||||
this.playingInGame.insertNextPlate(column);
|
||||
if (this.isMyTurn){
|
||||
System.out.println("[LOG] " + Plate.getColor(this.usingPlateType) + " is doing a move in col: " + column);
|
||||
for (PlayerMoveListener playerMoveListener : playerMoveListeners) {
|
||||
playerMoveListener.movePerformed(column, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add a move listener
|
||||
*
|
||||
* @param listener the listener to add
|
||||
*/
|
||||
public void addMoveListener(PlayerMoveListener listener) {
|
||||
this.playerMoveListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to remove a move listener
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
*/
|
||||
public void removeMoveListener(PlayerMoveListener listener) {
|
||||
if(this.playerMoveListeners.contains(listener))
|
||||
this.playerMoveListeners.remove(listener);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package de.itsblue.ConnectFour.player;
|
||||
|
||||
public abstract interface PlayerMoveListener {
|
||||
public abstract void movePerformed(int column, Player src);
|
||||
}
|
148
src/de/itsblue/ConnectFour/player/RemotePlayerClient.java
Normal file
148
src/de/itsblue/ConnectFour/player/RemotePlayerClient.java
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
Connect four - written in java
|
||||
Copyright (C) 2020 Oliver Schappacher and Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.itsblue.ConnectFour.player;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.util.Scanner;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import de.itsblue.ConnectFour.Plate.*;
|
||||
import de.itsblue.ConnectFour.*;
|
||||
|
||||
/**
|
||||
* LocalPlayer is a class meant for usage with de.itsblue.ConnectFour. It is
|
||||
* used for a player controlled by the local buttons in the button row.
|
||||
*
|
||||
* @author Dorian Zedler
|
||||
*/
|
||||
public class RemotePlayerClient extends Player implements PlayerMoveListener {
|
||||
|
||||
private Socket socket;
|
||||
private Scanner in;
|
||||
private PrintWriter out;
|
||||
|
||||
private Player opponent;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param controlledByButtonRow The button row used to control the player.
|
||||
*/
|
||||
public RemotePlayerClient(ButtonRow gameControllingButtonRow, String serverAddress, Player opponent) {
|
||||
super(gameControllingButtonRow, null);
|
||||
|
||||
this.opponent = opponent;
|
||||
opponent.addMoveListener(this);
|
||||
|
||||
try {
|
||||
socket = new Socket(serverAddress, 4444);
|
||||
in = new Scanner(socket.getInputStream());
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
System.out.println("Connected to Connect4 server");
|
||||
|
||||
// get our plate type
|
||||
String response = in.nextLine();
|
||||
if (response.split(" ")[0].equals("setUsingPlateType")) {
|
||||
this.usingPlateType = PlateType.valueOf(response.split(" ")[1]);
|
||||
this.opponent.usingPlateType = this.usingPlateType.equals(PlateType.O) ? PlateType.X : PlateType.O;
|
||||
}
|
||||
|
||||
// check if it is out turn
|
||||
response = in.nextLine();
|
||||
if (response.split(" ")[0].equals("setIsMyTurn")) {
|
||||
this.setIsMyTurn(response.split(" ")[1].equals("true"));
|
||||
opponent.setIsMyTurn(response.split(" ")[1].equals("false"));
|
||||
}
|
||||
|
||||
// listen to the socket
|
||||
ExecutorService pool = Executors.newFixedThreadPool(200);
|
||||
pool.execute(this.new ClientListener(in, this));
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void handleResponse(String response) {
|
||||
System.out.println("[CLIENT]GOT: " + response);
|
||||
|
||||
if(response.startsWith("setIsMyTurn")) {
|
||||
this.setIsMyTurn(response.split(" ")[1].equals("true"));
|
||||
opponent.setIsMyTurn(response.split(" ")[1].equals("false"));
|
||||
} else if(response.startsWith("movePerformed")) {
|
||||
this.doMove(Integer.parseInt(response.split(" ")[1]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to set wether it is this player's turn
|
||||
*/
|
||||
@Override
|
||||
public void setIsMyTurn(boolean isMyTurn) {
|
||||
super.setIsMyTurn(isMyTurn);
|
||||
|
||||
if (isMyTurn)
|
||||
this.gameControllingButtonRow.setEnabled(false);
|
||||
else
|
||||
this.gameControllingButtonRow.setEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePerformed(int column, Player src) {
|
||||
try {
|
||||
this.out.println("movePerformed " + column);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
class ClientListener implements Runnable {
|
||||
|
||||
RemotePlayerClient parent;
|
||||
Scanner in;
|
||||
|
||||
public ClientListener(Scanner in, RemotePlayerClient parent) {
|
||||
this.parent = parent;
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// listen to the socket
|
||||
try {
|
||||
while (in.hasNextLine()) {
|
||||
String response = in.nextLine();
|
||||
|
||||
this.parent.handleResponse(response);
|
||||
|
||||
}
|
||||
out.println("QUIT");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
140
src/de/itsblue/ConnectFour/player/RemotePlayerServer.java
Normal file
140
src/de/itsblue/ConnectFour/player/RemotePlayerServer.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
Connect four - written in java
|
||||
Copyright (C) 2020 Oliver Schappacher and Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.itsblue.ConnectFour.player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import de.itsblue.ConnectFour.Plate.*;
|
||||
import de.itsblue.ConnectFour.*;
|
||||
|
||||
/**
|
||||
* LocalPlayer is a class meant for usage with de.itsblue.ConnectFour. It is
|
||||
* used for a player controlled by the local buttons in the button row.
|
||||
*
|
||||
* @author Dorian Zedler
|
||||
*/
|
||||
public class RemotePlayerServer extends Player implements PlayerMoveListener {
|
||||
|
||||
private ServerSocket listener;
|
||||
private Socket clientSocket;
|
||||
private Scanner in;
|
||||
private PrintWriter out;
|
||||
|
||||
private Player opponent;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param controlledByButtonRow The button row used to control the player.
|
||||
* @param usingPlateType The type of plate the player is using.
|
||||
*/
|
||||
public RemotePlayerServer(ButtonRow gameControllingButtonRow, PlateType usingPlateType, Player opponent) {
|
||||
super(gameControllingButtonRow, usingPlateType);
|
||||
|
||||
this.opponent = opponent;
|
||||
opponent.addMoveListener(this);
|
||||
|
||||
try {
|
||||
this.listener = new ServerSocket(4444);
|
||||
System.out.println("Connect4 Server is Running...");
|
||||
|
||||
this.clientSocket = listener.accept();
|
||||
this.in = new Scanner(this.clientSocket.getInputStream());
|
||||
this.out = new PrintWriter(this.clientSocket.getOutputStream(), true);
|
||||
|
||||
System.out.println("Client connected");
|
||||
|
||||
out.println("setUsingPlateType " + this.opponent.usingPlateType.name());
|
||||
out.println("setIsMyTurn " + (this.opponent.isMyTurn ? "true":"false"));
|
||||
|
||||
ExecutorService pool = Executors.newFixedThreadPool(200);
|
||||
pool.execute(this.new ServerListener(in, this));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResponse(String response) {
|
||||
System.out.println("GOT: " + response);
|
||||
if(response.startsWith("movePerformed")) {
|
||||
this.doMove(Integer.parseInt(response.split(" ")[1]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to set wether it is this player's turn
|
||||
*/
|
||||
@Override
|
||||
public void setIsMyTurn(boolean isMyTurn) {
|
||||
super.setIsMyTurn(isMyTurn);
|
||||
|
||||
if(isMyTurn)
|
||||
this.gameControllingButtonRow.setEnabled(false);
|
||||
else
|
||||
this.gameControllingButtonRow.setEnabled(true);
|
||||
|
||||
out.println("setIsMyTurn " + (this.isMyTurn ? "false":"true"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePerformed(int column, Player src) {
|
||||
System.out.println("movePerformed");
|
||||
try {
|
||||
this.out.println("movePerformed " + column);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
class ServerListener implements Runnable {
|
||||
|
||||
RemotePlayerServer parent;
|
||||
Scanner in;
|
||||
|
||||
public ServerListener(Scanner in, RemotePlayerServer parent) {
|
||||
this.parent = parent;
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// listen to the socket
|
||||
try {
|
||||
while (in.hasNextLine()) {
|
||||
String response = in.nextLine();
|
||||
|
||||
this.parent.handleResponse(response);
|
||||
|
||||
}
|
||||
out.println("QUIT");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in a new issue