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

Niepoprawne działanie typu wyliczeniowego enum .

0 głosów
172 wizyt
pytanie zadane 31 października 2016 w C i C++ przez PaulW Początkujący (470 p.)
edycja 31 października 2016 przez PaulW
class Gra
{
public:
    Gra();
    enum opcje{MENU , GRA , USTAWIENIA , KONIEC};
    void uruchomGre();
    opcje stangry;
    void menu();
    void ustaw(); void ustaw1(); void ustaw2(); void ustaw3();
private:
    int wybranaopcja = 0;
    char znak;
 
 
};
#endif // gra_h

 

Tutaj zastosowałem dziedziczenie w celu uzyskania dostępu do zmiennej "stangry" typu "opcje" zadeklarowanej w klasie "Gra".

#ifndef menedzer_h
#define menedzer_h
#include <iostream>
#include "paletka.h"
#include "pilka.h"
#include "gra.h"
 
using namespace std;
 
class Menedzer:public Gra
{
public:
    Menedzer(int s , int w); // konstruktor dwuparametrowy
    ~Menedzer(); // destruktor
    void wynikUp(Paletka *gracz); // funkcja składowa klasy której parametrem jest wskaźnik na obiekt klasy Paletka
    void rysuj(); // deklaracja funkcji "rysuj"
    void wejscie(); // -//-
    void start(); // -//-
    void kolizje(); // -//-
private:
    int wysokosc , szerokosc; // zmienne określające wysokość i szerokość pola gry
    int wynik1 , wynik2; // zmienne typu int , przechowują wynik gracza I i II
    char gora1 , dol1 , gora2 , dol2; // zmienne typu char , odpowiadają za sterowanie graczami ( orzypisanie klawiszu klawiatury)
    bool koniec; // warunek sprawdzający
    Pilka *pilka; // nowy obiekt klasy Pilka tworzony dynamicznie
    Paletka *gracz1; // -//-
    Paletka *gracz2; // -//-
    void wynikReset(); // funkcja zerująca wynik meczu
    void pilkaStop();
 
};
 
#endif // menedzer_h

W konstruktorze , początkowy "stangry" ustawiam na "MENU"

void Gra::menu()
{
        while( wybranaopcja != 3 ) // jeżeli zmienna "wybranaopcja" jest różna od 3 (menu posiada tylko 3 opcje)
        {
        ustaw1();
        if( wybranaopcja == 0 ) cout << "-->Graj\n";         // opcje menu
        else cout << "Graj    \n";

        ustaw2();
        if( wybranaopcja == 1 ) cout << "-->Ustawienia\n";   // pokazuje się "-->"
        else cout << "Ustawienia    \n";

        ustaw3();
        if( wybranaopcja == 2 ) cout << "-->Wyjdz\n";        // -//-
        else cout << "Wyjdz    \n";

        znak = getch(); // odczytuje kod wciśniętego klawisza klawiatury i przechowuje go w zmiennej "znak"

        switch( znak )
        {
        case 72:                // jeżeli wciśniemy strzałkę w górę "kod ASCII = 72"
            wybranaopcja--;     // opcja menu zmniejsza się
            break;
        case 80:
            wybranaopcja++;    // jeżeli wciśniemy strzałkę w dół "kod ASCII = 80"
            break;             // opcja menu zwiększa się
        }

        if(wybranaopcja > 2 ) wybranaopcja--; // jeżeli wybrana opcja jest > 2 to zmniejsz wartość zmiennej "wybranaopcja"
        if(wybranaopcja < 0) wybranaopcja++; // jeżeli wybrana opcja jest < 0 to zwiększ wartość zmiennej "wybranaopcja"

        if(wybranaopcja == 0 && znak == 13) // jeżeli opcja == 0 ( Graj ) i wciśniemy klawisz "Enter"
        {
            stangry = GRA; // stan gry zostaje ustawiony na "GRA"
            cout << stangry;
            break;
        }

        if(wybranaopcja == 1 && znak == 13) // jeżeli opcja == 1 ( Ustawienia) i wciśniemy klawisz "Enter"
        {
            stangry = USTAWIENIA; // stan gry zostaje ustawiony na "USTAWIENIA"
            break;
        }

        if(wybranaopcja == 2 && znak == 13) // jeżeli opcja == 2 ( Koniec ) i wciśniemy klawisz "Enter"
        {
            stangry = KONIEC; // stan gry zostaje ustawiony na "KONIEC"
            cout << stangry;
            break;

        }
        }
}

Chciałem zrobić coś takiego , że w zależności od stanu wykona się dana rzecz. Wszystko działa jak należy tylko w pierwszym obiegu , później występują problemy

ważniejszy fragment menedzer.cpp
 
 void Menedzer::wejscie()
    {
        if(klawisz == 112) // P - Pauza
        {
           menu(); // chciałem tutaj zrobić tak while(stangry == GRA)
                                                {
                                                 stangry = MENU;
                                                 break;
                                                }
        }
    }

Wygląda to tak :

Stan gry ustawiony na "MENU" , zostaje uruchomiona funkcja "menu()"  , która tworzy menu . 

Po kliknięciu "enter" stan gry zostaje ustawiony na "GRA" czyli jak wynika z metody uruchomGre() :

