-4

问题很简单。我用 3X3 阵列制作了一个 3X3 tictactoe 游戏。但问题是:

array[0][3] = array[1][0]

这很奇怪,因为首先,我制作的数组没有第四列。所以array[0][3]根本不存在!更复杂的是,它需要[1][0]

当我输入我的移动坐标时遇到问题:0 2

void displayBoard(int tictac[3][3])
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout << tictac[i][j] << " ";
        } cout << "\n" ;
    } cout << "\n";
}



int Horizontal(int x, int y, int tictac[3][3])
{

    if(tictac[x][y+1]==0)
    {
        tictac[x][y+1]=2;
        return 1;
    }

    if(tictac[x][y-1]==0)
    {
        tictac[x][y-1]=2;
        return 1;
    }

    if(tictac[x][y-2]==0)
    {
        tictac[x][y-2]=2;
        return 1;
    }
    if(tictac[x][y+2]==0)
    {
        tictac[x][y+2]=2;
        return 1;
    }

    return 0;
}

int Vertical(int x, int y, int tictac[3][3])
{

    if(tictac[x+1][y]==0)
    {
        tictac[x+1][y]=2;
        return 1;
    }
    if(tictac[x-1][y]==0)
    {
        tictac[x-1][y]=2;
        return 1;
    }
    if(tictac[x-2][y]==0)
    {
        tictac[x-2][y]=2;
        return 1;
    }
    if(tictac[x+2][y]==0)
    {
        tictac[x+2][y]=2;
        return 1;
    }

    return 0;
}

void AI(int X,int Y,int tictac[3][3])
{
    int done = 0;
    cout << "\n-------------------------\nComputer plays: \n";

    done = Horizontal(X,Y,tictac);
    if(done == 0)
    {
    done = Vertical(X,Y,tictac);
    }
}


int main()
{
    int tictac[3][3] = {{0,0,0},{0,0,0}, {0,0,0} };
    int X, Y;
    for(int r=1; r<100; r++)
    {
    cout << "\n-------------------------\nPlayer play a move: \n";
    cin >> X;
    cin >> Y;

    if(tictac[X][Y]==0)
    {
    tictac[X][Y] = 1;
    displayBoard(tictac);
    AI(X,Y,tictac);
    displayBoard(tictac);
    }
    else
    {
        cout << "Space occupied. Try different cell." << endl;
    }


    }





}
4

2 回答 2

3

您需要添加边界检查。例如,当用户输入移动坐标时,您需要确保它们在 0 到 2 的范围内。下面的示例验证输入以确保只输入数字,X 和 Y 坐标都输入在一行上,并且坐标在范围内。它用于std::stringstream解析坐标,而不必处理检查和清除故障位std::cin

#include <string> // at top of your .cpp file
#include <sstream>

// in main()

// Get en entire input line so we can skip extra characters
// after the cell coordinates
string inputLine;
std::getline(cin, inputLine);

stringstream inputStream(inputLine);

if(!(inputStream >> X) || !(inputStream >> Y))
{
    cout << "Please enter the cell coordinates in the form of # #" << endl;
    continue;
}

bool invalidCoordinates = false;

if(X < 0 || X > 2)
{
    cout << "invalid X location" << endl;
    invalidCoordinates = true;
}
if(Y < 0 || Y > 2)
{
    cout << "invalid Y location" << endl;
    invalidCoordinates = true;
}

// check for invalid input
if(invalidCoordinates) continue;

在检查是否可以进行有效移动时,您还需要在Verticaland函数中执行相同的操作。Horizontal例如 if xis 2 and yis 2 以下Vertical行将访问数组边界之外的数据。

if(tictac[x+1][y]==0)
{
    tictac[x+1][y]=2;
    return 1;
}

这是因为您实际上是使用 访问第四个元素x+1。这个元素在技术上是不存在的,但是你最终会访问一个多维数组tictac[0][y+1]

您可以绕过边界检查VerticalHorizontal通过在边缘周围添加一些填充并用表明它们不可用的值填充它们。在您的情况下,将每个方向的大小增加 3。

int tictac[9][9] = {
    {3,3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3,3},
    {3,3,3,0,0,0,3,3,3},
    {3,3,3,0,0,0,3,3,3},
    {3,3,3,0,0,0,3,3,3},
    {3,3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3,3},
    {3,3,3,3,3,3,3,3,3},
};

您需要对它们进行适当的调整,X以便Y它们指向正确的位置。

X += 3;  // Adjust for padding
Y += 3;  // Adjust for padding
if(tictac[X][Y]==0)
{
    tictac[X][Y] = 1;
    displayBoard(tictac);
    AI(X,Y,tictac);
    displayBoard(tictac);
}

您可能需要对代码的其他部分进行调整,但上面的示例应该可以帮助您入门。

displayBoard你的功能也有问题。当它打印出数组的元素i并被j反转时,板看起来旋转了 90 度。更改以下行

cout << tictac[i][j] << " ";

cout << tictac[j][i] << " ";

