java - 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());
}
}
}
}
解决方案
推荐阅读
- c - 在 C 中使用 scanf;%i 和 %d 在签名或未签名的问题上是否相同?
- python - 我有两个(.py)文件。当第一个程序结束时,它会自行关闭,然后打开并运行第二个程序文件。我该怎么做?
- java - java.util.ServiceConfigurationError: org.apache.juli.logging.Log: org.eclipse.jetty.apache.jsp.JuliLog 不是子类型
- tensorflow2.x - Tensorflow 2.2 和 cudnn 8.0.3 不能正常工作。它仍然在寻找 cudnn 7.6.5 dll 文件
- kubernetes - Ngnix Ingress Controller 提供长期支持
- c++ - cpp 中的递归函数给出错误“分段错误(核心转储)”
- python - 将每行中的多个 csv 元素读取到单独的列表中
- python - Python sqlite3 和查询优化的问题
- android - Flutter:如何在 Flutter 小部件中显示 Android 片段
- wxwidgets - WxSocket(未在此范围内声明)