
本文针对一个简单的井字棋游戏,重点解决了胜负判断功能失效的问题。通过分析错误原因,并提供正确的代码示例,详细讲解了如何准确地检测游戏中的获胜条件,确保程序能够正确判定胜负,并避免潜在的逻辑错误。
胜负判断逻辑修正
原代码中,胜负判断的核心问题在于使用了错误的集合方法。ArrayList
错误代码:
if(plaeyer1position.contains(l)){
return "Spieler 1 gewonnen";
} else if (plaeyer2position.contains(l)) {
return "Spieler 2 gewonnen";
}plaeyer1position.contains(l) 检查的是 plaeyer1position 是否包含整个 List
正确的做法是使用 containsAll() 方法,判断 plaeyer1position 是否包含 l 中的 所有 元素。
正确代码:
if(plaeyer1position.containsAll(l)){
return "Spieler 1 gewonnen";
} else if (plaeyer2position.containsAll(l)) {
return "Spieler 2 gewonnen";
}X.containsAll(Y) 会检查 X 是否包含 Y 中的所有元素。这样,只要玩家1或玩家2占据了 gewinner 列表中的任何一个获胜组合的所有位置,就能正确判定胜负。
优化建议
除了修正胜负判断逻辑外,还可以对代码进行一些优化,提高可读性和健壮性。
- 代码国际化: 避免在代码中使用德语注释和输出,统一使用英语,方便代码维护和共享。
- 简化胜负判断: 将判断平局的逻辑放在循环外面,可以减少不必要的判断。
- 避免重复打印棋盘: bestimmmung_der_position 方法中调用了 gameboard 方法,导致每次落子后棋盘打印两次,可以移除 bestimmmung_der_position 方法中的 gameboard(board) 调用。
- 输入验证: 增加对玩家输入位置的验证,防止输入超出范围的数字或已被占用的位置。
-
可读性优化: 将 List 改为 List
增加代码可读性。
以下是优化后的 checkWinner() 方法:
public static String checkWinner() {
List top_zeile = Arrays.asList(1, 2, 3);
List mid_zeile = Arrays.asList(4, 5, 6);
List bot_zeile = Arrays.asList(7, 8, 9);
List links_reihe = Arrays.asList(1, 4, 7);
List mitte_reihe = Arrays.asList(2, 5, 8);
List rechts_reihe = Arrays.asList(3, 6, 9);
List diagonale_rechts = Arrays.asList(1, 5, 9);
List diagonale_links = Arrays.asList(7, 5, 3);
List> gewinner = new ArrayList<>();
gewinner.add(top_zeile);
gewinner.add(mid_zeile);
gewinner.add(bot_zeile);
gewinner.add(links_reihe);
gewinner.add(mitte_reihe);
gewinner.add(rechts_reihe);
gewinner.add(diagonale_links);
gewinner.add(diagonale_rechts);
for (List l : gewinner) {
if (plaeyer1position.containsAll(l)) {
return "Player 1 wins!";
} else if (plaeyer2position.containsAll(l)) {
return "Player 2 wins!";
}
}
if (plaeyer1position.size() + plaeyer2position.size() == 9) {
return "No player wins.\n";
}
return "";
}
完整示例代码(包含优化建议)
import java.util.*;
public class TicTacToe {
static ArrayList plaeyer1position = new ArrayList<>();
static ArrayList plaeyer2position = new ArrayList<>();
public static void main(String[] args) {
char[][] board = {{' ', '|', ' ', '|', ' '},
{'-', '+', '-', '+', '-'},
{' ', '|', ' ', '|', ' '},
{'-', '+', '-', '+', '-'},
{' ', '|', ' ', '|', ' '}};
gameboard(board);
Scanner scn = new Scanner(System.in); // Scanner should be initialized once
while(true) {
System.out.println("Player 1, enter your position (1-9):");
int position = getValidPosition(scn, board);
bestimmmung_der_position(board, position, "Player 1");
gameboard(board); // Print board after Player 1's move
String result = checkWinner();
if (!result.isEmpty()) {
System.out.println(result);
break;
}
System.out.println("Player 2, enter your position (1-9):");
int position2 = getValidPosition(scn, board);
bestimmmung_der_position(board, position2, "Player 2");
gameboard(board); // Print board after Player 2's move
result = checkWinner();
if (!result.isEmpty()) {
System.out.println(result);
break;
}
if (plaeyer1position.size() + plaeyer2position.size() == 9) {
System.out.println("It's a draw!");
break;
}
}
scn.close(); // Close the scanner to prevent resource leaks
}
public static void gameboard(char[][] board) {
for (char[] row : board) {
for (char c : row) {
System.out.print(c);
}
System.out.println();
}
}
public static void bestimmmung_der_position(char[][] board,int position, String spieler) {
char symbol = ' ';
if(spieler.equals("Player 1")){
symbol = 'X';
plaeyer1position.add(position);
} else if (spieler.equals("Player 2")) {
symbol = 'O';
plaeyer2position.add(position);
}
switch (position) {
case 1:
board[0][0] = symbol;
break;
case 2:
board[0][2] = symbol;
break;
case 3:
board[0][4] = symbol;
break;
case 4:
board[2][0] = symbol;
break;
case 5:
board[2][2] = symbol;
break;
case 6:
board[2][4] = symbol;
break;
case 7:
board[4][0] = symbol;
break;
case 8:
board[4][2] = symbol;
break;
case 9:
board[4][4] = symbol;
break;
default:
break;
}
//gameboard(board); // Removed duplicated call
}
public static String checkWinner(){
List top_zeile = Arrays.asList(1, 2, 3);
List mid_zeile = Arrays.asList(4, 5, 6);
List bot_zeile = Arrays.asList(7, 8, 9);
List links_reihe = Arrays.asList(1, 4, 7);
List mitte_reihe = Arrays.asList(2, 5, 8);
List rechts_reihe = Arrays.asList(3, 6, 9);
List diagonale_rechts = Arrays.asList(1, 5, 9);
List diagonale_links = Arrays.asList(7, 5, 3);
List> gewinner = new ArrayList<>();
gewinner.add(top_zeile);
gewinner.add(mid_zeile);
gewinner.add(bot_zeile);
gewinner.add(links_reihe);
gewinner.add(mitte_reihe);
gewinner.add(rechts_reihe);
gewinner.add(diagonale_links);
gewinner.add(diagonale_rechts);
for (List l : gewinner) {
if (plaeyer1position.containsAll(l)) {
return "Player 1 wins!";
} else if (plaeyer2position.containsAll(l)) {
return "Player 2 wins!";
}
}
return "";
}
public static int getValidPosition(Scanner scanner, char[][] board) {
int position;
while (true) {
try {
position = scanner.nextInt();
if (position < 1 || position > 9) {
System.out.println("Invalid input. Please enter a number between 1 and 9:");
} else if (isPositionTaken(position, board)) {
System.out.println("Position is already taken. Please choose another position:");
} else {
break; // Valid input, exit the loop
}
} catch (InputMismatchException e) {
System.out.println("Invalid input. Please enter a number:");
scanner.next(); // Consume the invalid input to prevent an infinite loop
continue;
}
}
return position;
}
public static boolean isPositionTaken(int position, char[][] board) {
switch (position) {
case 1:
return board[0][0] != ' ';
case 2:
return board[0][2] != ' ';
case 3:
return board[0][4] != ' ';
case 4:
return board[2][0] != ' ';
case 5:
return board[2][2] != ' ';
case 6:
return board[2][4] != ' ';
case 7:
return board[4][0] != ' ';
case 8:
return board[4][2] != ' ';
case 9:
return board[4][4] != ' ';
default:
return true; // Should not happen, but handle it to avoid errors
}
}
}
总结
通过修正 checkWinner() 方法中的集合判断逻辑,并加入输入验证等优化措施,可以使井字棋游戏更加健壮和易用。 记住,理解集合类型的区别和正确使用集合方法是编写可靠代码的关键。 此外,良好的代码风格和注释也能显著提高代码的可读性和可维护性。