另一个问题是,您\n在输出的每一行的末尾都使用了,而没有使用std::flush来确保将行发送到控制台。您可以放在<< flush;这些行之后,可以删除\nand 放在<< endl;行尾。

cout << "\n-------------------------\nComputer plays: \n" << flush;

或者

cout << "\n-------------------------\nComputer plays: " << endl;

下面的代码是您问题中包含的原始代码的完整更新。它结合了上述建议并进行了一些其他更改。我还添加了一个残局检查以确定是否还有任何动作。

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

static const int BoardSize = 3;
static const int BoardPadding = BoardSize;
static const int ArraySize = BoardSize + (BoardPadding * 2);

void displayBoard(int tictac[ArraySize][ArraySize])
{
    for(int y = 0; y < BoardSize; y++)
    {
        for(int x = 0; x < BoardSize; x++)
        {
            cout << tictac[BoardPadding + x][BoardPadding + y] << " ";
        }
        cout << endl ;
    }
    cout << endl;
}


int Horizontal(int x, int y, int tictac[ArraySize][ArraySize])
{
    if(tictac[x][y+1]==0)
    {
        tictac[x][y+1]=2;
        return 1;
    }

    if(tictac[x][y-1]==0)
    {
        tictac[x][y-1]=2;
        return 1;
    }

    if(tictac[x][y-2]==0)
    {
        tictac[x][y-2]=2;
        return 1;
    }
    if(tictac[x][y+2]==0)
    {
        tictac[x][y+2]=2;
        return 1;
    }

    return 0;
}


int Vertical(int x, int y, int tictac[ArraySize][ArraySize])
{
    if(tictac[x+1][y]==0)
    {
        tictac[x+1][y]=2;
        return 1;
    }
    if(tictac[x-1][y]==0)
    {
        tictac[x-1][y]=2;
        return 1;
    }
    if(tictac[x-2][y]==0)
    {
        tictac[x-2][y]=2;
        return 1;
    }
    if(tictac[x+2][y]==0)
    {
        tictac[x+2][y]=2;
        return 1;
    }

    return 0;
}


void AI(int X,int Y,int tictac[ArraySize][ArraySize])
{
    int done = 0;
    cout << "\n-------------------------\nComputer plays: " << endl;

    done = Horizontal(X,Y,tictac);
    if(done == 0)
    {
        done = Vertical(X,Y,tictac);
    }
}


// Check if all moves have been made
bool isEndGame(int tictac[ArraySize][ArraySize])
{
    int count = 0;

    for(int y = 0; y < BoardSize; y++)
    {
        for(int x = 0; x < BoardSize; x++)
        {
            count += tictac[BoardPadding + x][BoardPadding + y] ? 1 : 0;
        }
    }

    return count == (BoardSize * BoardSize);
}


int main()
{
    int tictac[ArraySize][ArraySize] = {
        {3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3},
        {3,3,3,0,0,0,3,3,3},
        {3,3,3,0,0,0,3,3,3},
        {3,3,3,0,0,0,3,3,3},
        {3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3},
    };
    int X, Y;

    while(isEndGame(tictac) == false)
    {
        cout << "\n-------------------------\nPlayer play a move: " << flush;

        // Get en entire input line so we can skip extra characters
        // after the cell coordinates
        string inputLine;
        std::getline(cin, inputLine);

        stringstream inputStream(inputLine);

        if(!(inputStream >> X) || !(inputStream >> Y))
        {
            cout << "Please enter the cell coordinates in the form of # #" << endl;
            continue;
        }

        bool invalidCoordinates = false;

        if(X < 0 || X >= BoardSize)
        {
            cout << "invalid X location" << endl;
            invalidCoordinates = true;
        }
        if(Y < 0 || Y >= BoardSize)
        {
            cout << "invalid Y location" << endl;
            invalidCoordinates = true;
        }

        // check for invalid input
        if(invalidCoordinates) continue;

        // adjust the coordinates and do our thing
        X += BoardPadding;
        Y += BoardPadding; 
        if(tictac[X][Y]==0)
        {
            tictac[X][Y] = 1;
            displayBoard(tictac);
            AI(X,Y,tictac);
            displayBoard(tictac);
        }
        else
        {
            cout << "Space occupied. Try different cell." << endl;
        }
    }

    cout << "game finished...check for winner" << endl;
}

注意:使用using namespace std;. 它将命名空间中的所有内容拉std入当前范围(在本例中为全局命名空间),并可能导致冲突。最好使用完全限定的名称std::cout来避免这种情况。

于 2013-06-23T18:01:39.247 回答
1

如果是这个数组

int array[3][3];

以下陈述是有效的

array[0][3] == array[1][0]

因为:

  • C/C++ 不执行任何边界检查。
  • 3x3 数组存储为一维数组。当您指定 2D 索引时,编译器会将它们转换为 1D 索引:[j][i]变为[j * width + i].
  • 因此,array[0][3]指向0 * 3 + 3内存中的(第三个)单元,但array[1][0]指向内存的1 * 3 + 0(也是第三个!)单元,从二维数组的开头开始。
于 2013-06-23T19:27:28.047 回答