选用 char board15 固定数组最稳妥,因15×15尺寸确定、内存连续、访问高效、调试友好;动态分配易越界难维护,初始化须遍历全部0..14置空格,坐标映射严格遵循0-based(用户第3行第5列→board2),输入校验须前置。

直接初始化二维数组存五子棋盘,用 char board[15][15] 最稳妥,别用指针模拟或 malloc 嵌套二维——容易越界、难调试、赢面小。
为什么选固定大小的二维数组而不是动态分配
五子棋标准棋盘是 15×15,尺寸确定,编译期可知。用 char board[15][15]:
- 内存连续,
board[i][j]访问就是一次地址计算,无间接跳转,性能稳 - 栈上分配(若定义在函数内)或全局/静态存储,生命周期清晰,不担心
free忘记或重复释放 - 调试时 IDE 能直接展开查看整块棋盘,GDB 里
print board也友好 - 反例:
char **board = malloc(15 * sizeof(char *))再循环 malloc 每行——多一层指针,board[15][0]会越界而无声崩溃
InitBoard() 函数必须清空所有格子,且只清有效区域
常见错误是只初始化了前几行,或把边界数字也当棋子位置清掉。正确做法:
- 用双重 for 循环遍历全部
[0..14][0..14],统一设为' '(空格)或0,表示无子 - 不要在初始化函数里塞坐标数字打印逻辑——那是
DisplayBoard()的事,混在一起会导致棋盘状态被污染 - C 语言中若用
char board[15][15] = {0}全局定义,编译器自动零初始化,可省掉显式循环;但局部变量不行,必须手动清 - Java 中
char[][] board = new char[15][15]默认全\u0000,等价于 C 的0,但注意后续判断要用board[i][j] == '\u0000',不是null
坐标映射必须对齐“人眼习惯”和“数组索引”
用户输入“第 3 行第 5 列”,程序里得转成 board[2][4] ——这个转换错一个数,整个胜负判断就全偏移:
- 约定:数组
[i][j]对应第i+1行、第j+1列(即 0-based 索引),这是所有教材和库函数(如getPieceAt(int row, int col))的默认行为 - 输入校验必须立刻做:收到
x, y后先判断x 15 || y 15,再转成board[x-1][y-1],别等到落子后再检查 - 别用
board[y][x]反着存——虽然数学上能转,但和所有文档、调试输出、甚至 AI 算法接口都不兼容 - 如果后期要加图形界面或网络传输,坐标协议必须和此处一致,否则联机对弈时双方看到的棋盘是镜像的
地图类数据(如 RPG 游戏区域)可以复用同一套初始化逻辑
只要结构是网格状、每个格子有独立状态(地形、物品、NPC),就完全适用:
- 把
char换成int或自定义 struct,比如Tile map[50][50],初始化时调用相同结构的InitMap() - 关键差异在初始值:
board初始化为空格,map可能初始化为TILE_GRASS或0表示可通行 - 共用同一个二重循环模板,但别强行合并函数——
InitBoard()和InitMap()语义不同,硬塞进一个函数会让参数膨胀、意图模糊 - 警惕“伪动态”:有人用
#define SIZE 15然后写char b[SIZE][SIZE],看起来灵活,但 SIZE 改了不改所有循环边界,照样越界
最易被忽略的是:初始化之后没做边界测试——比如往 board[-1][7] 写入,C 不报错但破坏栈上其他变量;Java 会抛 ArrayIndexOutOfBoundsException,但如果你在 catch 里吞掉异常并继续运行,棋盘就静默错乱了。

















