I have been working on a two-player card game and have been stuck on updating the respective players' JPanels. Each player has their own panel and after each player makes a move, I want to allow the JPanel of both players to display the updated move. I can't get this to work! I have been able to allow each player to take turns (concurrency via locks). If there is a thread out there where I can find some help on this, please help me out. I can't find any documentation on how to get my code to work. Here is the main thread:
private static void openConnection() throws IOException{
int port = 2222;
try(ServerSocket serverSocket = new ServerSocket(port);){
setDeckAndPlayers();
//Two threads.
PlayerThreadGame game = new PlayerThreadGame();
PlayerThreadGame.PlayerThread p1 = game.new PlayerThread(serverSocket.accept(), panel1);
PlayerThreadGame.PlayerThread p2 = game.new PlayerThread(serverSocket.accept(), panel2);
PlayerThreadGame.PlayerThread activeThread;
p1.setOpponentThread(p2);
p2.setOpponentThread(p1);
if(p1.panel.active){
activeThread = p1;
}
else{
activeThread = p2;
}
game.setCurrentPlayerThread(activeThread);
p1.start();
p2.start();
} catch(IOException ie){
System.err.println("Could not listen on port " + port);
}
}
and here is the PlayerThreadGame:
public class PlayerThreadGame{
private volatile PlayerThread currentPlayer;
private volatile Table sharedTable;
private volatile Deck sharedDeck;
private volatile int[] score;
public PlayerThreadGame(){
score = new int[2];
score[0] = 0;
score[1] = 0;
}
public synchronized void setCurrentPlayerThread(PlayerThread curr){
currentPlayer = curr;
}
public PlayerThread getCurrentPlayerThread(){
return currentPlayer;
}
public synchronized void updateGameTable(Table t){
sharedTable = t;
}
public synchronized void updateGameDeck(Deck d){
sharedDeck = d;
}
public synchronized void updateGameScore(int s, int playerNum){
score[playerNum] = s;
}
public class PlayerThread extends Thread{
@SuppressWarnings("unused")
private Socket socket;
//private BufferedReader input;
private ObjectInputStream in;
//PrintWriter output;
private ObjectOutputStream out;
public volatile PlayerThread opponent;
public volatile GamePanel panel;
private int playerNumber;
//public volatile Player player;
//public volatile Player opp;
public PlayerThread(Socket socket, GamePanel panel){
super("PlayerThread");
this.socket = socket;
this.panel = panel;
System.out.println("Deck pos in thread server: " + sharedDeck.deck_position);
this.playerNumber = panel.P.ID;
try{
//Initialize the player.
//input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
out.writeInt(this.playerNumber);
out.flush();
out.writeObject(panel);
out.flush();
}
catch(IOException e){
System.out.println("Bad stream for player. " + e);
}
}
public void setOpponentThread(PlayerThread opp){
this.opponent = opp;
}
public PlayerThread getOpponentThread(){
return opponent;
}
public synchronized void updateTable(Table t){
panel.table = t;
}
public synchronized void updatePlayer(Player p){
panel.P = p;
}
public synchronized void updatePanel(GamePanel p){
panel.table.number_of_heads = p.table.number_of_heads;
panel.D = p.D;
System.out.println("Updating the thread panel:\n\tPanel ID: " + panel.panelID
+ "\n\tPlaying: " + panel.P.playing + "\n\tActive: " + panel.active);
opponent.panel.table.number_of_heads = panel.table.number_of_heads;
opponent.panel.D = panel.D;
}
public synchronized void updateDeck(Deck d){
panel.D = d;
}
public void run() {
try{
//Setup the initial play status.
if(panel.active){
out.writeObject("PLAY");
out.flush();
}
else{
out.writeObject("WAIT");
out.flush();
}
//The player must be updated here also.
out.writeObject(panel);
out.flush();
synchronized(this){
while(true){
String clientIn = (String) in.readObject();
GamePanel p = (GamePanel)in.readObject();
if(clientIn.equals("MOVED") && currentPlayer == this){
updatePanel(p);
//Update players' panels, and the game table and deck.
updateGameTable(panel.table);
updateGameDeck(panel.D);
panel.P.handSize--;
if(panel.P.handSize == 0 && opponent.panel.P.handSize == 0){
panel.P.hand.removeAllElements();
opponent.panel.P.hand.removeAllElements();
System.out.println("Both hands empty.");
sharedDeck.deal(panel.P, opponent.panel.P);
sharedTable.handSize = panel.P.handSize;
sharedTable.before_deal = 0;
}
System.out.println("Switch from " + currentPlayer + " to " + opponent);
opponent.panel.P.playing = true;
opponent.panel.P.dropped = false;
opponent.panel.active = true;
//Update opponents thread
setCurrentPlayerThread(opponent);
Thread.sleep(20); //let the JVM catch up in case the system resources are being drained.
out.writeObject("WAIT");
out.flush();
}
else if(clientIn.equals("WAITING") && currentPlayer == this){
//in.readObject();
out.writeObject("PLAY");
out.flush();
}
else{
out.writeObject("WAIT");
out.flush();
}
out.writeObject(panel);
out.flush();
}
}
} catch (IOException | ClassNotFoundException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Bad I/O in Thread.");
}
}
public String toString(){
return playerNumber+"";
}
}
}
and the client:
public class Player{
private static final String ip = "localhost";
private static final int PORT = 2222;
private JFrame frame = new JFrame("Game!");
private final static int WIDTH = 1020;
private final static int HEIGHT = 600;
private GamePanel panel;
private static int id;
private Socket socket;
private ObjectInputStream in;
private ObjectOutputStream out;
public Player() throws IOException, ClassNotFoundException {
try{
socket = new Socket(ip, PORT);
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
id = in.readInt();
panel = (GamePanel)in.readObject();
//currentThread = (PlayerThread) in.readObject();
} catch (UnknownHostException e){
System.err.println("Don't know about host " + ip);
System.exit(1);
} catch (IOException e){
System.err.println("Couldn't get I/O for the connection to " + ip);
System.exit(1);
}
}
public synchronized void updatePanel(GamePanel p){
panel = p;
panel.active = true;
panel.P.playing = true;
panel.P.dropped = false;
frame.add(panel);
frame.repaint();
}
public void play() throws Exception{
try{
synchronized(this){
while(true){
String status = (String) in.readObject();
GamePanel p = (GamePanel) in.readObject();
if(status.equals("PLAY")){
updatePanel(p);
System.out.println("Set panel " + id + " to active.");
while(!panel.message.equals("NEXT")){
//wait for the player to make their move
}
System.out.println("Player " + panel.P.ID + " moved.");
panel.active = false;
panel.message = "";
out.writeObject("MOVED"); //set the opponent panel to "active"
out.flush();
}
else if(status.equals("WAIT")){
//in.readObject();
//panel.active = false;
out.writeObject("WAITING");
out.flush();
}
out.writeObject(panel);
out.flush();
}
}
}
catch(Exception e){
System.out.println("Out of while loop scope.");
System.exit(1);
}
finally{
System.err.println("Closing the socket");
socket.close();
}
}
public static void main(String[] args) throws Exception{
System.out.println("in main.");
while(true){
Player client = new Player();
client.createBoard();
client.play();
if(!client.rematch())
break;
}
}
private boolean rematch() {
int response = JOptionPane.showConfirmDialog(frame, "Would you like a rematch?",
" Again?", JOptionPane.YES_NO_OPTION);
//this.dispose();
frame.dispose();
return response == JOptionPane.YES_OPTION;
}
private void createBoard(){
frame.setTitle("! Player " + id);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage imgUrl = null;
ImageIcon imgIcon = null;
try {
imgUrl = ImageIO.read(_Applet.class.getResource("cards/card.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
imgIcon = new ImageIcon(imgUrl);
Image img = imgIcon.getImage();
frame.setIconImage(img);
frame.setSize(WIDTH, HEIGHT);
frame.setVisible(true);
frame.setResizable(false);
System.out.println("Deck pos in client: " + panel.D.deck_position);
if(panel.active)
System.out.println("Player " + id + " is first!");
}
public String toString(){
return id+"";
}
You can see I'm writing the panel and then attempting to updated the other players' panel, but I am definitely not doing it right...