二维数组
Suzhou 29 0

int a[3][5];通常可以理解为如下三行五列的矩阵: 二维数组 逻辑意义上也可以认为是一个五行三列的矩阵。 ::: warning 考虑到数组在计算机内存中的排列,把第一个数字当作行号,第二个数字当作列号。 ::: 二维数组最重要的是做遍历。一维数组只有一个维度,只需要做一重循环就可以,二维数组有两个维度,需要两重循环,外面的一重遍历行号,里面的一重遍历列号,来完成对一个矩阵(二维数组)的遍历。如下:

for(i=0;i<3;i++){
    for(j=0;j<5;j++){
        a[i][j] = i*j;
    }
}

::: tip 二维数组中每一个元素是一个整数,a[i][j]表示第i行第j列上的单元。

错误的二维数组表达方式如下: a[i,j]是一个表达式,逗号是运算符,计算结果是j,即a[i,j] == a[j]。 :::


二位数组初始化的时候必须给出列数,行数可以没有,由编译器数出,如下

int a[][5] = {
    {0,1,2,3,4},
    {2,3,4,5,6},
};

上述数组可以理解成定义一个数组,这个数组中的每一个包含有五个数组,第二行表示有5个int的数组作为a0,第三行表示有5个int的数组作为a1,有省略的补0。


对矩阵的行和列做遍历、判断对角线是二维数组运算的难点。 在一个tic-tac-toe游戏中,读入一个3X3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为O,玩家使用X和O填充矩阵,如果有一方将X或者O连成一条横或竖或对角线,该玩家获胜。当程序通过输入得到了矩阵,程序要判断这个矩阵中是否有获胜的一方,并输出获胜一方所使用的字符X或O,或输出无人获胜。

const int size = 3;
int board[size][size]; //定义一个3*3的棋盘
int i,j;
int number0fX;        //棋盘中X的数量
int number0fO;        //棋盘中O的数量
int result = -1;      //-1:无人获胜,1:X,0:O

//读入矩阵
for(i=0;i<size;i++){
    for(j=0;j<size;j++){
        scanf("%d",&board[i][j]);
    }
}

//检查行
for(i=0;i<size &&result == -1;i++){
    number0fO = number0fX = 0;   //初始化棋盘上O和X的数量
    for(j=0;j<size;j++){
        if (board[i][j] == 1){   //第6行定义函数值为1,则该位置为X
            number0fX ++;
        }else{
            number0fO ++;
        }
    }
    if(number0fO == size){
        result = 0;
    }else if(number0fX == size){
        result = 1;
    }
}

//检查列
for(i=0;i<size && result == -1;i++){
    number0fO = number0fX =0;
    for(j=0;j<size;j++){
        if(board[i][j] == 1){
            number0fX ++;
        }else{
            number0fO ++;
        }
    }
    if(number0fO == size){
        result = 0;
    }else if(number0fX == size){
        result = 1;
    }
}

//检查正对角线
number0fO = number0fX = 0;
for(i=0;i<size;i++){
    if(board[i][i] == 1){
        number0fX ++;
    }else{
        number0fO ++;
    }
}
if(number0fO == size){
    result = 0;
}else if(number0fX == size){
    result = 1;
}

//检查逆对角线
number0fO = number0fX = 0;
for(i=0;i<size;i++){
    if(board[i][size-i-1] == 1){
        number0fX ++;
    }else{
        number0fO ++;
    }
}

读入矩阵时第9和第10行代码遍历行和列,第11行用scanf读入数组中的每一个元素board[i][j]。数组的名字加上下标是一个变量,所以在变量前加上符号“&”,和普通变量的读入没有区别。 第16和18行的代码表示i行上的每一列j对应的所有元素,保持行号不变,列号从0到size。第25和27行检查X和O的数量(假设是一个摆满了的3*3的棋盘),如果X或O的数量等于size,即连成一条横的线,就会决出胜负。如果没有决出胜负,就需要再检查列,算法基本等同于检查行(检查X和O的数量是否等于size,即连成竖线)。

第49到第62行检查正对角线时候,使用board[i][i]的值来判断,即判断0,0、1,1、2,2上填充的符号,第64到72行检查逆对角线时候,需要判断的是0,2、1,1、2,0位置上的符号,使用board[i][size-i-1]的值判断。检查X和O的数量是否等于size,即连成对角线。 上述四种检查后,就可以确定胜负平。

::: warning 检查行和检查列的区别主要在于循环是行在内还是列在内。 检查行时先走行,行在循环外层,每一行中检查每一列,即[i]不变[j]变; 检查列时先走列,列在循环外层,每一列中检查每一行,即[i]变[j]不变。 ::: 如下是检查行和检查列的对比: 二维数组 上述两段检查行和列的代码可以用一个两重循环合并起来。

评论区