遗憾的是,我对线程没有经验。我一直在做一些“Hello World”线程示例,这看起来很简单。但是,我需要将线程合并到我拥有的Java Tic Tac Toe服务器中(使用套接字)。我的Tic Tac Toe游戏的设计就是:
Provider.java
(服务器):确定当前播放器,向当前播放器发送文本显示/游戏板,确定游戏是否结束
Requester.java
(客户端):为每个客户端启动游戏板对象,使客户端游戏板与服务器游戏板保持同步,检查有效移动
TBoard.java
:客户端和服务器使用的方法(make_move(),is_winner(),current_player()等)
我想知道你们是否可以看看我的Provider.java
(服务器),并给我一些关于如何合并线程以允许同时播放多个tic tac toe游戏的建议......
/**
* Provider.java
*
* @version 2.0
*/
import java.io.*;
import java.net.*;
/**
* The Provider class is responsible for any server-side activities with the
* Tic-Tac-Toe game. This includes:
*
* 1. Determining the current player 2. Managing the textual display for the two
* individual players 3. Updating the game board with the each player's moves 4.
* Determine what player wins, if any
*/
public class Provider {
TBoard board = new TBoard(); // Instantiate the game board object
ServerSocket providerSocket;
Socket connection1 = null, connection2 = null;
ObjectOutputStream out, out2; // Client 1, Client 2
ObjectInputStream in, in2; // Client 1, Client 2
String message;
Boolean done = false;
String end = "";
int row, col, game_state = 3;
/**
* Class constructor.
*/
Provider() {
}
void run() {
try {
// Open a socket and wait for connections
providerSocket = new ServerSocket(20092);
System.out.println("Waiting for connection...");
connection1 = providerSocket.accept();
System.out.println("Connection received from Player 1 "
+ connection1.getInetAddress().getHostName());
connection2 = providerSocket.accept();
System.out.println("Connection received from Player 2 "
+ connection2.getInetAddress().getHostName());
out = new ObjectOutputStream(connection1.getOutputStream());
out2 = new ObjectOutputStream(connection2.getOutputStream());
in = new ObjectInputStream(connection1.getInputStream());
in2 = new ObjectInputStream(connection2.getInputStream());
do {
// Send the game game_state to the current player
sendInt(board.get_player(), game_state);
// If the game state != 3 (There is a winner or board is full)
if (game_state != 3) {
// Send game state to the other player
sendInt(board.get_opposite_player(), game_state);
done = true; // Condition to terminate the server
// If game is in "play" state
} else {
// Send both the current player and the Tic Tac Toe board
// (2D array) to current player
sendInt(board.get_player(), board.get_player());
send2D(board.get_player(), board.print_board());
sendString(board.get_player(),
"Please enter a row, press Enter, then enter a column: ");
// Receive the tic tac toe board from current player
// (after a move has been made)
if (board.get_player() == 1) {
int[][] c_array = (int[][]) in.readObject();
board.set_array(c_array);
} else {
int[][] c_array = (int[][]) in2.readObject();
board.set_array(c_array);
}
// Switch the current player
if (board.get_player() == 1) {
board.set_player(2);
} else {
board.set_player(1);
}
// If there is a winner, set the game state accordingly
if (board.winner() != 0) {
if (board.get_player() == 1) {
game_state = 2;
} else {
game_state = 1;
}
// If there is no winner and the board is full, set the
// game state accordingly
} else if (board.board_full() && board.winner() == 0) {
game_state = 0;
// Otherwise, stay in the "play" state
} else {
game_state = 3;
}
}
} while (done != true);
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// Close the input/output streams, and the socket connections
try {
in.close();
out.close();
in2.close();
out2.close();
providerSocket.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
/**
* Sends a String to the current client
*
* @param player the current player
* @param msg the String to be sent
*/
void sendString(int player, String msg) {
try {
if (player == 1) {
out.writeObject(msg);
out.flush();
} else {
out2.writeObject(msg);
out2.flush();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* Sends a String to the current client
*
* @param player the current player
* @param array the 2D array to be sent
*/
void send2D(int player, int[][] array) {
try {
if (player == 1) {
out.writeObject(array);
out.flush();
} else {
out2.writeObject(array);
out2.flush();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* Sends a int to the current client
*
* @param player the current player
* @param msg the int to be sent
*/
void sendInt(int player, int msg) {
try {
if (player == 1) {
out.writeObject(msg);
out.flush();
} else {
out2.writeObject(msg);
out2.flush();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* Main method, invoking run() method
*/
public static void main(String args[]) {
Provider server = new Provider();
server.run();
}
}
谢谢!
答案 0 :(得分:1)
答案 1 :(得分:1)
首先,将实际的Tic-Tac-Toe内容与您的通信层完全分开。您的通信层基本上应该从任何客户端接收消息,找出哪个Tic-Tac-Toe实例属于该客户端,然后发送消息。同样,Tic-Tac-Toe实例可能需要通过通信层向其玩家发送消息。
我想你的TicTacToe类将有一个非常简单的API,如下所示:
public Result mark(int row, int col, int playerID);
结果可以是VALID,INVALID_MOVE,PLAYER_WINS或DRAW等类似的东西。使用这样的界面,您可以在进入网络之前轻松创建单人游戏版本。
最后,您将需要1个专门调用serverSocket.await()的线程,等待2个传入连接,然后创建一个新的Tic-Tac-Toe实例。无论何时来自这两个客户端的消息,您都会将其分派给该特定实例。您需要某种方法来查找给定套接字的TicTacToe实例,从输入流中提取消息,修改TicTacToe实例,然后将消息发送回2个玩家客户端。
每个插槽连接还需要一个额外的线程。每次尝试从套接字的输入流中读取时,都需要等待实际从客户端发送一些数据。这是线程发挥作用的地方。
哦,顺便说一下,java.util.concurrent包提供了使网络服务器更具可扩展性和效率的方法,但它非常复杂。此外,大多数使用它的方式实际上是单线程的(这实际上是为什么它更具可扩展性,信不信由你)。我建议明确指导这项任务。