Komputer gra w sapera

0

Witam wszystkich,
ostatnio napisałem w C++ projekt - sapera. Wszystko świetnie działa ale chciałem go zmodyfikować tak, aby plansze rozwiązał komputer(zawsze wygrywa). Chciałbym Was prosić o pomoc z wymyśleniem najlepszego schematu takie programu. Plansza jest tablicą dwuwymiarową dynamiczną o ilości min i wielkości podanej przez gracza. Każde pole zawiera informację o tym czy jest zakryte czy nie oraz liczbą min dookoła niego. Myślałem o tym by komputer szedł wierszami aż nie znajdzie pola odkrytego z liczbą inną niż 0 i wtedy rozpatruje obszar wokół niego ale wydaje mi się to żmudne i długie( duża ilość opcji - warunków if). Macie pomysł jak najlepiej się za to zabrać?Czy w ogóle da się za to inaczej zabrać?
Pozdrawiam serdecznie i wszystkie pomysły mile widziane :),
początkujący programista.

0

Komputer nie wygra za każdym razem ponieważ może trafić przy 1 razie na minę, a 1 kwadrat też mu nic nie da.
Jeśli oczywiście chcesz to zrobić niby uczciwie.(Komputer nie zna wartości pól, niby)
Ja bym to zrobił tak:
-Komputer randomowo odkrywa 3 pola obok siebie - wtedy zdobywa już jakieś pole to manewru.
-funkcja czytająca odkryte pola(i sprawdzająca ile miejsc w pobliżu ma odkrytych, jeżeli zostaje tylko tyle pól nieodkrytych co wartość pola to stawia tam bomby, a jeśli w pobliżu kwadracie o jakiejś tam wartości jest już tyle bomb jaka jest wartość to odkrywa sąsiednie pola tego pola.
Wszystko odświeża się cały czas i cały czas sczytuję obecne wartości pól.
Powinno zadziałać.

0

Hmm, grałeś kiedyś w sapera? ;p Zagraj troszkę i zobacz jak to działa, bardzo prosto.

No tak, ale co w przypadku gdy ilość pół nieodkrytych jest większa od wartości pola?

funkcja sprawdza wszystkie pola, więc dla któregoś na pewno postawi bombę i znów sprawdza wszystkie(z nowymi wiadomościami jakie posiada) i tak ect.
Rozumiesz? ;p

0

Jeżeli już zacznie działać tak jak opisałem to nie wiem co by musiało się zdarzyć żeby tak robiąc komputer nie miał gdzie postawić bomby, jest to wręcz niemożliwe... naprawdę, pograj troszkę w sapera, przeczytaj to co napisałem i zastanów się nad tym...
Saper to banalna gra, i ktoś to już wie jak działa może przy szczęściu że nie trafi bomby na starcie wygrać bez problemu.
Radzę ci pograć ale przy tym zastanawiaj się jak to działa i ogarniesz o co chodzi ;)

0

Moim zdaniem w saperze nie powinno być możliwości wybrania bomby na starcie (i tak chyba jest w większości popularnych implementacji? - nie mogę sprawdzić.) W każdym razie - wracając do implementacji samego sapera - można wypełnić planszę bombami dopiero po pierwszym odsłonięciu pola przez użytkownika, z pominięciem tego odsłoniętego pola. Wtedy nie da się przegrać po jednym ruchu.

0

Wątpię, (a nawet bardzo wątpię :)) by komuś się chciało to wszystko sprawdzać ale jak ktoś ma ochotę to byłbym bardzo wdzięczny o rzucenie okiem czy w ogóle dobrze się za to zabrałem. Generowanie planszy, ustawianie min itd działa bardzo dobrze, chodzi mi tylko o rozwiązanie planszy przez komputer.Wiem, że kod jest beznadziejny pod względem trudności, wyglądu, sposobu pisania ale zacząłem programować dopiero od niedawana i wciąż się uczę więc za to z góry przepraszam. Parametry kodu:
nowagra1 zawiera tylko informacje o wymiarach tablicy oraz ilości min (podane przez użytkownika).
t- tablica dwuwymiarowa struktur (pole to struktura o informacji odkryte(bool), wartość pola).

