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

时间:2016-01-05 12:45:35

标签: 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时,我使用此输入格式[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;
}

2 个答案:

答案 0 :(得分:1)

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

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

的偏移量

如果你看[2] [2]它将给出2 * 3 + 2 = 8

的偏移量

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

答案 1 :(得分:0)

访问范围数组是undefined behaviour。因此意味着您可能不会收到错误。您可能会得到奇怪的结果,如随机结果。因此,您应确保您的代码不会导致超出范围问题的解决方案。

关于-1问题,数组上的运算符[]是一种补充:

a[b]等于*( (a) + (b) )

因此,a[-1]等于*((a)+(-1))。然后,您尝试输入指针的前一个内存块。