📄 tictactoeclient.java
字号:
// Fig. 18.9: TicTacToeClient.java
// Client that let a user play Tic-Tac-Toe with another across a network.
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class TicTacToeClient extends JApplet implements Runnable {
private JTextField idField;
private JTextArea displayArea;
private JPanel boardPanel, panel2;
private Square board[][], currentSquare;
private Socket connection;
private DataInputStream input;
private DataOutputStream output;
private char myMark;
private boolean myTurn;
private final char X_MARK = 'X', O_MARK = 'O';
// Set up user-interface and board
public void init()
{
Container container = getContentPane();
// set up JTextArea to display messages to user
displayArea = new JTextArea( 4, 30 );
displayArea.setEditable( false );
container.add( new JScrollPane( displayArea ), BorderLayout.SOUTH );
// set up panel for squares in board
boardPanel = new JPanel();
boardPanel.setLayout( new GridLayout( 3, 3, 0, 0 ) );
// create board
board = new Square[ 3 ][ 3 ];
// When creating a Square, the location argument to the constructor
// is a value from 0 to 8 indicating the position of the Square on
// the board. Values 0, 1, and 2 are the first row, values 3, 4,
// and 5 are the second row. Values 6, 7, and 8 are the third row.
for ( int row = 0; row < board.length; row++ ) {
for ( int column = 0; column < board[ row ].length; column++ ) {
// create Square
board[ row ][ column ] = new Square( ' ', row * 3 + column );
boardPanel.add( board[ row ][ column ] );
}
}
// textfield to display player's mark
idField = new JTextField();
idField.setEditable( false );
container.add( idField, BorderLayout.NORTH );
// set up panel to contain boardPanel (for layout purposes)
panel2 = new JPanel();
panel2.add( boardPanel, BorderLayout.CENTER );
container.add( panel2, BorderLayout.CENTER );
} // end method init
// Make connection to server and get associated streams.
// Start separate thread to allow this applet to
// continually update its output in textarea display.
public void start()
{
// connect to server, get streams and start outputThread
try {
// make connection
connection = new Socket( getCodeBase().getHost(), 12345 );
// get streams
input = new DataInputStream( connection.getInputStream() );
output = new DataOutputStream( connection.getOutputStream() );
}
// catch problems setting up connection and streams
catch ( IOException ioException ) {
ioException.printStackTrace();
}
// create and start output thread
Thread outputThread = new Thread( this );
outputThread.start();
} // end method start
// control thread that allows continuous update of displayArea
public void run()
{
// get player's mark (X or O)
try {
myMark = input.readChar();
// display player ID in event-dispatch thread
SwingUtilities.invokeLater(
new Runnable() {
public void run()
{
idField.setText( "You are player \"" + myMark + "\"" );
}
}
);
myTurn = ( myMark == X_MARK ? true : false );
// receive messages sent to client and output them
while ( true ) {
processMessage( input.readUTF() );
}
} // end try
// process problems communicating with server
catch ( IOException ioException ) {
ioException.printStackTrace();
}
} // end method run
// process messages received by client
private void processMessage( String message )
{
// valid move occurred
if ( message.equals( "Valid move." ) ) {
displayMessage( "Valid move, please wait.\n" );
setMark( currentSquare, myMark );
}
// invalid move occurred
else if ( message.equals( "Invalid move, try again" ) ) {
displayMessage( message + "\n" );
myTurn = true;
}
// opponent moved
else if ( message.equals( "Opponent moved" ) ) {
// get move location and update board
try {
int location = input.readInt();
int row = location / 3;
int column = location % 3;
setMark( board[ row ][ column ],
( myMark == X_MARK ? O_MARK : X_MARK ) );
displayMessage( "Opponent moved. Your turn.\n" );
myTurn = true;
} // end try
// process problems communicating with server
catch ( IOException ioException ) {
ioException.printStackTrace();
}
} // end else if
// simply display message
else
displayMessage( message + "\n" );
} // end method processMessage
// 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 displayArea
{
displayArea.append( messageToDisplay );
displayArea.setCaretPosition(
displayArea.getText().length() );
}
} // end inner class
); // end call to SwingUtilities.invokeLater
}
// utility method to set mark on board in event-dispatch thread
private void setMark( final Square squareToMark, final char mark )
{
SwingUtilities.invokeLater(
new Runnable() {
public void run()
{
squareToMark.setMark( mark );
}
}
);
}
// send message to server indicating clicked square
public void sendClickedSquare( int location )
{
if ( myTurn ) {
// send location to server
try {
output.writeInt( location );
myTurn = false;
}
// process problems communicating with server
catch ( IOException ioException ) {
ioException.printStackTrace();
}
}
}
// set current Square
public void setCurrentSquare( Square square )
{
currentSquare = square;
}
// private inner class for the squares on the board
private class Square extends JPanel {
private char mark;
private int location;
public Square( char squareMark, int squareLocation )
{
mark = squareMark;
location = squareLocation;
addMouseListener(
new MouseAdapter() {
public void mouseReleased( MouseEvent e )
{
setCurrentSquare( Square.this );
sendClickedSquare( getSquareLocation() );
}
}
);
} // end Square constructor
// return preferred size of Square
public Dimension getPreferredSize()
{
return new Dimension( 30, 30 );
}
// return minimum size of Square
public Dimension getMinimumSize()
{
return getPreferredSize();
}
// set mark for Square
public void setMark( char newMark )
{
mark = newMark;
repaint();
}
// return Square location
public int getSquareLocation()
{
return location;
}
// draw Square
public void paintComponent( Graphics g )
{
super.paintComponent( g );
g.drawRect( 0, 0, 29, 29 );
g.drawString( String.valueOf( mark ), 11, 20 );
}
} // end inner-class Square
} // end class TicTacToeClient
/**************************************************************************
* (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 + -