void odkryj_plansze(pola** t, int x, int y, nowagra& nowagra1)
{
    if (x < 0 || x > nowagra1.N - 1)
        return; // poza tablicą wyjście
    if (y < 0 || y > nowagra1.M - 1)
        return; // poza tablicą wyjście
    if (t[x][y].odkryte)
        return; // już odkryte wyjście

    if (t[x][y].wartosc != 9 && t[x][y].odkryte == false)
        t[x][y].odkryte = true; // odkryj!

    if (t[x][y].wartosc != 0)
        return; // wartość > 0 wyjście

    //wywołanie funkcji dla każdego sąsiada
    odkryj_plansze(t, x - 1, y - 1, nowagra1);
    odkryj_plansze(t, x - 1, y, nowagra1);
    odkryj_plansze(t, x - 1, y + 1, nowagra1);
    odkryj_plansze(t, x + 1, y - 1, nowagra1);
    odkryj_plansze(t, x + 1, y, nowagra1);
    odkryj_plansze(t, x + 1, y + 1, nowagra1);
    odkryj_plansze(t, x, y - 1, nowagra1);
    odkryj_plansze(t, x, y, nowagra1);
    odkryj_plansze(t, x, y + 1, nowagra1);
}
bool sprawdzczyzakryte(pola** t, int x, int y, nowagra nowagra1) //sprawdza czy pole jest zakryte
{
    bool sprawdz = true;
    if (x < 0 || x > nowagra1.N - 1)
        return sprawdz; // poza tablicą wyjście
    if (y < 0 || y > nowagra1.M - 1)
        return sprawdz; // poza tablicą wyjście
    if (t[x][y].odkryte)
        sprawdz = true;
    else
        sprawdz = false;
    return sprawdz;
}
int ilepol(pola** t, int x, int y, nowagra nowagra1) //liczy ile pól obok danego pola jest zakrytych
{
    int licza = 0;
    if (!sprawdzczyzakryte(t, x + 1, y, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x - 1, y - 1, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x - 1, y, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x - 1, y + 1, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x + 1, y - 1, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x + 1, y + 1, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x, y - 1, nowagra1))
        licza++;
    if (!sprawdzczyzakryte(t, x - 1, y + 1, nowagra1))
        licza++;
    return licza;
}
bool sprawdzczyminy(pola** t, int x, int y, nowagra nowagra1) //sprawdza czy to mina
{
    bool sprawdz = true;
    if (x < 0 || x > nowagra1.N - 1)
        return sprawdz; // poza tablicą wyjście
    if (y < 0 || y > nowagra1.M - 1)
        return sprawdz; // poza tablicą wyjście
    if (t[x][y].wartosc == 10)
        sprawdz = true;
    else
        sprawdz = false;
    return sprawdz;
}

int ilemin(pola** t, int x, int y, nowagra nowagra1) //liczy ile min jest obok danego pola
{
    int mina = 0;
    if (!sprawdzczyminy(t, x + 1, y, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x - 1, y - 1, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x - 1, y, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x - 1, y + 1, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x + 1, y - 1, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x + 1, y + 1, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x, y - 1, nowagra1))
        mina++;
    if (!sprawdzczyminy(t, x - 1, y + 1, nowagra1))
        mina++;
    return mina;
}

