Глупое поведение многомерного массива

Проблема проста. Я сделал тиктактое 3X3 игру с массивами 3X3. Но проблема в следующем:

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

Решение

Вам нужно добавить проверку границ. Например, когда пользователь вводит координаты перемещения, вам необходимо убедиться, что они находятся в диапазоне от 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;

Вы также должны сделать то же самое в вашем Vertical а также Horizontal функции при проверке возможного допустимого перемещения. Например, если x это 2 и y 2 следующие строки из Vertical получит доступ к данным за пределами массива.

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

Это потому, что вы на самом деле обращаетесь к четвертому элементу с x+1, Этот элемент технически не существует, но с многомерным массивом вы получаете доступ tictac[0][y+1] вместо.

Вы можете обойти границы проверки в Vertical а также Horizontal добавив некоторые отступы по краям и заполните их значением, которое указывает, что они непригодны. В вашем случае увеличьте размер на 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; после этих строк или же удалить \n и положи << 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 вместо этого, чтобы избежать этого.

3

Другие решения

В случае этого массива

int array[3][3];

следующее утверждение действительно

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

так как:

  • C / C ++ не выполняет никаких пограничных проверок.
  • Массив 3х3 хранится как одномерный массив. Когда вы указываете двумерные индексы, компилятор преобразует их в одномерный индекс: [j][i] становится [j * width + i],
  • Таким образом, array[0][3] указывает на 0 * 3 + 3 (третья) ячейка в памяти, но array[1][0] указывает на 1 * 3 + 0 (также третья!) ячейка памяти, начиная с начала вашего 2D-массива.
1

По вопросам рекламы [email protected]