Jak zrobić, aby pytania się nie powtarzały?

0

Mam grę milionerzy.
Pytania wyglądają tak:

void pytanie1()
{
   if( !wyswietlZawartosc( "pytania/1.txt" ) )
         cout << "Nie udalo sie otworzyc pliku o podanej nazwie." << endl;
         char odp=0;
         cin>>odp;
         if(odp != 'd')
            {   
                system("cls");
                sprawdzstatus();
                getch();
            }
}

Losowanie pytań tak:

int losuj()
{
    srand(time(NULL));
    int losowa = std::rand() % 32 + 1;
}
int wylosowano(int losowa)
{
    if (losowa == 1) {
        pytanie1();
    }
    else if (losowa == 2) {
        pytanie2();
    }
    else if (losowa == 3) {
        pytanie3();
    }
    else if (losowa == 4) {
        pytanie4();
    }
    else if (losowa == 5) {
        pytanie5();
    }
    else if (losowa == 6) {
        pytanie5();
    }
    else if (losowa == 7) {
        pytanie7();
    }
    else if (losowa == 8) {
        pytanie8();
    }
    else if (losowa == 9) {
        pytanie9();
    }
    else if (losowa == 10) {
        pytanie10();
    }
    else if (losowa == 11) {
        pytanie11();
    }
    else if (losowa == 12) {
        pytanie12();
    }
    else if (losowa == 13) {
        pytanie13();
    }
    else if (losowa == 14) {
        pytanie14();
    }
    else if (losowa == 15) {
        pytanie15();
    }
    else if (losowa == 16) {
        pytanie16();
    }
    else if (losowa == 17) {
        pytanie17();
    }
    else if (losowa == 18) {
        pytanie18();
    }
    else if (losowa == 19) {
        pytanie19();
    }
    else if (losowa == 20) {
        pytanie20();
    }
    else if (losowa == 21) {
        pytanie21();
    }
    else if (losowa == 22) {
        pytanie22();
    }
    else if (losowa == 23) {
        pytanie23();
    }
    else if (losowa == 24) {
        pytanie24();
    }
    else if (losowa == 25) {
        pytanie25();
    }
    else if (losowa == 26) {
        pytanie26();
    }
    else if (losowa == 27) {
        pytanie27();
    }
    else if (losowa == 28) {
        pytanie28();
    }
    else if (losowa == 29) {
        pytanie29();
    }
    else if (losowa == 30) {
        pytanie30();
    }
    else if (losowa == 31) {
        pytanie31();
    }
    else {
        pytanie32();
    }
}

Użycie pytania w programie tak (w main) :

///pytanie 1 za 500
            statuspytania= 500;
            status500();
            wylosowano(losuj());
            system("cls");
            //kontynuuj();
///pytanie 2 za 1 000
            statuspytania= 1000;
            status1000();
            wylosowano(losuj());
            system("cls");

Jak zrobić aby pytania się nie powtarzały?
(za mało danych, piszcie to wkleję co potrzebne, nie wklejałem całości bo 1000 linijek+pliki txt)

Drugą sprawą jest jak w przypadku błędnej odpowiedzi powrócić do menu głównego?
Bo obecnei jak źle odpowiemy na pytanie to wyswietli sie info ze przegralismy, ale i tak mozna grac dalej.

4

o_O

  1. srand() wykonaj tylko na początku programu w main, a nie przed każdym losowaniem
  2. Czy gdyby pytań było np. 1000 to też byś to tak zrobił za pomocą copy-paste? ;]
1

Wklejaj kod w znaczniki C++. Podeślij cały kod. Ta drabinka 32 ifów jest okropna.

  1. Jest nieskończenie wiele sposobów. Brzydkie, słabo rozszerzalne ale działające rozwiązanie to np.: możesz do każdego pytania zrobić bool CzyByloX = false;. Srand losuje jakąś liczbę np. 16, po wylosowaniu sprawdza czy bool CzyBylo16 == true;. Jeśli true, to nie wywołujesz pytanie16();. Jeśli false, to callujesz pytanie16(); i ustawiasz tego boola na true. Ale lepiej zrobić jedną funkcję za to odpowiedzialną zamiast tworzyć pińćset booli.
  2. Stwórz jakiś bool GameFinished. Wykonuj losowanie (i wyświetlanie, itd.) pytań tylko jeśli GameFinished jest false. Jeśli odpowie się błędnie na pytanie, ustaw GameFinished na true.
    bool GameFinished = false;
    ...
    while ( ! GameFinished) {
    // losowanie
    // wyświetlanie
    // itd
    }

    Ogólnie poczytaj więcej o funkcjach, żeby kod był łatwiej rozszerzalny (i czytalniejszy).

