• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Liczby pseudolosowe w C++ ( dziwne działanie w niektórych okolicznościach )

Object Storage Arubacloud
0 głosów
264 wizyt
pytanie zadane 4 lutego 2019 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 5 lutego 2019 przez Jakub 0

Witam, napisałem ostatnio prosty testowy program w Qt. Chodziło mi żeby dało się go uruchomić na innych komputerach, kodował polskie znaki itd... oczywiście jak mówię jest to tylko test wykorzystujący bibliotekę, a nie program demonstrujący szczyt moich umiejętności ;)

Kod wygląda tak:

#include <QtWidgets>
#include <QMessageBox>
#include <QDialog>
#include <random>
#include <cstdlib>

///-----------------------------------------------------------------------

void game();

///--------------------------------main-----------------------------------

int main(int argc, char* argv[]) {
    QCoreApplication::addLibraryPath("./");
    QApplication app(argc, argv);

    int messageAnswer{0};

    messageAnswer = QMessageBox::question(
                nullptr,
                "prosta gra tekstowa :)",
                "Zagrasz?",
                QMessageBox::Yes | QMessageBox::No);

    if(messageAnswer!=QMessageBox::Yes)
        return EXIT_SUCCESS;
    else {
        game();
    }

    return EXIT_SUCCESS;
}

///-----------------------------------------------------------------------

unsigned getRandomIntigerValue(int min, int max) {
    std::random_device r;
    std::default_random_engine gen(r());
    std::uniform_int_distribution<int> dist(min, max);
    return static_cast<unsigned>(dist(gen));
}

///-----------------------------------------------------------------------

struct gameStartInfo {
    unsigned numberOfField;
    unsigned metaNumber;
    unsigned cavityNumber;
};

gameStartInfo menu() {
    bool dialogAnswer{0};
    int messageAnswer{0};
    gameStartInfo toRet;

    toRet.numberOfField = static_cast<unsigned>(QInputDialog::getInt(
                nullptr,
                "Zadecyduj",
                "Podaj ilość pól w grze 5-100:",
                12,5,100,1,&dialogAnswer));
    if(!dialogAnswer)
        exit(0);

    toRet.metaNumber = static_cast<unsigned>(QInputDialog::getInt(
                nullptr,
                "Zadecyduj",
                "Podaj number mety:",
                4,1,static_cast<int>(toRet.numberOfField-1),1,&dialogAnswer));
    if(!dialogAnswer)
        exit(0);

    do {
        toRet.cavityNumber = static_cast<unsigned>(QInputDialog::getInt(
                    nullptr,
                    "Zadecyduj",
                    "Podaj number jamy:",
                    4,1,static_cast<int>(toRet.numberOfField-1),1,&dialogAnswer));
        if(!dialogAnswer)
            exit(0);

        if(toRet.cavityNumber==toRet.metaNumber){
            messageAnswer = QMessageBox::question(
                        nullptr,
                        "Mamy problem",
                        "Number jamy nie może być równy numerowi mety!",
                        QMessageBox::Ok | QMessageBox::Cancel);
            if(messageAnswer!=QMessageBox::Ok)
                exit(0);

        }

    }while(toRet.cavityNumber==toRet.metaNumber);

    return toRet;
}

///-----------------------------------------------------------------------

void showGameStatus(const gameStartInfo& info, unsigned playerAct, unsigned pcAct) {
     int messageAnswer{0};

     QString status = QString("Ilość pól: %1\nNumer pola z metą: "
                              "%2\nNumber pola z jamą: %3\n\nTwoje aktualne pole: %4\n"
                              "Aktualne pole PC'eta: %5\n\n"
                              "Rzucamy kostką? ( 1-6 oczek )")
             .arg(info.numberOfField).arg(info.metaNumber).arg(info.cavityNumber)
             .arg(playerAct).arg(pcAct);

     messageAnswer = QMessageBox::question(
                 nullptr,
                 "Status",
                 status,
                 QMessageBox::Ok | QMessageBox::Cancel);
     if(messageAnswer!=QMessageBox::Ok)
         exit(0);

}

///-----------------------------------------------------------------------

void game(){

    gameStartInfo info = menu();
    int messageAnswer{0};

    unsigned playerAct=0, pcAct=0;

   showGameStatus(info, playerAct, pcAct);


    while(
          playerAct!=info.cavityNumber && playerAct!=info.metaNumber &&
          pcAct!=info.cavityNumber && pcAct!=info.metaNumber
          ) {

            playerAct+=getRandomIntigerValue(1,6);
            pcAct+=getRandomIntigerValue(1,6);
            playerAct%=info.numberOfField;
            pcAct%=info.numberOfField;

            showGameStatus(info, playerAct, pcAct);

    }

    QString summary = playerAct==info.cavityNumber ? QString("Przegrałeś :(") :
                      playerAct==info.metaNumber ? QString("Wygrałeś :P") :
                      pcAct==info.cavityNumber ? QString("Komputer przegrał :)") :
                                                 QString("Komputer wygrał :/");

    messageAnswer = QMessageBox::question(
                nullptr,
                "Podsumowanie",
                summary,
                QMessageBox::Ok);

}

///-----------------------------------------------------------------------

Problem dotyczy najprawdopodobniej generatora liczb losowych:

unsigned getRandomIntigerValue(int min, int max) {
    std::random_device r;
    std::default_random_engine gen(r());
    std::uniform_int_distribution<int> dist(min, max);
    return static_cast<unsigned>(dist(gen));
}

Program wykorzystuje tą funkcje do przesunięcia gracza oraz komputera na planszy o losową ilość pól z przedziału 1-6. O ile u mnie wszystko chodzi dobrze, to kiedy uruchamiam program na pendrive'ie lub innych komputerach to funkcja zawsze losuje wartość 1... nie mam pojęcia co jest grane.

Będę wdzięczny za wskazówki...

komentarz zamknięcia: problem rozwiązany.
1
komentarz 4 lutego 2019 przez niezalogowany

Jaki kompilator? Spróbuj dodać static do random_device i generatora. 

unsigned getRandomIntegerValue(unsigned min, unsigned max) {
    static std::random_device r;
    static std::default_random_engine gen(r());
    std::uniform_int_distribution<unsigned> dist(min, max);
    return dist(gen);
}
komentarz 5 lutego 2019 przez Jakub 0 Pasjonat (23,120 p.)
Dziękuje, teraz działa poprawnie. To już pewnie nie ma znaczenia ale do kompilacji wykorzystałem MinGW.

1 odpowiedź

+1 głos
odpowiedź 5 lutego 2019 przez Bondrusiek Maniak (61,410 p.)

Witam,

może spróbuj użyć klasy QRandomGenerator https://doc.qt.io/qt-5/qrandomgenerator.html , która pozwala uzyskać losowe wartości.

komentarz 5 lutego 2019 przez Jakub 0 Pasjonat (23,120 p.)
Dzięki za odpowiedź, ale jakoś nie jestem przekonany do tych funkcji z bibliotek Qt ( framework'u planuje na razie używać tylko do GUI ). Jeśli jest wybór to wolę bibliotekę standardową :)
komentarz 6 lutego 2019 przez niezalogowany
Jakub 0 biblioteka standardowa jest ok, ale nie używaj funkcji std::exit (tak samo z terminate, abort). To nie jest bezpieczne zakończenie procesów.

Podobne pytania

+1 głos
1 odpowiedź 379 wizyt
0 głosów
1 odpowiedź 325 wizyt
0 głosów
0 odpowiedzi 460 wizyt

92,674 zapytań

141,575 odpowiedzi

320,045 komentarzy

62,038 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...