📄 tictactoeclient.java
字号:
// TicTacToeClient.java: Play the TicTacToe game
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 isFromServer;
private DataOutputStream osToServer;
// Continue to play?
private boolean continueToPlay = true;
// Wait for the player to mark a cell
private boolean waiting = true;
// 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
this.getContentPane().add(jlblTitle, BorderLayout.NORTH);
this.getContentPane().add(p, BorderLayout.CENTER);
this.getContentPane().add(jlblStatus, BorderLayout.SOUTH);
// Connect to the server
connectToServer();
}
private void connectToServer()
{
try
{
// Create a socket to connect to the server
Socket connectToServer = new Socket("localhost", 8000);
// Create an input stream to receive data from the server
isFromServer = new DataInputStream(
connectToServer.getInputStream());
// Create an output stream to send data to the server
osToServer =
new DataOutputStream(connectToServer.getOutputStream());
}
catch (Exception ex)
{
System.err.println(ex);
}
// Control the game on a separate thread
Thread thread = new Thread(this);
thread.start();
}
// This main method enables the applet to run as an application
public static void main(String[] args)
{
// Create a frame
JFrame frame = new JFrame("Tic Tac Toe Client");
// Create an instance of the applet
TicTacToeClient applet = new TicTacToeClient();
// Add the applet instance to the frame
frame.getContentPane().add(applet, BorderLayout.CENTER);
// Invoke init() and start()
applet.init();
applet.start();
// Display the frame
frame.setSize(320, 300);
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void run()
{
try
{
// Get notification from the server
int player = isFromServer.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
isFromServer.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
}
}
}
catch (Exception ex)
{ }
}
// 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
{
osToServer.writeInt(rowSelected); // Send the selected row
osToServer.writeInt(columnSelected); // Send the selected column
}
// Receive info from the server
private void receiveInfoFromServer() throws IOException
{
// Receive game status
int status = isFromServer.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
}
}
private void receiveMove() throws IOException
{
// Get the other player's move
int row = isFromServer.readInt();
int column = isFromServer.readInt();
cell[row][column].setToken(otherToken);
}
// An inner class for a cell
public class Cell extends JPanel implements MouseListener
{
// 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 = ' ';
public Cell(int row, int column)
{
this.row = row;
this.column = column;
setBorder(new LineBorder(Color.black, 1)); // Set cell's border
addMouseListener(this); // Register listener
}
// The getter method for token
public char getToken()
{
return token;
}
// The setter method for token
public void setToken(char c)
{
token = c;
repaint();
}
// Paint the cell
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (token == 'X')
{
g.drawLine(10, 10, getSize().width-10, getSize().height-10);
g.drawLine(getSize().width-10, 10, 10, getSize().height-10);
}
else if (token == 'O')
{
g.drawOval(10, 10, getSize().width-20, getSize().height-20);
}
}
// Handle mouse click on a cell
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 succeful move
}
}
public void mousePressed(MouseEvent e)
{
// TODO: implement this java.awt.event.MouseListener method;
}
public void mouseReleased(MouseEvent e)
{
// TODO: implement this java.awt.event.MouseListener method;
}
public void mouseEntered(MouseEvent e)
{
// TODO: implement this java.awt.event.MouseListener method;
}
public void mouseExited(MouseEvent e)
{
// TODO: implement this java.awt.event.MouseListener method;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -