c++ - 为什么我可以索引到包含超出范围的数字的 3-D 数组并仍然访问数组中的最后一个数字?

标签 c++ arrays indexing

我正在制作一个程序,可以让我用电脑玩棋盘游戏。我创建了一个包含 3 个字符的 3 个数组来创建网格。

char grid[3][3] = { {' ',' ',' '},
                    {' ',' ',' '},
                    {' ',' ',' '}};

我使用这种格式接收输入:

cout << "\n";
cout << "                                   |     |      \n";
cout << "                                7  |  8  |  9   \n";
cout << "                              _____|_____|_____ \n";
cout << "                                   |     |      \n";
cout << "                                4  |  5  |  6   \n";
cout << "                              _____|_____|_____ \n";
cout << "                                   |     |      \n";
cout << "                                1  |  2  |  3   \n";
cout << "                                   |     |      \n";
cout << "\n";   

当用户输入 9 时,我使用它索引到 grid[3][-1](在这种情况下输入为 9):

grid[input/3][input%3-1] = userMark;

并将用户的标记放在那里,但那个空间是网格[2][2],而不是网格[3][-1]。有人能解释一下为什么我不能出现任何错误,甚至还在玩这样做之后的游戏。感谢所有帮助,谢谢!

这是我的整个程序:

#include <iostream.h.>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

char grid[3][3] = { {' ',' ',' '},
                    {' ',' ',' '},
                    {' ',' ',' '}};
char userMark = ' ';
char comMark = ' ';
int difficulty = 0;

showExample();
showGrid();
userMove();
comMove();
reset();
check();

main()
{
    //Asking if the user wants to be Xs or Os
    while(userMark != 'X' && userMark != 'O')
    {
        cout << "\n              Would you like to be Xs or Os? (enter \'X\' or \'O\')\n\n";
        cout << "                                 Mark: ";
        cin >> userMark;
    } 
    if(userMark == 'X')
    {
        comMark = 'O';
    }
    else
    {
        comMark = 'X';
    }
    system( "cls");

//Asking the uswer for the difficulty
while(difficulty <1 || difficulty > 3)
{
    cout << "                       Choose the difficulty level!\n\n";
    cout << "                         1) The computer is dumb\n";
    cout << "                         2) You may win\n";
    cout << "                         3) You will never win\n\n";
    cout << "                                level: ";
    cin >> difficulty;
}

//Looping through the game until the use wins or loses
while (check() == 0)
{
    system("cls");
    if (userMark == 'X')
    {
        userMove();
        if (check() != 0)
        {
            break;
        }
        comMove();
    }
    else
    {
        comMove();
        if (check() != 0)
        {
            break;
        }
        userMove();
    }
}

//Telling whether the user won or lost after showing the grid
showGrid();
if(check() == 1)
{
    cout << "                                   You win!\n\n\n";
}
else if (check() == 2)
{
    cout << "                                  You lose!\n\n\n";
}



return 0;
}

这是我的功能:

    showExample()
{
    /*
    * Shows the numeric values for the places using cout
    */
    cout << "\n";
    cout << "                                   |     |      \n";
    cout << "                                7  |  8  |  9   \n";
    cout << "                              _____|_____|_____ \n";
    cout << "                                   |     |      \n";
    cout << "                                4  |  5  |  6   \n";
    cout << "                              _____|_____|_____ \n";
    cout << "                                   |     |      \n";
    cout << "                                1  |  2  |  3   \n";
    cout << "                                   |     |      \n";
    cout << "\n";   
    return 0;
}

/******************************************************************/

showGrid()
{
    /*
    * Shows the grid with all of the user's moves
    */
    cout << "\n";
    cout << "                                   |     |      \n                              ";
    cout << "  " << grid[2][0] << "  |  " << grid[2][1] << "  |  " << grid[2][2] << endl;
    cout << "                              _____|_____|_____ \n";
    cout << "                                   |     |      \n                              ";
    cout << "  " << grid[1][0] << "  |  " << grid[1][1] << "  |  " << grid[1][2] << endl;
    cout << "                              _____|_____|_____ \n";
    cout << "                                   |     |      \n                              ";
    cout << "  " << grid[0][0] << "  |  " << grid[0][1] << "  |  " << grid[0][2] << endl;
    cout << "                                   |     |      \n";
    cout << "\n";
    return 0;
}

/******************************************************************/

userMove()
{
    /*
    * Asks for input from the user and puts that in grid if there is no something already there
    */
    int input = 0;
    while(input<1 || input>9 || grid[input/3][input%3-1] != ' ')
    {
        showExample();
        showGrid();
        cout << "                Please enter the place you would like to mark: ";
        cin >> input;
        system("cls");
    }

    grid[input/3][input%3-1] = userMark;
    cout << "grid: " << grid[3][3] << endl;

    return 0;
}

/******************************************************************/

comMove()
{
    /*
    * Making the computer's move based on the difficulty level 
    */
    int move = 0;
    if(difficulty == 1)
    {
        do
        {
            Sleep(700);
            srand((unsigned int)time(NULL));
            move = rand() % 9 + 1;
        } while(grid[move/3][move%3-1] != ' ');
    }
    else if (difficulty == 2)
    {

    }
    else
    {

    }
    grid[move/3][move%3-1] = comMark;

    return 0;
}

/******************************************************************/

reset()
{
    /*
    * Resets the grid to the correct places using a for loop nested in a another for loop
    */
    for(int place=0, row=0; row<3; row++)
    {
        for(int column=0; column<3; column++, place++)
        {
             grid[row][column] = ' ';
        }
    }
    return 0;
}

/******************************************************************/

check()
{
    //Checking for 3 in a row
    for(int position=0; position<3; position++)
    {
        if(grid[position][0] + grid[position][1] + grid[position][2] == userMark*3 || grid[0][position] + grid[1][position] + grid[2][position] == userMark*3)
        {
            return 1;
        }
        else if(grid[position][0] + grid[position][1] + grid[position][2] == comMark*3 || grid[0][position] + grid[1][position] + grid[2][position] == comMark*3)
        {
            return 2;
        }
    }

    //Checking diagonals for 3 in a row
    if(grid[0][0] + grid[1][1] + grid[2][2] == userMark*3 || grid[0][2] + grid[1][1] + grid[2][0] == userMark*3)
    {
        return 1;
    }
    else if(grid[0][0] + grid[1][1] + grid[2][2] == comMark*3 || grid[0][2] + grid[1][1] + grid[2][0] == comMark*3)
    {
        return 2;
    }

    return 0;
}

最佳答案

传统的 C 风格数组没有范围检查。他们只是根据您的索引计算偏移量,将偏移量添加到数组的开头,然后写入该地址。

在你的情况下 [3][-1] 将给出 3*3 - 1 = 8 的偏移量

如果你查看 [2][2],它会给出 2*3 + 2 = 8 的偏移量

因此,当您(错误地)访问 [3][-1] 时,它恰好与 [2][2] 相同,因为您有一个 3 x 3 数组。

关于c++ - 为什么我可以索引到包含超出范围的数字的 3-D 数组并仍然访问数组中的最后一个数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34612068/

相关文章:

c++ - 在 CMake 中,如何测试编译器是否为 Clang?

c++ - 如何退出 do while 循环? C++

C++ 游戏开发 : truncating float to int

javascript - 将对象转换为二维数组

javascript - AngularJS - 将数组中具有相同值的对象分组到一个新数组中

python - numpy 3d 数组 -- 展平 --> 1d 数组 --> 选择 1d 中的一个元素 --> 如何知道该元素在 3d 中的索引?

c++ - 为什么我不能在opencv中将点绕点旋转90度?

arrays - 在 Go 中将指针转换为数组

python - 替换 numpy 数组中的值

python - 填充缺失的索引并将其值填充为 0