使Java Tic Tac Toe服务器多线程

时间:2009-10-13 20:01:05

标签: java multithreading

遗憾的是,我对线程没有经验。我一直在做一些“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();
}
 }

谢谢!

2 个答案:

答案 0 :(得分:1)

查看java.util.concurrent包。

答案 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包提供了使网络服务器更具可扩展性和效率的方法,但它非常复杂。此外,大多数使用它的方式实际上是单线程的(这实际上是为什么它更具可扩展性,信不信由你)。我建议明确指导这项任务。