2

Pierwsza rzecz – zapoznaj się z wektorami, bo ta drabinka if-ów nie dość, że wygląda paskudnie, to w dodatku trzeba ją będzie wydłużać, jeśli do gry dołożysz kolejne pytania. Dzięki wektorowi, możesz załadować do pamięci wszystkie pytania, następnie losować indeks i na jego podstawie wybierać dane z tego kontenera.

Jeśli koniecznie chcesz mieć pytania w osobnych plikach, to jeszcze łatwiej będzie nimi zarządzać – tzn. mniej kodu potrzeba, aby je obsługiwać. Chodzi o to, aby wylosować liczbę i tę liczbę przekazać do funkcji pytanie w parametrze, którą następnie konwertujesz na ciąg znaków i łączysz z nazwą pliku w tej instrukcji:

if( !wyswietlZawartosc( "pytania/1.txt" ) )

W miejscu 1 wstawiasz wynik konwersji liczby z parametru. Poczytaj o tym, w jaki sposób konwertować liczby na ciągi znaków i jak łączyć je w jeden łańcuch.

Kolejna rzecz to kwota, jaką w danym momencie ma gracz na ”koncie”. Znów robisz dziwne drabinki z przypisań do zmiennej statuspytania i z funkcji status500, status1000 itd. Po co to? Zadeklaruj sobie wektor, wypełnij liczbami określającymi wygraną (0, 500, 1000 itd., aż do miliona) i w jednej zmiennej przechowuj indeks kwoty, jaką w danym momencie posiada gracz. Po poprawnej odpowiedzi inkrementuj ten indeks o 1. Za pomocą tego indeksu możesz pobrać z wektora tę kwotę, aby np. wyświetlić ją na ekranie, razem z aktualnym pytaniem.

Jeśli chodzi o niepowtarzalność pytań – znów możesz użyć wektora. Ustaw jego rozmiar na zgodny z liczbą wszystkich możliwych pytań (u Ciebie będzie to 31). Wypełnij go kolejno liczbami od 1 do 31, a następnie pomieszaj losowo zawartość – do tego celu możesz użyć random_shuffle (kliknij w link, jest tam przykład kodu robiącego dokładnie to o czym piszę). Po przemieszaniu wektora, przytnij jego długość do 10 elementów. Od tej chwili, wektor ten zawiera indeksy pytań dla całej gry – teraz wystarczy Ci jedna zmienna z numerem pytania. Aby załadować dane bieżącego pytania, pobierz jego indeks z tego wektora i przekaż go do funkcji, która użyje go do otwarcia pliku.

I pisz ten kod w całości po angielsku, stosując się do wytycznych związanych z formatowaniem kodu i nazewnictwem.

2

Jak zrobić aby pytania się nie powtarzały?
1) zrob klase ktora odpowiada plikowi
2) wczytuj pytania / odpowiedzi do tej klasy. Wszystko wrzuc w std::vector zeby miec liste pytan
3) wylosuj jakies pytanie z std::vector (nie bedziesz wiedziec to napisz w komentarzu). Po czym usuwasz z std::vector

Drugą sprawą jest jak w przypadku błędnej odpowiedzi powrócić do menu głównego?
"Tryby" pracy programu
Jak stworzyć menu w konsoli

0

coś ty uczynił ten absurdalnie długi switch xD

jest kilka metod na zrobienie tego...

  1. Klasami ( zapewne odpada widząc twój kod - a to najlepsza metoda )
  2. Tablicami Funkcji ( to też odpada widząc twój kod na 100% nawet nie znasz tego określenia )
  3. na podstawie Struktury...

zapewne widząc twój kod pkt. 3 też odpada ale zamiast wypisywać jak wiele ci brakuje to opiszę ci moim zdaniem najłatwiejszą metodę do stworzenia czegoś takiego... chyba że wiesz już czym są struktury to po prostu ich użyj...

