Applet Clients do not respond to click
I just created a project in eclipse, using the very good book 'Introduction to Java Programming'.
The problem is that the two applet clients do not respond to my clicks.
Any ideas?
Here is the code :
TicaTacToeConstants.java :
Code:
package mypackage;
public interface TicTacToeConstants {
public static int PLAYER1 = 1; //Indicate player 1
public static int PLAYER2 = 2; //Indicate player 2
public static int PLAYER1_WON = 1; //Indicate player 1 won
public static int PLAYER2_WON = 2; //Indicate player 2 won
public static int DRAW = 3; //Indicate a draw
public static int CONTINUE = 4; //Indicate to continue
}
TicTacToeServer.java :
Code:
package mypackage;
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.util.Date;
public class TicTacToeServer extends JFrame implements TicTacToeConstants{
//main method
public static void main(String[] args) {
// TODO Auto-generated method stub
TicTacToeServer frame = new TicTacToeServer();
}
//---default constructor
public TicTacToeServer()
{
JTextArea jtaLog = new JTextArea();
//Create a scroll pane to hold text area
JScrollPane scrollPane = new JScrollPane(jtaLog);
//Add the scroll pane to the frame
add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
setTitle("TicTacToeServer");
setVisible(true);
try
{
//Create a server socket
ServerSocket serverSocket = new ServerSocket(8000);
jtaLog.append(new Date() + ": Server started at socket 8000\n");
//Number a session
int sessionNo = 1;
//Ready to create a session for every two players
while(true)
{
jtaLog.append(new Date() + ": Wait for players to join session " + sessionNo + "\n");
//Connect to player 1
Socket player1 = serverSocket.accept();
jtaLog.append(new Date() + ": Player 1 joined session " + sessionNo + "\n");
jtaLog.append("Player 1's IP address" + player1.getInetAddress().getHostAddress() + "\n");
//Notify that the player is Player 1
new DataOutputStream(player1.getOutputStream()).writeInt(PLAYER1);
//Connect to player 2
Socket player2 = serverSocket.accept();
jtaLog.append(new Date() + ": Player 2 joined session " + sessionNo + "\n");
jtaLog.append("Player 2's IP address" + player2.getInetAddress().getHostAddress() + "\n");
//Notify that the player is Player 2
new DataOutputStream(player2.getOutputStream()).writeInt(PLAYER2);
//Display this session and increment session number
jtaLog.append(new Date() + ": Start a thread for session " + sessionNo++ + "\n");
//Create a new thread for this session of two players
HandleASession task = new HandleASession(player1, player2);
}//end while
}
catch(IOException ex)
{
System.err.println(ex);
}
}//end default constructor
}//end TicTacToeServer class
HandleASession.java :
Code:
package mypackage;
import java.io.*;
import java.net.*;
//Define the thread class for handling a new session for two players
class HandleASession implements Runnable, TicTacToeConstants{
private Socket player1;
private Socket player2;
//Create and initialize cells
private char[][] cell = new char[3][3];
private DataInputStream fromPlayer1;
private DataOutputStream toPlayer1;
private DataInputStream fromPlayer2;
private DataOutputStream toPlayer2;
//---default constructor
//Construct a thread
public HandleASession(Socket player1, Socket player2)
{
this.player1 = player1;
this.player2 = player2;
//Initialize cells
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
cell[i][j] = ' ';
}
//---Implement the run() method for the thread
public void run()
{
try
{
//Create data input and output streams
fromPlayer1 = new DataInputStream(player1.getInputStream());
toPlayer1 = new DataOutputStream(player1.getOutputStream());
fromPlayer2 = new DataInputStream(player2.getInputStream());
toPlayer2 = new DataOutputStream(player2.getOutputStream());
//Write anything to notify player1 to start
//This is just to let player 1 know to start
toPlayer1.writeInt(1);
//Continuously serve the players and determine and report the game status to the players
while(true)
{
//---Receive a move from player 1
int row = fromPlayer1.readInt();
int column = fromPlayer1.readInt();
cell[row][column] = 'X';
//Check if Player 1 wins
if (isWon('X'))
{
toPlayer1.writeInt(PLAYER1_WON);
toPlayer2.writeInt(PLAYER1_WON);
sendMove(toPlayer2, row, column);
break; //Break the loop
}
else if (isFull()) //Check if all cells are filled
{
toPlayer1.writeInt(DRAW);
toPlayer2.writeInt(DRAW);
sendMove(toPlayer2, row, column);
break;
}
else
{
//Notify player 2 to take the turn
toPlayer2.writeInt(CONTINUE);
//Send player 1's selected row and column to player 2
sendMove(toPlayer2, row, column);
}
//---Receive a move from Player 2
row = fromPlayer2.readInt();
column = fromPlayer2.readInt();
cell[row][column] = 'O';
//Check if Player 2 wins
if (isWon('O'))
{
toPlayer1.writeInt(PLAYER2_WON);
toPlayer2.writeInt(PLAYER2_WON);
sendMove(toPlayer1, row, column);
break;
}
else
{
//Notify player 1 to take the turn
toPlayer1.writeInt(CONTINUE);
//Send player 2's selected row and column to player 1
sendMove(toPlayer1, row, column);
}
}//end while
}
catch(IOException ex)
{
System.err.println(ex);
}
}//end run method
//---Helper methods
//Send the move to other player
private void sendMove(DataOutputStream out, int row, int column) throws IOException
{
out.writeInt(row); //Send row index
out.writeInt(column); //Send column index
}
//Determine if the cells are all occupied
private boolean isFull()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (cell[i][j] == ' ')
return false; //At least one cell is not filled
//All cells are filled
return true;
}
//Determine if the player with the specified token wins
private boolean isWon(char token)
{
//Check all rows
for (int i = 0; i < 3; i++)
if ( (cell[i][0] == token) && (cell[i][1] == token) && (cell[i][2] == token) )
{
return true;
}
//Check all columns
for (int j = 0; j < 3; j++)
if ( (cell[0][j] == token) && (cell[1][j] == token) && (cell[2][j] == token) )
{
return true;
}
//Check main diagonal
if ( (cell[0][0] == token) && (cell[1][1] == token) && (cell[2][2] == token) )
{
return true;
}
//Check subdiagonal
if ( (cell[0][2] == token) && (cell[1][1] == token) && (cell[2][0] == token) )
{
return true;
}
//All checked, but no winner
return false;
}
}
TicTacToeClient.java :
Code:
package mypackage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.io.*;
import java.net.*;
public class TicTacToeClient extends JApplet
implements Runnable, TicTacToeConstants
{
//Indicate whether the player has the turn
private boolean myTurn = false;
//Indicate the token for the player
private char myToken = ' ';
//Indicate the token for the other player
private char otherToken = ' ';
//Create and initialize cells
private Cell[][] cell = new Cell[3][3];
//Create and initialize a title label
private JLabel jlblTitle = new JLabel();
//Create and initialize a status label
private JLabel jlblStatus = new JLabel();
//Indicate selected row and column by the current move
private int rowSelected;
private int columnSelected;
//Input and output streams from/to server
private DataInputStream fromServer;
private DataOutputStream toServer;
//Continue to play?
private boolean continueToPlay = true;
//Wait for the player to mark a cell
private boolean waiting = true;
//**Indicate if it runs as application
private boolean isStandAlone = false;
//Host name or ip
private String host = "localhost";
//---Initialize UI
public void init()
{
//Panel p to hold cells
JPanel p = new JPanel();
p.setLayout(new GridLayout(3, 3, 0, 0));
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
p.add(cell[i][j] = new Cell(i, j));
//Set properties for labels , and borders for labels and panel
p.setBorder(new LineBorder(Color.black, 1));
jlblTitle.setHorizontalAlignment(JLabel.CENTER);
jlblTitle.setFont(new Font("SansSerif", Font.BOLD, 16));
jlblTitle.setBorder(new LineBorder(Color.black, 1));
jlblStatus.setBorder(new LineBorder(Color.black, 1));
//Place the panel and the labels to the applet
add(jlblTitle, BorderLayout.NORTH);
add(p, BorderLayout.CENTER);
add(jlblStatus, BorderLayout.SOUTH);
//Connect to the server
connectToServer();
}//end init method
//---methods
private void connectToServer()
{
try
{
//Create a socket to connect to the server
Socket socket;
if (isStandAlone)
socket = new Socket(host, 8000);
else
socket = new Socket(getCodeBase().getHost(), 8000);
//Create an input stream to receive data from the server
fromServer = new DataInputStream(socket.getInputStream());
//Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
}
catch(Exception ex)
{
System.err.println(ex);
}
//Control the game on a separate thread
Thread thread = new Thread(this);
thread.start();
}//end method connectToServer()
public void run()
{
try
{
//Get notification from the server
int player = fromServer.readInt();
//Am I player 1 or 2?
if (player == PLAYER1)
{
myToken = 'X';
otherToken = 'O';
jlblTitle.setText("Player 1 with token 'X'");
jlblStatus.setText("Waiting for player 2 to join");
//Receive startup notification from the server
fromServer.readInt(); //Whatever read is ignored
//The other player has joined
jlblStatus.setText("Player 2 has joined. I start first");
//It is my turn
myTurn = true;
}
else if (player == PLAYER2)
{
myToken = 'O';
otherToken = 'X';
jlblTitle.setText("Player 2 with token 'O'");
jlblStatus.setText("Waiting for player 1 to move");
}
//Continue to play
while(continueToPlay)
{
if (player == PLAYER1)
{
waitForPlayerAction(); //Wait for player 1 to move
sendMove(); //Send the move to the server
receiveInfoFromServer(); //Receive info from the server
}
else if (player == PLAYER2)
{
receiveInfoFromServer(); //Receive info from the server
waitForPlayerAction(); //Wait for player 2 to move
sendMove(); //Send player 2's move to the server
}
}//end while
}
catch (Exception ex)
{
}
}//end run method
//---helper methods
//Wait for the player to mark a cell
private void waitForPlayerAction() throws InterruptedException
{
while(waiting)
{
Thread.sleep(100);
}
waiting = true;
}
//Send this player's move to the server
private void sendMove() throws IOException
{
toServer.writeInt(rowSelected); //Send the selected row
toServer.writeInt(columnSelected); //Send the selected column
}
//Receive info from the server
private void receiveInfoFromServer() throws IOException
{
//Receive game status
int status = fromServer.readInt();
if (status == PLAYER1_WON)
{
//Player 1 won, stop playing
continueToPlay = false;
if (myToken == 'X')
{
jlblStatus.setText("I won! (X)");
}
else if (myToken == 'O')
{
jlblStatus.setText("Player 1 (X) has won!");
receiveMove();
}
}
else if (status == PLAYER2_WON)
{
//Player 2 won, stop playing
continueToPlay = false;
if (myToken == 'O')
{
jlblStatus.setText("I won! (O)");
}
else if (myToken == 'X')
{
jlblStatus.setText("Player 2 (O) has won!");
receiveMove();
}
}
else if (status == DRAW)
{
//No winner, game is over
continueToPlay = false;
jlblStatus.setText("Game is over, no winner!");
if (myToken == 'O')
{
receiveMove();
}
}
else
{
receiveMove();
jlblStatus.setText("My turn");
myTurn = true; //It is my turn
}
}//end ReceiveInfoFromServer method
private void receiveMove() throws IOException
{
//Get the other player's move
int row = fromServer.readInt();
int column = fromServer.readInt();
cell[row][column].setToken(otherToken);
}
//A class for a cell (inner class)
public class Cell extends JPanel{
//Indicate the row and column of this cell in the board
private int row;
private int column;
//Token used for this cell
private char token = ' ';
//---default constructor
public Cell(int row, int column)
{
this.row = row;
this.column = column;
setBorder(new LineBorder(Color.black, 1)); //Set cell's border
addMouseListener(new ClickListener()); //Register listener
}
//---methods
public char getToken()
{
return token;
}
public void setToken(char c)
{
token = c;
repaint();
}
//Paint the cell
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (token == 'X')
{
g.drawLine(10, 10, getWidth() - 10, getHeight() - 10); //draw X
g.drawLine(getWidth() - 10, 10, 10, getHeight() - 10);
}
else if (token == 'O')
{
g.drawOval(10, 10, getWidth() - 20, getHeight() - 20); //draw O
}
}
//Handle mouse click on a cell
private class ClickListener extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
//If cell is not occupied and the player has the turn
if ((token == ' ' && myTurn))
{
setToken(myToken); //Set the player's token in the cell
myTurn = false;
rowSelected = row;
columnSelected = column;
jlblStatus.setText("Waiting for the other player to move");
waiting = false; //Just completed a successful move
}
}
}//end listener class
}//end inner class Cell
}
Re: Applet Clients do not respond to click
Do the applets have the focus?
Are they able to get the focus? Not all components are able to get the focus. You may need to set the focusable property.
Re: Applet Clients do not respond to click
I think that they have the focus.
Re: Applet Clients do not respond to click
Are they capable of getting the focus?
Add a println to the listener to see if it is called.
Re: Applet Clients do not respond to click
I've added a println in the mouseClicked method and it is getting the clicks from both clients.
Re: Applet Clients do not respond to click
Quote:
problem is that the two applet clients do not respond to my clicks.
Quote:
it is getting the clicks from both clients.
Can you explain the problem then? If the code is getting the mouse clicks, then the logic must not be handling the clicks as you want them to.
Add some more prntlns to the code to see what it is doing.
Re: Applet Clients do not respond to click
It is supposed to draw an 'X' or a 'O' and play the game of tic-tac-toe.
It seems that it just freezes waiting for the clients to send something to the server.
Can somebody replicate the app on his own machine?
Re: Applet Clients do not respond to click
Have you tried debugging the code by adding printlns to see where the execution flow goes?
I've gotten the code to work by making some changes. I found the problem by adding printlns that showed me what the code was doing.
Re: Applet Clients do not respond to click
Re: Applet Clients do not respond to click
Add lots of printlns to show the execution flow and the values of variables. Look at the print out and see what and where.
Re: Applet Clients do not respond to click
In fact I am doing debugging using Eclipse.
Re: Applet Clients do not respond to click
Sorry, I do not have an IDE with debug features. I have to use printlns. In some cases printlns are faster because they can show the values from all over the program in a quick execution without having to step from break pt to break pt. Then the print out list can be studied to see what and where and how the code is executing.
Interactive is better in many cases, but print outs can be better in a few cases.