void zaznaczminy(pola** t, int x, int y, nowagra nowagra1) //zaznacza mine
{
    if (x < 0 || x > nowagra1.N - 1)
        return; // poza tablicą wyjście
    if (y < 0 || y > nowagra1.M - 1)
        return; // poza tablicą wyjście
    if (!t[x][y].odkryte) {
        t[x][y].odkryte = true;
        t[x][y].wartosc = 10;
    }
    zaznaczminy(t, x - 1, y - 1, nowagra1);
    zaznaczminy(t, x - 1, y, nowagra1);
    zaznaczminy(t, x - 1, y + 1, nowagra1);
    zaznaczminy(t, x + 1, y - 1, nowagra1);
    zaznaczminy(t, x + 1, y, nowagra1);
    zaznaczminy(t, x + 1, y + 1, nowagra1);
    zaznaczminy(t, x, y - 1, nowagra1);
    zaznaczminy(t, x, y + 1, nowagra1);
}
void zmienwartosc(pola** t, int x, int y, nowagra nowagra1) // zmniejsza wartość pól wokół których zaznaczono mine
{
    if (x < 0 || x > nowagra1.N - 1)
        return; // poza tablicą wyjście
    if (y < 0 || y > nowagra1.M - 1)
        return; // poza tablicą wyjście
    if (t[x][y].odkryte && t[x][y].wartosc != 10 && t[x][y].wartosc != 0) {

        t[x][y].wartosc--;
    }
    zmienwartosc(t, x - 1, y - 1, nowagra1);
    zmienwartosc(t, x - 1, y, nowagra1);
    zmienwartosc(t, x - 1, y + 1, nowagra1);
    zmienwartosc(t, x + 1, y - 1, nowagra1);
    zmienwartosc(t, x + 1, y, nowagra1);
    zmienwartosc(t, x + 1, y + 1, nowagra1);
    zmienwartosc(t, x, y - 1, nowagra1);
    zmienwartosc(t, x, y + 1, nowagra1);
}
void odkryjpola(pola** t, int x, int y, nowagra nowagra1) // odkrywa pola (obszarowo jak w saperze)
{

    odkryj_plansze(t, x - 1, y - 1, nowagra1);
    odkryj_plansze(t, x - 1, y, nowagra1);
    odkryj_plansze(t, x - 1, y + 1, nowagra1);
    odkryj_plansze(t, x + 1, y - 1, nowagra1);
    odkryj_plansze(t, x + 1, y, nowagra1);
    odkryj_plansze(t, x + 1, y + 1, nowagra1);
    odkryj_plansze(t, x, y - 1, nowagra1);
    odkryj_plansze(t, x, y + 1, nowagra1);
}

void komp(pola** t, nowagra nowagra1) // głowna funckja
{

    int miny = 0;
    int liczba = 0;
    odkryj_plansze(t, 0, 0, nowagra1); //odkrywa pierwsze pole (pierwszy ruch)
    liczba = ilepol(t, 0, 0, nowagra1); //liczy ile jest obok niego zasłoniętych
    if (liczba > 1) //jeżeli nie ma przynajmniej dwóch odsłoniętych to odkrywa randomowe obok - jest możliwość wejscia na mine.
    // by tablica się wypełniała po pierwszym kliknieciu ale na razie chce aby przynajmniej tak działo.
    {
        odkryj_plansze(t, 1, 0, nowagra1);
        odkryj_plansze(t, 0, 1, nowagra1);
        liczba = 0;
    }
    else // jezeli 1 ruch odslonil obszar
    {
        liczba = 0;
        bool koniec;
        koniec = false;

        while (!koniec) // aż sie nie skonczy gra
        {

            for (int i = 0; i < nowagra1.N; ++i) //  ustawienie min na całej tablicy - tam gdzie są na pewno.
            {
                for (int j = 0; j < nowagra1.M; ++j) {
                    if (t[i][j].odkryte) {
                        liczba = ilepol(t, i, j, nowagra1); //ile pol zakrytych w sąsiedzwie tego pola
                        if (liczba == t[i][j].wartosc) // jezeli tyle samo co wartosc pola to znaczy ze sa to miny
                        {
                            zaznaczminy(t, i, j, nowagra1);
                            liczba = 0;
                        }
                        miny = ilemin(t, i, j, nowagra1); //jezeli min obok pola jest tyle samo co liczba pola to mozna odslonic reszte pol zakrytych
                        if (t[i][j].wartosc == miny) {
                            odkryjpola(t, i, j, nowagra1);
                            miny = 0;
                        }
                    }
                    else
                        break;
                }
            }
            for (int i = 0; i < nowagra1.N; ++i) // zmniejszenie liczby pol
            {
                for (int j = 0; j < nowagra1.M; ++j) {
                    if (t[i][j].wartosc == 10)
                        zmienwartosc(t, i, j, nowagra1);
                }
            }

            if (czy_wygrana(t, nowagra1))
                koniec = true;
        }
    } 

Jeżeli ktoś ma ochotę i czas to zapraszam do komentowania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1