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 int player = 0;
private JLabel statusLabel;
private int currentPlayer = -1;
@ -60,6 +59,10 @@ public class ConnectFour extends JFrame implements ActionListener {
Idle, Waiting, Running, Over
}
enum GameOverReason {
Winner, Draw, OpponentDisconnected, Error
}
/**
* Constructor
*/
@ -135,7 +138,8 @@ public class ConnectFour extends JFrame implements ActionListener {
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);
break;
@ -164,20 +168,33 @@ public class ConnectFour extends JFrame implements ActionListener {
this.setGameState(GameState.Running);
}
private void gameOver(String gameOverType) {
private void gameOver(GameOverReason reason, String attributes) {
if (!this.gameState.equals(GameState.Running))
return;
if (gameOverType.equals("draw")) {
this.winnerPlayer = -1;
this.statusLabel.setText("Game over. This was a draw!");
} else {
PlateType winnerPlateType = PlateType.valueOf(gameOverType);
this.winnerPlayer = this.players[0].getUsedPlateType().equals(winnerPlateType) ? 0 : 1;
if (!this.gameType.equals(GameType.Local) && this.players[this.winnerPlayer] instanceof LocalPlayer)
this.statusLabel.setText("Game over. You won the game!");
else
this.statusLabel.setText("Game over. " + this.players[this.winnerPlayer].getName() + " won the game!");
if (this.gameType.equals(GameType.RemoteServer))
((RemotePlayerServer) this.players[1]).notifyGameOver(reason.toString() + " " + attributes);
switch (reason) {
case Draw:
this.winnerPlayer = -1;
this.statusLabel.setText("Game over. This was a draw!");
break;
case Winner:
PlateType winnerPlateType = PlateType.valueOf(attributes);
this.winnerPlayer = this.players[0].getUsedPlateType().equals(winnerPlateType) ? 0 : 1;
if (!this.gameType.equals(GameType.Local) && this.players[this.winnerPlayer] instanceof LocalPlayer)
this.statusLabel.setText("Game over. You won the game!");
else
this.statusLabel
.setText("Game over. " + this.players[this.winnerPlayer].getName() + " won the game!");
case OpponentDisconnected:
break;
case Error:
break;
}
this.setGameState(GameState.Over);
@ -187,6 +204,9 @@ public class ConnectFour extends JFrame implements ActionListener {
if (!this.gameState.equals(GameState.Over))
return;
if(this.gameType.equals(GameType.RemoteServer))
((RemotePlayerServer) this.players[1]).notifyGameReset();
this.players[0] = null;
this.players[1] = null;
this.currentPlayer = -1;
@ -217,6 +237,7 @@ public class ConnectFour extends JFrame implements ActionListener {
if (e.getSource() instanceof Player) {
Player src = (Player) e.getSource();
if (e.getActionCommand().startsWith("doMove")
// handle moves
&& (this.gameType == GameType.RemoteClient || this.players[this.currentPlayer].equals(src))) {
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))
switchPlayer();
} else if (e.getActionCommand().startsWith("isMyTurnChanged")) {
// handle a turn change
if (e.getActionCommand().split(" ")[1].equals("true")) {
if (!this.gameType.equals(GameType.Local) && src instanceof LocalPlayer)
this.statusLabel.setText("Running, it's your turn!'");
else
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
if (e.getSource() instanceof GameBoard) {
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)
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) {
if (this.isMyTurn) {
this.fireActionListeners("doMove " + column);
this.fireActionListeners(this, "doMove " + column);
}
}
@ -108,8 +108,8 @@ public abstract class Player {
* @return player name
*/
public String getName() {
Color winnerColor = Plate.getColor(this.usingPlateType);
return winnerColor.equals(Color.BLACK) ? "Black":"Red";
Color thisColor = Plate.getColor(this.usingPlateType);
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
*/
protected void fireActionListeners(String actionCommand) {
protected void fireActionListeners(Object source, String command) {
for (ActionListener playerActionListener : playerActionListeners) {
ActionEvent e = new ActionEvent(this, this.currentActionId, actionCommand);
playerActionListener.actionPerformed(e);
playerActionListener.actionPerformed(new ActionEvent(source, this.currentActionId, command));
this.currentActionId++;
}
}

View file

@ -22,7 +22,6 @@ import de.itsblue.ConnectFour.Plate.*;
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;
@ -73,20 +72,7 @@ public abstract class RemotePlayer extends Player implements ActionListener {
}
@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("movePerformed " + column);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public abstract void actionPerformed(ActionEvent e);
private class SocketListener implements Runnable {
RemotePlayer parent;

View file

@ -22,8 +22,7 @@ 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 java.awt.event.*;
import de.itsblue.ConnectFour.Plate.*;
import de.itsblue.ConnectFour.*;
@ -52,21 +51,47 @@ public class RemotePlayerClient extends RemotePlayer {
System.out.println("Connected to Connect4 server");
this.startListening();
}
public void handleResponse(String response) {
System.out.println("[SOCKET] Got: " + response);
if (response.startsWith("setUsingPlateType")) {
// handle PlateType change
this.usingPlateType = PlateType.valueOf(response.split(" ")[1]);
this.opponent.usingPlateType = this.usingPlateType == PlateType.O ? PlateType.X : PlateType.O;
this.opponent.usingPlateType = PlateType.valueOf(response.split(" ")[1]);
this.usingPlateType = this.usingPlateType == PlateType.O ? PlateType.X : PlateType.O;
} else if (response.startsWith("setIsMyTurn")) {
// handle turn change
this.setIsMyTurn(response.split(" ")[1].equals("true"));
opponent.setIsMyTurn(response.split(" ")[1].equals("false"));
PlateType targetPlateType = PlateType.valueOf(response.split(" ")[1]);
Player target = this.getUsedPlateType().equals(targetPlateType) ? this:this.opponent;
target.setIsMyTurn(response.split(" ")[2].equals("true"));
} else if (response.startsWith("movePerformed")) {
// 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;
import java.awt.event.*;
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.*;
@ -52,6 +47,9 @@ public class RemotePlayerServer extends RemotePlayer {
throws Exception {
super(gameControllingButtonRow, usingPlateType, opponent);
// also catch own actions
this.addActionListener(this);
this.serverSocket = new ServerSocket(4444);
System.out.println("Connect4 Server is Running...");
@ -61,15 +59,31 @@ public class RemotePlayerServer extends RemotePlayer {
System.out.println("Client connected");
out.println("setUsingPlateType " + this.opponent.usingPlateType.name());
out.println("setIsMyTurn " + (this.opponent.isMyTurn ? "true" : "false"));
out.println("setUsingPlateType " + this.usingPlateType.name());
this.startListening();
}
public void handleResponse(String response) {
if (response.startsWith("movePerformed")) {
this.doMove(Integer.parseInt(response.split(" ")[1]));
if (response.startsWith("doMove")) {
if (this.isMyTurn)
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
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")) {
out.println("setIsMyTurn " + (e.getActionCommand().split(" ")[1]));
out.println("setIsMyTurn " + src.getUsedPlateType().toString() + " " + (e.getActionCommand().split(" ")[1]));
}
}
}