棋盘用char[][]初始化为'.',落子直接写'x'或'o';输赢判断只在落子点用方向数组双向统计四向连子数≥5即胜;输入用hasnextint()校验并清缓冲区;平局判无空位且未分胜负。

用 char[][] 画棋盘,别用 int[][] 存状态
控制台五子棋的棋盘本质是“显示+逻辑”分离,但初学者常把状态和字符混在一起——比如用 0/1/2 存空位、黑子、白子,再手动映射成 '.'、'X'、'O' 去打印。这会让输赢判断和绘制耦合,改一个地方漏一个地方。
更直接的做法是:棋盘只用 char[][],初始化全填 '.',落子时直接写 'X' 或 'O'。打印时逐行输出,不用额外转换。
-
char[][] board = new char[15][15];初始化后必须用双循环赋值board[i][j] = '.';,否则全是\u0000(打印成空白或乱码) - 下标从
0开始,但用户输入习惯是1~15,读入后立刻减1,别在判断逻辑里反复加减 - 打印时每行末尾加
\n,列之间加空格(如System.out.print(board[i][j] + " ");),否则棋盘挤成一团
判断五连用方向数组,别写八个 if
检测某位置是否形成五子,本质是检查上下、左右、两对角线共四个方向,每个方向延伸出连续相同棋子的长度。硬写八段逻辑(上/下/左/右/左上/右下/右上/左下)极易出错,且重复代码多。
用两个 int[] 表示方向偏移更稳:
立即学习“Java免费学习笔记(深入)”;
int[] dx = {-1, 0, 1, 1}; // 上、右、下、右下
int[] dy = {0, 1, 0, 1}; // 对应的列偏移对每个方向,从落子点出发,分别往正反两个方向数同色棋子个数,加起来+1就是该方向总长。只要任一方向 ≥5 就赢。
- 必须检查边界:每次
x + dx[i]和y + dy[i]都要>= 0 && ,否则 <code>ArrayIndexOutOfBoundsException - 不能只数“单向”,比如只往右数3个,往左数1个,实际是4连;必须双向统计再求和
- 只在刚落子的位置触发判断,不需要遍历全盘——性能差且可能误判(比如对方刚下完你没赢,你下完才检)
Scanner 读坐标时,hasNextInt() 比 nextInt() 安全
用户输入 "3 a" 或直接回车,nextInt() 会卡住或抛异常,导致程序崩溃或进入奇怪状态。这不是输赢逻辑问题,但会让整个游戏无法持续交互。
正确做法是先用 hasNextInt() 探路,不匹配就清掉错误输入:
if (scanner.hasNextInt()) {
row = scanner.nextInt() - 1;
} else {
scanner.next(); // 丢弃非法输入
System.out.println("请输入数字!");
continue;
}- 每次读完一行后调用
scanner.nextLine()清缓冲区,否则混合nextInt()和nextLine()会导致跳过输入 - 输入范围校验要放在解析之后:确认
row和col都在0~14内,且对应位置是'.' - 别用
try-catch包裹nextInt()来处理错误——掩盖了输入流状态混乱的本质问题
平局判断不是“棋盘满了”,而是“无空位且无人胜”
15×15 共 225 个点,但实战中极少下满——通常一方早早就赢了。如果只靠计数器到 225 判平局,会忽略“提前终局”的情况,也可能因计数失误(比如覆盖落子没减计数)导致逻辑错乱。
稳妥方式是:每次落子后,检查当前棋盘是否存在 '.'。没有空位 且 刚才没人获胜,才算平局。
- 不要遍历全盘查
'.'——太慢。维护一个int emptyCount,初始化为225,每次成功落子后减1 - 减
1的时机必须严格:只在落子有效、未获胜、未重复落子时才减;撤销操作(如有)要加回 - 平局检测必须放在输赢判断之后,否则可能“赢了还报平局”
边界情况比想象中多:比如用户输错两次坐标,emptyCount 没变,但程序状态已乱;或者某次输入触发了异常退出,计数器没同步。这类细节不显眼,但一出问题就难定位。











