📄 tictactoeserver.java
字号:
// Fig. 18.8: TicTacToeServer.java
// This class maintains a game of Tic-Tac-Toe for two client applets.
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class TicTacToeServer extends JFrame {
private char[] board;
private JTextArea outputArea;
private Player[] players;
private ServerSocket server;
private int currentPlayer;
private final int PLAYER_X = 0, PLAYER_O = 1;
private final char X_MARK = 'X', O_MARK = 'O';
// set up tic-tac-toe server and GUI that displays messages
public TicTacToeServer()
{
super( "Tic-Tac-Toe Server" );
board = new char[ 9 ];
players = new Player[ 2 ];
currentPlayer = PLAYER_X;
// set up ServerSocket
try {
server = new ServerSocket( 12345, 2 );
}
// process problems creating ServerSocket
catch( IOException ioException ) {
ioException.printStackTrace();
System.exit( 1 );
}
// set up JTextArea to display messages during execution
outputArea = new JTextArea();
outputArea.setFont(new Font(outputArea.getFont().getName(),Font.PLAIN,20));
getContentPane().add( new JScrollPane(outputArea), BorderLayout.CENTER );
outputArea.setText( "Server awaiting connections\n" );
setSize( 300, 300 );
setVisible( true );
} // end TicTacToeServer constructor
// wait for two connections so game can be played
public void execute()
{
// wait for each client to connect
for ( int i = 0; i < players.length; i++ ) {
// wait for connection, create Player, start thread
try {
players[ i ] = new Player( server.accept(), i );
players[ i ].start();
}
// process problems receiving connection from client
catch( IOException ioException ) {
ioException.printStackTrace();
System.exit( 1 );
}
}
// Player X is suspended until Player O connects.
// Resume player X now.
synchronized ( players[ PLAYER_X ] ) {
players[ PLAYER_X ].setSuspended( false );
players[ PLAYER_X ].notify();
}
} // end method execute
// utility method called from other threads to manipulate
// outputArea in the event-dispatch thread
private void displayMessage( final String messageToDisplay )
{
// display message from event-dispatch thread of execution
SwingUtilities.invokeLater(
new Runnable() { // inner class to ensure GUI updates properly
public void run() // updates outputArea
{
outputArea.append( messageToDisplay );
outputArea.setCaretPosition(
outputArea.getText().length() );
}
} // end inner class
); // end call to SwingUtilities.invokeLater
}
// Determine if a move is valid. This method is synchronized because
// only one move can be made at a time.
public synchronized boolean validateAndMove( int location, int player )
{
boolean moveDone = false;
// while not current player, must wait for turn
while ( player != currentPlayer ) {
// wait for turn
try {
wait();
}
// catch wait interruptions
catch( InterruptedException interruptedException ) {
interruptedException.printStackTrace();
}
}
// if location not occupied, make move
if ( !isOccupied( location ) ) {
// set move in board array
board[ location ] = currentPlayer == PLAYER_X ? X_MARK : O_MARK;
// change current player
currentPlayer = ( currentPlayer + 1 ) % 2;
// let new current player know that move occurred
players[ currentPlayer ].otherPlayerMoved( location );
notify(); // tell waiting player to continue
// tell player that made move that the move was valid
return true;
}
// tell player that made move that the move was not valid
else
return false;
} // end method validateAndMove
// determine whether location is occupied
public boolean isOccupied( int location )
{
if ( board[ location ] == X_MARK || board [ location ] == O_MARK )
return true;
else
return false;
}
// place code in this method to determine whether game over
public boolean isGameOver()
{
return false; // this is left as an exercise
}
public static void main( String args[] )
{
TicTacToeServer application = new TicTacToeServer();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
application.execute();
}
// private inner class Player manages each Player as a thread
private class Player extends Thread {
private Socket connection;
private DataInputStream input;
private DataOutputStream output;
private int playerNumber;
private char mark;
protected boolean suspended = true;
// set up Player thread
public Player( Socket socket, int number )
{
playerNumber = number;
// specify player's mark
mark = ( playerNumber == PLAYER_X ? X_MARK : O_MARK );
connection = socket;
// obtain streams from Socket
try {
input = new DataInputStream( connection.getInputStream() );
output = new DataOutputStream( connection.getOutputStream() );
}
// process problems getting streams
catch( IOException ioException ) {
ioException.printStackTrace();
System.exit( 1 );
}
} // end Player constructor
// send message that other player moved
public void otherPlayerMoved( int location )
{
// send message indicating move
try {
output.writeUTF( "Opponent moved" );
output.writeInt( location );
}
// process problems sending message
catch ( IOException ioException ) {
ioException.printStackTrace();
}
}
// control thread's execution
public void run()
{
// send client message indicating its mark (X or O),
// process messages from client
try {
displayMessage( "Player " + ( playerNumber ==
PLAYER_X ? X_MARK : O_MARK ) + " connected\n" );
output.writeChar( mark ); // send player's mark
// send message indicating connection
output.writeUTF( "Player " + ( playerNumber == PLAYER_X ?
"X connected\n" : "O connected, please wait\n" ) );
// if player X, wait for another player to arrive
if ( mark == X_MARK ) {
output.writeUTF( "Waiting for another player" );
// wait for player O
try {
synchronized( this ) {
while ( suspended )
wait();
}
}
// process interruptions while waiting
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
// send message that other player connected and
// player X can make a move
output.writeUTF( "Other player connected. Your move." );
}
// while game not over
while ( ! isGameOver() ) {
// get move location from client
int location = input.readInt();
System.out.println("user0:"+":"+players[0].getState());
System.out.println("user1:"+":"+players[1].getState());
// check for valid move
if ( validateAndMove( location, playerNumber ) ) {
displayMessage( "\nlocation: " + location );
output.writeUTF( "Valid move." );
}
else
output.writeUTF( "Invalid move, try again" );
}
connection.close(); // close connection to client
} // end try
// process problems communicating with client
catch( IOException ioException ) {
ioException.printStackTrace();
System.exit( 1 );
}
} // end method run
// set whether or not thread is suspended
public void setSuspended( boolean status )
{
suspended = status;
}
} // end class Player
} // end class TicTacToeServer
/**************************************************************************
* (C) Copyright 1992-2003 by Deitel & Associates, Inc. and *
* Prentice Hall. All Rights Reserved. *
* *
* DISCLAIMER: The authors and publisher of this book have used their *
* best efforts in preparing the book. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these books. The authors *
* and publisher shall not be liable in any event for incidental or *
* consequential damages in connection with, or arising out of, the *
* furnishing, performance, or use of these programs. *
*************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -