C语言矩阵打印异常:mat[7][8]赋值后整列显示'A'求助
围棋棋盘矩阵赋值异常问题排查与修复
问题描述
开发围棋棋盘游戏时,遇到两个异常:
- 设置
mat[7][8]='A'后,整列都显示'A' - 在循环外修改矩阵值,无法达到预期显示效果
相关代码
#include "Go_1.h" #define DIMENSION 9 #define SPACELEFT 2 /* 该函数用于显示初始状态的矩阵,根据玩家选择的交叉点放置棋子(检查位置是否为空),并显示带有玩家棋子的网格 */ void grille(char mat[][TAILLE_MATRICE], int *x, int *y,char jeton,char *joueur,char lettres[],char nombres[]) { int a=0; // 用于通过ASCII码显示A--I的计数器 int b=1; // 计算网格的行列数:需要显示矩阵值的行列数为LIGNE_COLONNE const int LIGNE_COLONNE=(SPACELEFT-1)*(DIMENSION-1)+ DIMENSION;/* 注释错误:正确值是17,不是25 */ printf("\t"); printf(" "); /*2个空格*/ /* 水平显示棋盘的字母标识 */ for(int j=0;j<DIMENSION;j++) { printf("%c", 'A'+a); a++; for (int k=0; k<(2*SPACELEFT-1);k++) { printf(" "); /*5个空格 5=2*SPACELEFT-1 */ } } printf("\n"); /* 填充矩阵 */ for (int i=0;i<LIGNE_COLONNE;i+=SPACELEFT) { for (int j=0;j<LIGNE_COLONNE;j+=SPACELEFT) { mat[i][j]='0'; } } mat[7][8]='A'; /* 垂直显示棋盘的数字标识 */ for (int i=0;i<LIGNE_COLONNE;i++) /* 当前错误设置为25 */ { printf("\t"); if (i%SPACELEFT==0) { printf("%d ",b); b++; } else printf(" "); for (int j=0; j<LIGNE_COLONNE;j++) { if ((i%SPACELEFT==0)&&(j%SPACELEFT==0)) /* 交叉点的情况 */ { /* if (i==*x && j==*y) // 检查是否与玩家选择的索引一致 { if (mat[*x][*y]=='0') // 检查交叉点是否为空(即值为'0') { mat[*x][*y]=jeton; } else { printf("\tLa place est deja occupee!"); choix_pion(joueur,jeton,x,y,lettres,nombres);// 让玩家重新选择棋子位置 break; } } */ printf("%c ",mat[i][j]); } else if ((i%SPACELEFT==0)&&(j%SPACELEFT!=0)) printf("* "); else if ((i%SPACELEFT!=0)&&(j%SPACELEFT!=0)) printf(" "); else if ((i%SPACELEFT!=0)&&(j%SPACELEFT==0)) printf("* "); } printf("\n"); } return; }
问题原因分析
行列数计算错误:
代码中LIGNE_COLONNE的注释标注为25,但实际计算结果是(2-1)*(9-1)+9=17。错误的行列数导致循环访问超出矩阵的合法范围,引发数组越界,进而出现整列被意外修改的异常。矩阵初始化不完整:
当前仅初始化了步长为SPACELEFT(即2)的交叉点位置为'0',其他位置都是未定义的垃圾值。当访问这些未初始化的位置时,会出现不可预料的行为。棋子放置位置错误:
设置mat[7][8]='A'时,7不是SPACELEFT的倍数(7%2=1),该位置不属于棋盘的交叉点,不会被打印显示,因此无法达到预期效果。历史棋子被覆盖:
每次调用grille函数都会重新将所有交叉点设为'0',导致之前放置的历史棋子被清空,无法保留。
修复方案
修正行列数计算:
移除错误的注释,确保LIGNE_COLONNE的计算结果正确:const int LIGNE_COLONNE=(SPACELEFT-1)*(DIMENSION-1)+ DIMENSION; // 正确结果为17完整初始化矩阵:
先将整个矩阵初始化为默认值(比如空格),再设置交叉点为'0',避免垃圾值干扰:// 初始化整个矩阵 for (int i=0;i<LIGNE_COLONNE;i++) { for (int j=0;j<LIGNE_COLONNE;j++) { mat[i][j] = ' '; } } // 初始化交叉点 for (int i=0;i<LIGNE_COLONNE;i+=SPACELEFT) { for (int j=0;j<LIGNE_COLONNE;j+=SPACELEFT) { mat[i][j]='0'; } }在交叉点放置棋子:
确保棋子放在符合规则的交叉点上,比如将mat[7][8]='A'改为mat[6][8]='A'(6是2的倍数,属于交叉点行):mat[6][8]='A';分离初始化与打印逻辑:
将矩阵初始化逻辑移到grille函数外部,仅在游戏开始时执行一次。grille函数只负责打印当前棋盘状态和处理新棋子的放置,避免历史棋子被覆盖。
内容的提问来源于stack exchange,提问作者Elas
相关产品推荐
相关产品推荐

