SOURCE CODE for TicTacToe server which allows two applets to play
import java.net.*;
import java.io.*;
import java.awt.*;
// set up a TicTacToeServer for two client applets
public class TicTacToeServer extends Frame {
private byte board[];
private boolean xMove;
private TextArea output;
private Player players[];
private ServerSocket server;
private Socket connection;
private int numberOfPlayers;
private int currentPlayer;
public TicTacToeServer()
{
super( "Tic-Tac-Toe Server" );
board = new byte[9];
xMove = true;
players = new Player[2];
currentPlayer = 0;
// set up ServerSocket
try
{ server = new ServerSocket (5000, 2);
}
catch ( IOException e)
{ e.printStackTrace();
System.exit(1); }
output = new TextArea ();
add( "Center", output);
resize( 300, 300);
show();
}
public void execute()
// wait for two connections so game can be played
{
for ( int i = 0; i < players.length; i++ ) {
try
{
players[i] = new Player( server.accept(), this, i );
players[i].start();
++numberOfPlayers;
}
catch (IOException e)
{ e.printStackTrace(); System.exit(1); }
}
}
public int getNumberOfPlayers() { return numberOfPlayers; }
public void display (String str) { output.appendText (str + "\n"); }
public synchronized boolean validMove (int loc, int player)
// Determine if move is valid. This method is synchronized so that only
// one move can be made at a time
{
boolean moveDone = false;
while ( player != currentPlayer ) {
try
{ wait(); }
catch (InterruptedException e)
{ }
}
if ( !isOccupied (loc) )
{
board[loc] = (byte) (currentPlayer == 0 ? 'X' : 'O' );
currentPlayer = ++currentPlayer % 2;
players[currentPlayer].otherPlayerMoved(loc);
notify(); // tell waiting player to continue
return true;
}
else
return false;
}
public boolean isOccupied (int loc)
{
if ( board[loc] == 'X' || board[loc] == 'O' )
return true;
else
return false;
}
public boolean gameOver()
{
return false;
}
public boolean handleEvent (Event evt)
{
if (evt.id == Event.WINDOW_DESTROY)
{
hide();
dispose();
for ( int i = 0; i < players.length; i++ )
players[i].stop();
System.exit( 0 );
}
return super.handleEvent (evt);
}
public static void main( String args[] )
{
TicTacToeServer game = new TicTacToeServer();
game.execute();
}
}
class Player extends Thread {
// Player class to manage each Player as a thread
Socket connection;
DataInputStream input;
DataOutputStream output;
TicTacToeServer control;
int number;
char mark;
public Player (Socket sock, TicTacToeServer tttServer, int num )
{
mark = ( num == 0 ? 'X' : 'O' );
connection = sock;
try
{
input = new DataInputStream(connection.getInputStream() );
output = new DataOutputStream(connection.getOutputStream() );
}
catch (IOException e)
{ e.printStackTrace(); System.exit(1); }
control = tttServer;
number = num;
}
public void otherPlayerMoved (int loc )
{
try {
output.writeUTF( "Opponent moved" );
output.writeInt( loc );
}
catch (IOException e) {}
}
public void run()
{
boolean done = false;
try {
control.display( "Player " + ( number == 0 ? 'X' : 'O' ) + " connected" );
output.writeChar( mark );
output.writeUTF( "Player " + ( number == 0 ? "X connected\n" :
"O connected, please wait\n"));
// wait for another player to arrive
if ( control.getNumberOfPlayers() < 2 )
{
output.writeUTF( "Waiting for another player" );
while (control.getNumberOfPlayers() < 2) ;
output.writeUTF( "Other player connected. Your move.");
}
// play game
while ( !done )
{
int location = input.readInt();
if (control.validMove (location, number ) )
{
control.display ( "loc: " + location );
output.writeUTF ( "Valid move." );
}
else
output.writeUTF ( "Invalid move, try again!!!" );
if (control.gameOver() )
done = true;
}
connection.close();
}
catch (IOException e)
{ e.printStackTrace(); System.exit(1); }
}
}