Создание простого приложения Minesweeper с использованием 2D вектора

Я пытаюсь создать простое приложение Minesweeper, используя 2D вектор. Сначала я заполняю квадраты цифрами 1 и 0 (1 означает мины, а 0 — ясно).

srand(time(NULL));
for (int i = 0; i < battlefield.size(); i++)
{
for (int j = 0; j < battlefield[i].size(); j++)
{
int num = (rand() % 2);
battlefield[i][j] = num;
}
}`

Затем я снова прохожу вектор и подсчитываю количество окружающих мин. Вот где у меня проблемы. Я думаю, что когда он пытается проверить квадрат, который находится за пределами, он взрывается. Однако, если не удается до любой из этих проверок. Если не удается, когда он пытается увидеть, равен ли текущий квадрат 1.

for (int i = 0; i < battlefield.size(); i++)
{
for (int j = 0; j < battlefield[i].size(); j++)
{
int count = 0;
if (battlefield[i][j] == 1)//mine square
{
if (battlefield[i - 1][j - 1] != 0)
{
count++;
}
if (battlefield[i][j - 1] != 0)
{
count++;
}
if (battlefield[i + 1][j - 1] != 0)
{
count++;
}
if (battlefield[i - 1][j] != 0)
{
count++;
}
if (battlefield[i + 1][j] != 0)
{
count++;
}
if (battlefield[i - 1][j + 1] != 0)
{
count++;
}
if (battlefield[i][j + 1] != 0)
{
count++;
}
if (battlefield[i + 1][j + 1] != 0)
{
count++;
}
battlefield[i][j] = count;
}
}

Я не совсем уверен, почему это терпит неудачу, какие-либо идеи?

1

Решение

Если ваша шахта находится на уровне 0,0, то первая проверка, которую вы выполните, проверит -1, -1, что выходит за пределы, буквально взорвав вашу программу.

Вы должны сначала проверить свои границы.

1

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

Вам действительно повезло. Доступ вне границ std::vector «неопределенное поведение», и программа останавливается, только если вам повезет.

Если вам не повезло, программа все равно «работает», и вы продолжаете добавлять функции, пока не наступит день отгрузки … и она взорвется только на широком экране компьютера клиента во время собрания акционеров 🙂

На мой взгляд, более простая реализация будет

int i0 = std::max(0, i-1), i1 = std::min(height-1, i+1);
int j0 = std::max(0, j-1); j1 = std::min(width-1, j+1);
int count = 0;
for (int i=i0; i<=i1; i++) {
for (int j=j0; j<=j1; j++) {
if (mine[i][j]) count++;
}
}

в основном, сначала вычисляя безопасные границы, а затем зацикливая их, вместо того, чтобы отдельно указывать всех соседей в коде.

1

Сделайте функцию «CheckTile»

bool CheckTile(int i, int j)
{
// check if both i and j are in the map bounds, return false if not
if(i < 0 || i >= battlefield.size() || j < 0 || j >= battlefield.size())
return false;

// return true if the tile is a mine, false if not
return (battlefield[i - 1][j - 1] != 0);
}

В основном замените внутренности всех ваших проверок if звонками в CheckTile. Ваш текущий код ломается, потому что вы не выполняете проверку границ массива, поэтому, когда он читает

if(battlefield[i - 1][j - 1] != 0)

В первый раз он пытается прочитать расположение массива (-1, -1), которое находится за пределами выделенной памяти, что приводит к ошибке. Замените это на

if(CheckTile(i - 1, j - 1))

И он будет делать то же самое, но с добавленной проверкой границ защиты.

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