Added some checks to the server to enshure that moves of the client are legal

This commit is contained in:
Dorian Zedler 2020-02-25 15:34:07 +01:00
parent cc65762f95
commit 0c972d335c
5 changed files with 124 additions and 55 deletions

View file

@ -40,7 +40,6 @@ public class ConnectFour extends JFrame implements ActionListener {
private ControllRow controllRow; private ControllRow controllRow;
private int player = 0;
private JLabel statusLabel; private JLabel statusLabel;
private int currentPlayer = -1; private int currentPlayer = -1;
@ -60,6 +59,10 @@ public class ConnectFour extends JFrame implements ActionListener {
Idle, Waiting, Running, Over Idle, Waiting, Running, Over
} }
enum GameOverReason {
Winner, Draw, OpponentDisconnected, Error
}
/** /**
* Constructor * Constructor
*/ */
@ -135,7 +138,8 @@ public class ConnectFour extends JFrame implements ActionListener {
e.printStackTrace(); e.printStackTrace();
} }
this.players[0].addActionListener(this); // do not add the listener of the local player here, as the client player will
// handle its moves in order to make shure they are legal
this.players[1].addActionListener(this); this.players[1].addActionListener(this);
break; break;
@ -164,20 +168,33 @@ public class ConnectFour extends JFrame implements ActionListener {
this.setGameState(GameState.Running); this.setGameState(GameState.Running);
} }
private void gameOver(String gameOverType) { private void gameOver(GameOverReason reason, String attributes) {
if (!this.gameState.equals(GameState.Running)) if (!this.gameState.equals(GameState.Running))
return; return;
if (gameOverType.equals("draw")) { if (this.gameType.equals(GameType.RemoteServer))
((RemotePlayerServer) this.players[1]).notifyGameOver(reason.toString() + " " + attributes);
switch (reason) {
case Draw:
this.winnerPlayer = -1; this.winnerPlayer = -1;
this.statusLabel.setText("Game over. This was a draw!"); this.statusLabel.setText("Game over. This was a draw!");
} else { break;
PlateType winnerPlateType = PlateType.valueOf(gameOverType);
case Winner:
PlateType winnerPlateType = PlateType.valueOf(attributes);
this.winnerPlayer = this.players[0].getUsedPlateType().equals(winnerPlateType) ? 0 : 1; this.winnerPlayer = this.players[0].getUsedPlateType().equals(winnerPlateType) ? 0 : 1;
if (!this.gameType.equals(GameType.Local) && this.players[this.winnerPlayer] instanceof LocalPlayer) if (!this.gameType.equals(GameType.Local) && this.players[this.winnerPlayer] instanceof LocalPlayer)
this.statusLabel.setText("Game over. You won the game!"); this.statusLabel.setText("Game over. You won the game!");
else else
this.statusLabel.setText("Game over. " + this.players[this.winnerPlayer].getName() + " won the game!"); this.statusLabel
.setText("Game over. " + this.players[this.winnerPlayer].getName() + " won the game!");
case OpponentDisconnected:
break;
case Error:
break;
} }
this.setGameState(GameState.Over); this.setGameState(GameState.Over);
@ -187,6 +204,9 @@ public class ConnectFour extends JFrame implements ActionListener {
if (!this.gameState.equals(GameState.Over)) if (!this.gameState.equals(GameState.Over))
return; return;
if(this.gameType.equals(GameType.RemoteServer))
((RemotePlayerServer) this.players[1]).notifyGameReset();
this.players[0] = null; this.players[0] = null;
this.players[1] = null; this.players[1] = null;
this.currentPlayer = -1; this.currentPlayer = -1;
@ -217,6 +237,7 @@ public class ConnectFour extends JFrame implements ActionListener {
if (e.getSource() instanceof Player) { if (e.getSource() instanceof Player) {
Player src = (Player) e.getSource(); Player src = (Player) e.getSource();
if (e.getActionCommand().startsWith("doMove") if (e.getActionCommand().startsWith("doMove")
// handle moves
&& (this.gameType == GameType.RemoteClient || this.players[this.currentPlayer].equals(src))) { && (this.gameType == GameType.RemoteClient || this.players[this.currentPlayer].equals(src))) {
boolean res = this.gameBoard.insertPlate(new Plate(src.getUsedPlateType()), boolean res = this.gameBoard.insertPlate(new Plate(src.getUsedPlateType()),
@ -229,20 +250,32 @@ public class ConnectFour extends JFrame implements ActionListener {
if (this.gameType != GameType.RemoteClient && this.gameState.equals(GameState.Running)) if (this.gameType != GameType.RemoteClient && this.gameState.equals(GameState.Running))
switchPlayer(); switchPlayer();
} else if (e.getActionCommand().startsWith("isMyTurnChanged")) { } else if (e.getActionCommand().startsWith("isMyTurnChanged")) {
// handle a turn change
if (e.getActionCommand().split(" ")[1].equals("true")) { if (e.getActionCommand().split(" ")[1].equals("true")) {
if (!this.gameType.equals(GameType.Local) && src instanceof LocalPlayer) if (!this.gameType.equals(GameType.Local) && src instanceof LocalPlayer)
this.statusLabel.setText("Running, it's your turn!'"); this.statusLabel.setText("Running, it's your turn!'");
else else
this.statusLabel.setText("Running, it's " + src.getName() + "'s turn!'"); this.statusLabel.setText("Running, it's " + src.getName() + "'s turn!'");
} }
} else if (e.getActionCommand().startsWith("gameReset")) {
if(!this.gameState.equals(GameState.Over))
this.gameOver(GameOverReason.OpponentDisconnected, "");
else
this.resetGame();
} }
} }
// catch board events // catch board events
if (e.getSource() instanceof GameBoard) { if (e.getSource() instanceof GameBoard) {
if (e.getActionCommand().startsWith("gameOver")) { if (e.getActionCommand().startsWith("gameOver")) {
this.gameOver(e.getActionCommand().split(" ")[1]); if(e.getActionCommand().split(" ")[1].equals("draw"))
this.gameOver(GameOverReason.Draw, "");
else
this.gameOver(GameOverReason.Winner, e.getActionCommand().split(" ")[1]);
} }
} }
} }

View file

@ -79,7 +79,7 @@ public abstract class Player {
if (isMyTurn) if (isMyTurn)
this.gameControllingButtonRow.setColor(Plate.getColor(this.usingPlateType)); this.gameControllingButtonRow.setColor(Plate.getColor(this.usingPlateType));
this.fireActionListeners("isMyTurnChanged " + (isMyTurn ? "true" : "false")); this.fireActionListeners(this,"isMyTurnChanged " + (isMyTurn ? "true" : "false"));
} }
/** /**
@ -89,7 +89,7 @@ public abstract class Player {
*/ */
protected void doMove(int column) { protected void doMove(int column) {
if (this.isMyTurn) { if (this.isMyTurn) {
this.fireActionListeners("doMove " + column); this.fireActionListeners(this, "doMove " + column);
} }
} }
@ -108,8 +108,8 @@ public abstract class Player {
* @return player name * @return player name
*/ */
public String getName() { public String getName() {
Color winnerColor = Plate.getColor(this.usingPlateType); Color thisColor = Plate.getColor(this.usingPlateType);
return winnerColor.equals(Color.BLACK) ? "Black":"Red"; return thisColor.equals(Color.BLACK) ? "Black":"Red";
} }
/** /**
@ -117,10 +117,9 @@ public abstract class Player {
* *
* @param actionCommand The action command to fire the listeners with * @param actionCommand The action command to fire the listeners with
*/ */
protected void fireActionListeners(String actionCommand) { protected void fireActionListeners(Object source, String command) {
for (ActionListener playerActionListener : playerActionListeners) { for (ActionListener playerActionListener : playerActionListeners) {
ActionEvent e = new ActionEvent(this, this.currentActionId, actionCommand); playerActionListener.actionPerformed(new ActionEvent(source, this.currentActionId, command));
playerActionListener.actionPerformed(e);
this.currentActionId++; this.currentActionId++;
} }
} }

View file

@ -22,7 +22,6 @@ import de.itsblue.ConnectFour.Plate.*;
import java.awt.event.*; import java.awt.event.*;
import java.util.Scanner; import java.util.Scanner;
import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.Socket; import java.net.Socket;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -73,20 +72,7 @@ public abstract class RemotePlayer extends Player implements ActionListener {
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public abstract void actionPerformed(ActionEvent e);
if(!(e.getSource() instanceof Player))
return;
if (e.getActionCommand().startsWith("doMove")) {
int column = Integer.parseInt(e.getActionCommand().split(" ")[1]);
try {
this.out.println("movePerformed " + column);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private class SocketListener implements Runnable { private class SocketListener implements Runnable {
RemotePlayer parent; RemotePlayer parent;

View file

@ -22,8 +22,7 @@ import java.util.Scanner;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.Socket; import java.net.Socket;
import java.util.concurrent.ExecutorService; import java.awt.event.*;
import java.util.concurrent.Executors;
import de.itsblue.ConnectFour.Plate.*; import de.itsblue.ConnectFour.Plate.*;
import de.itsblue.ConnectFour.*; import de.itsblue.ConnectFour.*;
@ -52,21 +51,47 @@ public class RemotePlayerClient extends RemotePlayer {
System.out.println("Connected to Connect4 server"); System.out.println("Connected to Connect4 server");
this.startListening(); this.startListening();
} }
public void handleResponse(String response) { public void handleResponse(String response) {
System.out.println("[SOCKET] Got: " + response);
if (response.startsWith("setUsingPlateType")) { if (response.startsWith("setUsingPlateType")) {
// handle PlateType change // handle PlateType change
this.usingPlateType = PlateType.valueOf(response.split(" ")[1]); this.opponent.usingPlateType = PlateType.valueOf(response.split(" ")[1]);
this.opponent.usingPlateType = this.usingPlateType == PlateType.O ? PlateType.X : PlateType.O; this.usingPlateType = this.usingPlateType == PlateType.O ? PlateType.X : PlateType.O;
} else if (response.startsWith("setIsMyTurn")) { } else if (response.startsWith("setIsMyTurn")) {
// handle turn change // handle turn change
this.setIsMyTurn(response.split(" ")[1].equals("true")); PlateType targetPlateType = PlateType.valueOf(response.split(" ")[1]);
opponent.setIsMyTurn(response.split(" ")[1].equals("false")); Player target = this.getUsedPlateType().equals(targetPlateType) ? this:this.opponent;
target.setIsMyTurn(response.split(" ")[2].equals("true"));
} else if (response.startsWith("movePerformed")) { } else if (response.startsWith("movePerformed")) {
// handle move performed // handle move performed
this.doMove(Integer.parseInt(response.split(" ")[1])); PlateType targetPlateType = PlateType.valueOf(response.split(" ")[1]);
Player target = this.getUsedPlateType().equals(targetPlateType) ? this:this.opponent;
this.fireActionListeners(target, "doMove " + Integer.parseInt(response.split(" ")[2]));
} else if(response.startsWith("gameOver") || response.startsWith("gameReset")) {
// handle game over
this.fireActionListeners(this, response);
}
}
@Override
public void actionPerformed(ActionEvent e) {
if(!(e.getSource() instanceof Player))
return;
if (e.getActionCommand().startsWith("doMove")) {
int column = Integer.parseInt(e.getActionCommand().split(" ")[1]);
try {
this.out.println("doMove " + column);
System.out.println("[SOCKET] SENT: " + "doMove " + column);
} catch (Exception ex) {
ex.printStackTrace();
}
} }
} }
} }

View file

@ -19,15 +19,10 @@
package de.itsblue.ConnectFour.player; package de.itsblue.ConnectFour.player;
import java.awt.event.*; import java.awt.event.*;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import de.itsblue.ConnectFour.Plate.*; import de.itsblue.ConnectFour.Plate.*;
import de.itsblue.ConnectFour.*; import de.itsblue.ConnectFour.*;
@ -52,6 +47,9 @@ public class RemotePlayerServer extends RemotePlayer {
throws Exception { throws Exception {
super(gameControllingButtonRow, usingPlateType, opponent); super(gameControllingButtonRow, usingPlateType, opponent);
// also catch own actions
this.addActionListener(this);
this.serverSocket = new ServerSocket(4444); this.serverSocket = new ServerSocket(4444);
System.out.println("Connect4 Server is Running..."); System.out.println("Connect4 Server is Running...");
@ -61,15 +59,31 @@ public class RemotePlayerServer extends RemotePlayer {
System.out.println("Client connected"); System.out.println("Client connected");
out.println("setUsingPlateType " + this.opponent.usingPlateType.name()); out.println("setUsingPlateType " + this.usingPlateType.name());
out.println("setIsMyTurn " + (this.opponent.isMyTurn ? "true" : "false"));
this.startListening(); this.startListening();
} }
public void handleResponse(String response) { public void handleResponse(String response) {
if (response.startsWith("movePerformed")) { if (response.startsWith("doMove")) {
if (this.isMyTurn)
this.doMove(Integer.parseInt(response.split(" ")[1])); this.doMove(Integer.parseInt(response.split(" ")[1]));
else
this.out.println("invalidMove " + response.split(" ")[1]);
}
}
public void notifyGameOver(String reason) {
this.out.println("gameOver " + reason);
}
public void notifyGameReset() {
this.out.println("gameReset");
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
} }
} }
@ -79,10 +93,22 @@ public class RemotePlayerServer extends RemotePlayer {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
super.actionPerformed(e); if(!(e.getSource() instanceof Player))
return;
Player src = (Player)e.getSource();
if (e.getActionCommand().startsWith("doMove")) {
int column = Integer.parseInt(e.getActionCommand().split(" ")[1]);
try {
this.out.println("movePerformed " + src.getUsedPlateType().toString() + " " + column);
} catch (Exception ex) {
ex.printStackTrace();
}
}
if (e.getActionCommand().startsWith("isMyTurnChanged")) { if (e.getActionCommand().startsWith("isMyTurnChanged")) {
out.println("setIsMyTurn " + (e.getActionCommand().split(" ")[1])); out.println("setIsMyTurn " + src.getUsedPlateType().toString() + " " + (e.getActionCommand().split(" ")[1]));
} }
} }
} }