case GRA:
            {
             Menedzer m1(40 , 20);
             m1.start();
            } break;

W skrócie klasa Menedzer odpowiada za całą grę . Natomiast metoda start() :

 void Menedzer::start()
    {

            while(stangry != KONIEC)
            {
            rysuj();   // rysuje boisko , graczy ( 2 paletki) i piłkę itd.
            wejscie(); // "wprawia w ruch" graczy , piłkę, obługuje opcje gry itp.
            kolizje(); // odpowiada za kolizje w grze
            }
    }

Wracając do ostatniego obrazka , po powrocie do menu (kliknięciu klawisza"p") oraz ponownym naciśnięciu klawisza enter  na opcji "Graj" piłka kontynuuje ruch co ważne w dobrym kierunku . ( Poprzednio po zatrzymaniu obierała losowy kierunek nadany w metodzie "losowyKierunek":

 void Pilka::losowyKierunek()
    {
        kierunek = (stan)((rand() % 6) + 1); // przypisanie losowego kierunku zmiennej "kierunek"
    }

Także do tego momentu jest ok . Działa to za każdym razem po kliknięciu literki "p" . Niestety nie działa jak należy opcja "Wyjdź " po drugim bądź kolejnym powrocie do menu. 


 

 

1 odpowiedź

0 głosów
odpowiedź 31 października 2016 przez siof Gaduła (3,560 p.)

Jeśli dobrze rozumiem ideę po tym co przedstawiłeś to:

  • Funkcja uruchomGre uruchamiana jest tylko raz na poczatku uruchomienia programu (zakłądam tak ponieważ po wyborze 'Gra' startowany jest manager który najprawdopodobniej blokuje dalsze wywoływanie funkcji do czasu zakończenia gry)
  • funkcja Menedzer::start blokuje watek do czasu zakonczenia gry

Jeśli powyższe jest prawdziwe to najprawdopodobniej włąśnie dlatego nie działa Ci menu. Z wewnątrz funkcji Menedzer::wejscie mozesz wejsc do menu i zmodyfikowac stan gry ale nigdzie tu nie widzę obsługi nowego stanu (obsługa w tym co przedstawiłeś jest jedynie w funkcji uruchomGre która nie jest wykonywana po wystartowaniu gry).  Aby Ci program obsługiwał stany gry musiałbyś dodać obsługę jego sprawdzania gdzieś w głównej pętli gry (najprawdopodobniej na jej poczatku lub końcu ale to już sam zdecydujesz ;) ).

Jeśli jednak źle zrozumiałem działanie to rozwiń proszę jego opis

komentarz 31 października 2016 przez PaulW Początkujący (470 p.)

Dobrze myślisz :

#include <iostream>       // biblioteka wejscia / wyjscia
#include "pilka.h"        // dyrektywa #include załącza plik nagłówkowy "pilka.h"
#include "paletka.h"      // dyrektywa #include załącza plik nagłówkowy "paletka.h"
#include "menedzer.h"     // dyrektywa #include załącza plik nagłówkowy "menedzer.h"
#include "gra.h"       // dyrektywa #include załącza plik nagłówkowy "gra.h"
using namespace std;      // użycie przestrzeni nazw "std"

int main()
{

    Gra g1;
    g1.uruchomGre();
    return 0;
}

Myślałem ,że jak zrobię tak :

if(klawisz == 112) // P - Pauza
        {
            while(stangry == GRA)
            {
                stangry = MENU;
                break;
            }
        }

to wróci mi tak jakby do metody "uruchomGre" i wykona się case MENU , który wywołuje funkcje rysującą menu. Może trochę inaczej  , nie chcę w tym miejscu:

if(klawisz == 112) // P - Pauza
        {
        
        }

robić tak :

if(klawisz == 112) // P - Pauza
        {
            menu();
        }

tylko tak :

if(klawisz == 112) // P - Pauza
        {
            while(stangry == GRA)
            {
                stangry = MENU;
                break;
            }
        }

Chciałbym działanie mojej gry oprzeć na stanach

komentarz 31 października 2016 przez siof Gaduła (3,560 p.)
            while(stangry == GRA)
            {
                stangry = MENU;
                break;
            }

Tutaj chyba miał być if. Po co wsadzać niepotrzebnie while skoro i tak maksymalnie 1 raz się to wykona.

Co do stanów to najłatwiej by Ci było chyba dodać sprawdzanie stanów i odpalanie odpowiednich funkcji w metodęStart.

Niżej daje pseudokod ala cpp prezentującą przykład takiego podejścia:

while (stanGry != KONIEC)
{
    switch (stanGry)
    {
        case GRA:
            rysowanie();
            i();
            inneCuda();
            break;

        case MENU:
            menu();
            break;

        case KONIEC:
            break;
    }
}

 

Podobne pytania

0 głosów
1 odpowiedź 1,306 wizyt
pytanie zadane 27 kwietnia 2016 w C i C++ przez lukasz_m Obywatel (1,380 p.)
0 głosów
1 odpowiedź 363 wizyt
pytanie zadane 28 października 2016 w C i C++ przez PaulW Początkujący (470 p.)
0 głosów
4 odpowiedzi 312 wizyt

93,424 zapytań

142,421 odpowiedzi

322,643 komentarzy

62,782 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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...