
怎么用二维数组表示五子棋盘和落子状态
棋盘本质就是个 char[][] 或 int[][],每个位置存空、黑子、白子——别用 String[][],内存和比较都慢;也别用 boolean[][],两种状态不够,得区分“空”“黑”“白”。推荐用 int:0 表示空,1 表示黑子,2 表示白子,后续判定逻辑更直白。
常见错误是初始化时写成 new int[15][15] 却忘了边界检查,用户输 15,15 就直接 ArrayIndexOutOfBoundsException。实际下标范围是 0–14,输入要先减 1,且必须校验是否在 [0, 14] 内。
实操建议:
- 声明为
private static final int BOARD_SIZE = 15;,所有地方统一引用,别硬写 15 - 初始化后用双重循环填 0,别依赖默认值——局部变量不自动初始化
- 打印棋盘时,行号列号从 1 开始显示(用户友好),但内部运算始终用 0 起始下标
怎么判断横/竖/斜五个连续相同棋子
不能只查“当前落子点出发的八个方向”,必须以该点为中心,向两边延展统计——否则漏判,比如已有三子连在左边,新子落在最右端,只往右查会错过。
立即学习“Java免费学习笔记(深入)”;
核心逻辑是:对四个方向(横、竖、主对角、副对角),分别计算「该点往左+往右」(或上+下等)的同色连续长度,加起来 +1 ≥ 5 就赢。方向用两个增量数组最稳:int[] dx = {0, 1, 1, 1} 和 int[] dy = {1, 0, 1, -1}。
容易踩的坑:
- 没做越界保护:循环中直接
board[x + i*dx][y + i*dy],i 一超就崩——每次访问前必须if (nx >= 0 && nx = 0 && ny - 把空位也算进连续:只统计等于当前玩家颜色的格子,遇到 0 或对方颜色立刻停
- 重复判定:一局中只要有人连五,立刻结束,别等下一轮再判——否则可能双方同时“赢”
控制台交互时怎么避免输入崩溃
用户输 “a,3” 或直接回车,Scanner.nextInt() 会卡住或抛 InputMismatchException,接着后续所有输入都乱。必须用 nextLine() 读整行,再切分解析。
推荐模式:String line = scanner.nextLine().trim(); → 检查是否为空 → 用 split("[,\s]+") 拆(兼容逗号、空格、制表符)→ 取前两个元素 → 分别转 Integer.parseInt() 并捕获 NumberFormatException。
关键细节:
- 转数字后立刻检查范围:
if (row BOARD_SIZE || col BOARD_SIZE) - 落子前必须验证该位置是否为空:
if (board[row-1][col-1] != 0),否则提示“此处已有子” - 别在异常处理里吞掉所有异常——至少
printStackTrace()或记录日志,否则 debug 时找不到错在哪
为什么 winCheck() 放在落子后而不是每轮开头
因为只有刚落下的那颗子才可能构成新的五连,检查全部位置是纯浪费——15×15=225 个点,每个点查 4 个方向,性能差且逻辑冗余。聚焦单点,复杂度从 O(n²) 降到 O(1)。
但要注意:这个优化成立的前提是,你严格保证每次只下一颗子、且只在合法空位下。如果代码里存在“自动补子”“悔棋重置未清空”等情况,单点判定就会失效。
实操要点:
- 把
winCheck(int x, int y)设为私有方法,参数是 0 起始坐标,外部调用传row-1, col-1 - 返回
boolean,不是 int 或枚举——赢了就 break 主循环,没必要知道谁赢、怎么赢 - 不要在
winCheck里打印结果,由调用方决定输出什么(比如“黑方胜!”或“游戏结束”)
最易被忽略的是:斜向判定中副对角线(从右上到左下)的 dy 是 -1,新手常写成 +1 导致永远判不出这个方向的连珠——手写一遍坐标变化比背结论管用。











