Реализация алгоритма Сапера

126
04 февраля 2021, 19:00

Наткнулся в интернете на реализацию сапера, но сразу понял, что работает он немного не так, как нужно. (А точнее открывает с одного клика почти все поле)

Пытался сам исправить, но все тщетно. Вот сам код реализации открытие полей. ...

Вот так реализуется раставление мин


#define FIELD_X 19
#define FIELD_Y 19
 int field[FIELD_X][FIELD_Y];

void putMines()  //Рандомно раскладываем мины
{
    for(int z=0;z<MINES_COUNT;z++)
    {
        field[1+rand()%(FIELD_X-2)][1+rand()%(FIELD_Y-2)]=9;
    }
}

Вот так реализуется прорисовка клеток


        app.clear(sf::Color(255,255,255));

        for(int yqwe = 1; yqwe <= (FIELD_Y-2); yqwe+=1)  //В цикле проходим все клетки и рисуем их с соответствующей позицией
        {
            for(int zqwe = 1; zqwe <= (FIELD_X-2); zqwe+=1)
            {
                if (opened[zqwe][yqwe])  //Если клетка открыта рисуем значение
                {
                switch (field[zqwe][yqwe])  //В зависимости от значения клетки выбираем нужный участок текстуры
                {
                    case 1: {sprite.setTextureRect(sf::IntRect(0,0,30,30)); break;}
                    case 2: {sprite.setTextureRect(sf::IntRect(31,0,61,30)); break;}
                    case 3: {sprite.setTextureRect(sf::IntRect(62,0,92,30)); break;}
                    case 4: {sprite.setTextureRect(sf::IntRect(93,0,123,30)); break;}
                    case 5: {sprite.setTextureRect(sf::IntRect(124,0,154,30)); break;}
                    case 6: {sprite.setTextureRect(sf::IntRect(155,0,185,30)); break;}
                    case 9: {sprite.setTextureRect(sf::IntRect(217,0,247,30)); break;}
                    case 0: {sprite.setTextureRect(sf::IntRect(248,0,278,30)); break;}
                    case 10: {sprite.setTextureRect(sf::IntRect(186,0,216,30)); break;}

                }
                } else {sprite.setTextureRect(sf::IntRect(186,0,216,30));}  //Иначе рисуем флажок
                sprite.setPosition((zqwe-1)*30,(yqwe-1)*30);
                app.draw(sprite);

            }
        }
        app.draw(exit.button);
        app.draw(exit.text);
        app.draw(newGame.button);
        app.draw(newGame.text);
        app.draw(settings.button);
        app.draw(settings.text);
        if (settingsWindow)
        {
        app.draw(setWin.title);
        app.draw(setWin.leftBorder);
        app.draw(setWin.rightBorder);
        app.draw(setWin.botBorder);
        app.draw(setWin.body);
        }
        if (lose)
        {
        app.draw(loseWin.title);
        app.draw(loseWin.leftBorder);
        app.draw(loseWin.rightBorder);
        app.draw(loseWin.botBorder);
        app.draw(loseWin.body);
        }
        app.display();
Answer 1

Задача открывания клетки в сапере (в том числе соседних клеток) решается примерно так:

void open(int x, int y) {
    // проверка на выход за границы:
    if (x < 0 || y < 0 || x >= width || x >= height) return;
    // если открыта мина, то игра кончается
    if (field[x][y] == MINE) {
        game_over();
        return;
    }
    // предотвращение бесконечной рекурсии: если клетка открыта, ничего не делаем
    if (opened[x][y]) return;
    // открываем клетку
    opened[x][y] = true;
    // и если нет мин рядом, то и все соседние через эту же функцию
    // если и там нет мин, они откроют уже свои соседние
    if (field[x][y] == 0) {
        open(x-1, y-1); open(x, y-1); open(x+1, y-1);
        open(x-1, y  );               open(x+1, y  );
        open(x-1, y+1); open(x, y+1); open(x+1, y+1);
    }
}

Обходить все поле да еще и с циклом на 600 итераций "про запас" - нелогичное решение, к тому же и неэффективное.

READ ALSO
Как сделать чат в глобальной сети c++ [закрыт]

Как сделать чат в глобальной сети c++ [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме

170
Заменить постояный вызов assert

Заменить постояный вызов assert

Можно как нибудь красивее написать?

127
Не правильно работает функция std::snprintf

Не правильно работает функция std::snprintf

Мне нужно чтобы выводилось Score: 0:0, а выводится так Score: 0Делаю так:

93
Как избежать множественного включения?

Как избежать множественного включения?

Можно ли создать объект класса внутри другого класса не подключая заголовочный файл в header с описанием этого классасумбурно

103