struct
{
 string Pytanie;
 string Odpowiedzi[4];
 char Odpowiedz;
 bool Dostepne;
}ListaPytan[25];

( W tym przypadku sam zakładam że będzie np. 25 róznych pytan )

dzięki takiej strukturze możesz stworzyć cały swój program ( no i w dodatku zapisywać dane i pobierać je jednym getlinem )
w każdym razie co jest to ?...

Pytanie -> Obiekt ( Zmienna ) przechowująca twoje pytanie
Odpowiedzi[4] -> Tablica typu string z 4 elementami ( domyslnie w końcu mamy A , B , C , D ^_^ )
Odpowiedz -> Obiekt ( Zmienna ) typu char przechowująca poprawną odpowiedź
Dostepne -> Obiekt ( Zmienna ) typu bool przechowywująca CZY pytanie zostało już zadane
a jeśli tak to losowane jest nowe pytanie

if(ListaPytan.Dostepne)LosujPytanie();else ZadajPytanie();

zamiast podawać na końcu nazwę obiektu możesz wykorzystać

Struct ListaPytań
{
 CTRL C / V
}

i na tej podstawie stworzyć np. kategorie

ListaPytan PytaniaHumanistyczne[25];
ListaPytan PytaniaBiologiczne[15];
ListaPytan PytaniaChemiczne[20];

warto wtedy też zrobić osobna tablica aby nie bawić się w 1000 case break...
albo skorzystać ze wskaźnika... ale wracając do poprzedniego...

widząc twój kod zakładam że uzycie wskaźników oraz bardziej zaawansowanych tablic jest nierealne dla cb :P

w każdym razie pokazałem ci jak to MNIEJ więcej zrobić ^_^...

0

Sorry, wiem że kod jest paskudny i amatorski, wiem że powinno być inaczej, robię na ile mi mój skill (a raczej jego brak) pozwala. Będę starał się to korygować i robić w bardziej "profesjonalny" sposób.

@Hodor Odnośnie twojego rozwiązania. Pozumiem że powinienem to zrobić tak:

bool GameFinished = false; //gdzieś w programie np. na początku.
while ( ! GameFinished) { //na początku maina
GameFinished = true; //w każdym pytaniu w przypadku gdy gracz udzieli błędnej odpowiedzi?

Nie działa :/

@TobiPL
Nie widziałeś absurdalnie długich switchy xD

1
  1. Nie używaj rand/srand: https://dsp.krzaq.cc/post/180/nie-uzywaj-rand-cxx-ma-random/
  2. O absurdalnym switchu inni już napisali.
  3. Wrzuć pytania do kontenera (np. std::vector), wymieszaj go za pomocą std::shuffle, a potem po prostu leć w tej kolejności. Łatwo, prosto, czytelnie.
0

Dobra wrzucam całe archiwum z "grafiką" + kod.
@kq obowiązuje tutaj jakiś skan pliku dla potwierdzenia że plik nie zawiera wirusa?
(za chwile wrzucę)

0

@watus1992r:
jeżeli twój main wygląda mniej więcej tak:

///pytanie 1 za 500
            statuspytania= 500;
            status500();
            wylosowano(losuj());
            system("cls");
            //kontynuuj();
///pytanie 2 za 1 000
            statuspytania= 1000;
            status1000();
            wylosowano(losuj());
            system("cls");
///pytanie 3 za 2 000
            statuspytania= 2000;
            status2000();
            wylosowano(losuj());
            system("cls");
///pytanie 4 za 4 000
            statuspytania= 4000;
            status4000();
            wylosowano(losuj());
            system("cls");
///pytanie 5 za 8 000
            statuspytania= 8000;
            status8000();
            wylosowano(losuj());
            system("cls");
/// ...

i wsadzisz to wszystko w While, to i tak While wykona się przynajmniej raz do samego końca. Chyba, że użyjesz break i wyjdziesz z pętli, ale jak tu mądrze skorzystać z tego brejka mając taki kod?

#include <iostream>

int main()
{
    bool GameFinished = false;
    while (!GameFinished)
    {
        std::cout << "Pierwsza jakas tam linijka\n";
        GameFinished = true;
        std::cout << "Druga jakas tam linijka. To tez sie wypisze!\n";
    }
}

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