首页 > 解决方案 > Java Sockets - 无法在客户端输入第二个输入[编辑]

问题描述

我正在尝试制作一个 Connect 5 游戏,其中游戏逻辑保存在服务器端,客户端影响当前游戏状态。到目前为止,我已经实现了游戏逻辑,如果你要运行它,它就可以正常工作。在尝试实现实际的客户端/服务器端时,我遇到了问题。

我不完全确定如何去做。我现在能做的就是得到玩家的名字和棋盘的大小。在实际玩游戏时,我遇到了一些问题,例如保持游戏运行和让玩家行动。目前,服务器将在短时间内停止运行。我尝试使用 awhile(true)来保持它运行,但它似乎不起作用。

另一个问题是在客户端显示实际的棋盘——而如果您只是使用服务器类玩游戏System.out.println(fiveInARow);,我可以显示棋盘,每次移动后都会显示棋盘。我尝试过使用如何通过套接字发送字符串数组对象?显示棋盘(测试我是否可以在游戏开始时将空棋盘显示在客户端),我得到一个错误。

我是否应该做类似如何从 Java 客户端服务器程序中的控制台获取输入以从内部用户那里获取输入for (int player = 0; moves-- > 0; player = 1 - player)

更新:所以我可以移动,移动会相应地进行。但是,第二个玩家无法移动(第一次输入后无法在客户端输入输入)。

