You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

问题原因分析

  1. 行列数计算错误:
    代码中LIGNE_COLONNE的注释标注为25,但实际计算结果是(2-1)*(9-1)+9=17。错误的行列数导致循环访问超出矩阵的合法范围,引发数组越界,进而出现整列被意外修改的异常。

  2. 矩阵初始化不完整:
    当前仅初始化了步长为SPACELEFT(即2)的交叉点位置为'0',其他位置都是未定义的垃圾值。当访问这些未初始化的位置时,会出现不可预料的行为。

  3. 棋子放置位置错误:
    设置mat[7][8]='A'时,7不是SPACELEFT的倍数(7%2=1),该位置不属于棋盘的交叉点,不会被打印显示,因此无法达到预期效果。

  4. 历史棋子被覆盖:
    每次调用grille函数都会重新将所有交叉点设为'0',导致之前放置的历史棋子被清空,无法保留。

修复方案

  1. 修正行列数计算:
    移除错误的注释,确保LIGNE_COLONNE的计算结果正确:

    const int LIGNE_COLONNE=(SPACELEFT-1)*(DIMENSION-1)+ DIMENSION; // 正确结果为17
    
  2. 完整初始化矩阵:
    先将整个矩阵初始化为默认值(比如空格),再设置交叉点为'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';
        }
    }
    
  3. 在交叉点放置棋子:
    确保棋子放在符合规则的交叉点上,比如将mat[7][8]='A'改为mat[6][8]='A'(6是2的倍数,属于交叉点行):

    mat[6][8]='A';
    
  4. 分离初始化与打印逻辑:
    将矩阵初始化逻辑移到grille函数外部,仅在游戏开始时执行一次。grille函数只负责打印当前棋盘状态和处理新棋子的放置,避免历史棋子被覆盖。

内容的提问来源于stack exchange,提问作者Elas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 14:45:34