服务器

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class FiveInARow implements Runnable {
    private ArrayList<String> playerNames = new ArrayList<String>();
    private String currPlayer;
    private Socket socket;
    private Scanner scanner;
    private int width, height;
    private static final char[] PLAYERS = { 'X', 'O' };
    private char[][] gameBoard;
    private int lastCol = -1, lastRow = -1;

    public FiveInARow(Socket socket) {
        this.socket = socket;
    }

    /**
     * 
     * @param w  - Width
     * @param h  - Height
     * @param p1 - Player 1
     * @param p2 - Player 2
     */
    public FiveInARow(int w, int h, String p1, String p2) {
        width = w;
        height = h;
        gameBoard = new char[h][];
        playerNames.add(p1);
        playerNames.add(p2);

        for (int i = 0; i < h; i++) {
            Arrays.fill(gameBoard[i] = new char[w], '.');
        }
    }

    // Display the game board
    public String toString() {
        return IntStream.range(0, width).mapToObj(Integer::toString).collect(Collectors.joining("")) + "\n"
                + Arrays.stream(gameBoard).map(String::new).collect(Collectors.joining("\n"));
    }

    // Get string representation of the row containing the last play of the user
    public String horizontal() {
        return new String(gameBoard[lastRow]);
    }

    // Get string representation of the column containing the last play of the user
    public String vertical() {
        StringBuilder stringBuilder = new StringBuilder(height);

        for (int h = 0; h < height; h++) {
            stringBuilder.append(gameBoard[h][lastCol]);
        }

        return stringBuilder.toString();
    }

    // Get string representation of the "/" diagonal containing the last play of the
    // user
    public String fowardSlashDiagonal() {
        StringBuilder stringBuilder = new StringBuilder(height);

        for (int h = 0; h < height; h++) {
            int w = lastCol + lastRow - h;

            if (w >= 0 && w < width) {
                stringBuilder.append(gameBoard[h][w]);
            }
        }

        return stringBuilder.toString();
    }

    /**
     * Get string representation of the "\" diagonal containing the last play of the
     * user
     * 
     * @return
     */
    public String backSlashDiagonal() {
        StringBuilder stringBuilder = new StringBuilder(height);

        for (int h = 0; h < height; h++) {
            int w = lastCol - lastRow + h;

            if (0 <= w && w < width) {
                stringBuilder.append(gameBoard[h][w]);
            }
        }

        return stringBuilder.toString();
    }

    public static boolean contains(String str, String subString) {
        return str.indexOf(subString) >= 0;
    }

    // Determine if a game as been won
    public boolean hasWon() {
        if (lastCol == -1) {
            System.err.println("No move has been made yet");

            return false;
        }

        char symbol = gameBoard[lastRow][lastCol];
        String streak = String.format("%c%c%c%c%c", symbol, symbol, symbol, symbol, symbol);

        return contains(horizontal(), streak) || contains(vertical(), streak) || contains(fowardSlashDiagonal(), streak)
                || contains(backSlashDiagonal(), streak);
    }

    /**
     * 
     * @param symbol  - Symbol/piece to be played
     * @param scanner - Input
     */
    public void playMove(char symbol, Scanner scanner) {
        do {
            if (symbol == PLAYERS[0]) {
                currPlayer = playerNames.get(0);
            } else {
                currPlayer = playerNames.get(1);
            }

            System.out.println("\n" + currPlayer + "'s turn: ");
            int col = scanner.nextInt();

            // Check if input is valid
            if (!(0 <= col && col < width)) {
                System.out.println("Column must be between 0 and " + (width - 1));
                continue;
            }

            for (int h = height - 1; h >= 0; h--) {
                if (gameBoard[h][col] == '.') {
                    gameBoard[lastRow = h][lastCol = col] = symbol;

                    return;
                }
            }

            // If column has already been filled, we need to ask for a new input
            System.out.println("Column " + col + " is full");
        } while (true);
    }

//  public static void main(String[] args) {
//      try (Scanner input = new Scanner(System.in)) {
//          String player1Name, player2Name;
//          int height = 6;
//          int width = 9;
//          int moves = height * width;
//
//          System.out.println("Player 1 name: ");
//          player1Name = input.next();
//
//          System.out.println("Player 2 name: ");
//          player2Name = input.next();
//
//          FiveInARow fiveInARow = new FiveInARow(width, height, player1Name, player2Name);
//
//          System.out.println("Enter 0 - " + (width - 1) + " to play a piece\n");
//
//          System.out.println(fiveInARow);
//
//          for (int player = 0; moves-- > 0; player = 1 - player) {
//              char symbol = PLAYERS[player];
//
//              fiveInARow.playMove(symbol, input);
//
//              System.out.println(fiveInARow);
//
//              if (fiveInARow.hasWon()) {
//                  System.out.println("\nPlayer " + symbol + " wins!");
//
//                  return;
//              }
//          }
//
//          System.out.println("Game over. Draw game!");
//      }
//  }

    @Override
    public void run() {
        int height = 6;
        int width = 9;
        int moves = height * width;

        System.out.println("Connected: " + socket);

        try {
            FiveInARow fiveInARow = new FiveInARow(width, height, "Kevin", "Fasha");
            Scanner scanner = new Scanner(socket.getInputStream());
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);

//          while (scanner.hasNextInt()) {
//              printWriter.println(scanner.nextInt());
//          }

            System.out.println(fiveInARow);

//          while (scanner.hasNextInt()) {
            for (int player = 0; moves-- > 0; player = 1 - player) {
                char symbol = PLAYERS[player];

                fiveInARow.playMove(symbol, scanner);

                System.out.println(fiveInARow);

                if (fiveInARow.hasWon()) {
                    System.out.println("\nPlayer " + symbol + " wins!");

                    return;
                }
//              }
            }
        } catch (Exception exception) {
            System.out.println("Error: " + socket);
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
            }

            System.out.println("Closed: " + socket);
        }
    }

    public static void main(String[] args) throws Exception {
        try (ServerSocket serverSocket = new ServerSocket(59898)) {
            System.out.println("The game server is running...");
            ExecutorService pool = Executors.newFixedThreadPool(20);

            while (true) {
                pool.execute(new FiveInARow(serverSocket.accept()));
            }
        }
    }
}

客户

import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class FiveInARowClient {
    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.err.println("Pass the server IP as the sole command line argument");
            
            return;
        }
        
        try (Socket socket = new Socket(args[0], 59898)) {
            System.out.println("Enter lines of text then Ctrl+D or Ctrl+C to quit");
            
            Scanner scanner = new Scanner(System.in);
            Scanner in = new Scanner(socket.getInputStream());
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            
            while (scanner.hasNextLine()) {
                out.println(scanner.nextLine());
                
                System.out.println(in.nextLine());
            }
        }
    }
}

标签: javasocketsclient-server

解决方案


推荐阅读