Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C++]gra - prosty labirynt w wierszu polecenia

Gaatt 28 Cze 2011 23:35 5516 21
  • #1 28 Cze 2011 23:35
    Gaatt
    Poziom 10  

    Witam! Chciałbym napisać prosty program w wierszu polecenia. Będę go pisał w C++ z użyciem klas i obiektów (To mój pierwszy program tą metodą więc proszę o wyrozumiałość.). Będzie to labirynt. Na razie jednak sądzę, że mój poziom wiedzy nie jest wystarczający, dlatego apeluję o pomoc. Zacznijmy od początku. Gracz, aby wygrać, musi się przemieścić ze swojego pola do mety. Ma to wyglądać na przykład tak:
    
    88888
    8G0M8
    88888

    8-pole ze ścianą
    G-pole z graczem
    M-pole z metą
    0-pole bez gracza

    Domyślam się, że pola muszą być w enum, a plansza to tablica dwuwymiarowa, jednak jak napisać choćby prototypy klas nie mam pojęcia. Proszę o pomoc, a za każde wsparcie z góry dziękuję. Nie chcę gotowego programu, lecz wskazówki i porady.

    Dodano po 3 [godziny] 24 [minuty]:

    Coś skleciłem. Prawdopodobnie jest to bez sensu, ale jednak to zamieszczę. Proszę o porady jak to dalej rozwinąć. Nie jestem również pewny użytych specyfikatorów.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0 21
  • #2 29 Cze 2011 09:33
    chudybyk
    Poziom 27  

    Witam!
    Po co Ci tyle klas? Moim zdaniem wystarczyłaby jedna klasa Plansza i dobrze zorganizowany zespół zmiennych i metod.
    Na początek - tak jak pisałeś, ale nie zdefiniowałeś - pomyśl nad tablicą dwuwymiarową.
    Pozdrawiam!

    0
  • #3 29 Cze 2011 10:29
    Gaatt
    Poziom 10  

    Coś w tym stylu?

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #4 29 Cze 2011 10:49
    chudybyk
    Poziom 27  

    Mniej więcej.
    Rusz trochę wyobraźnię. Jak zrobiłbyś to na tekturowej planszy?
    1. Plansza jest stała i to twoja tablica dwuwymiarowa. Również niezmienna aż do kolejnego poziomu/etapu. Nie definiowałbym typu P_GRACZ dla tablicy, bo gracz będzie się przesuwał "po" planszy. Wystarczy w klasie trzymać współrzędne gracza i je zmieniać.
    2. Proces gry polega na przesuwaniu gracza, więc trzeba zaimplementować metody przesuwające gracza. Albo cztery dla każdego z kierunków, albo jedną z argumentem kierunku
    3. Odświeżanie ekranu gry - przepisywanie planszy z pamięci na ekran - nasuwa się kolejna metoda. Można ją wywoływać po każdym ruchu.
    4. Sprawdzenie czy gracz jest na polu META i ewentualne fanfary - oczywiście znowu metoda klasy.

    No i zrobiłem Ci projekt. ;-)

    0
  • #5 29 Cze 2011 12:59
    Gaatt
    Poziom 10  

    Jak napisać jedną klasę Plansza i dobrze zorganizowany zespół zmiennych i metod. Kolejny problem: Nie mogę zaimplementować klasy.

    To jest plik class.h:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    To jest plik main.cpp
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #6 29 Cze 2011 14:15
    chudybyk
    Poziom 27  

    Myślę, że powinieneś bardziej się skupić na algorytmie i sposobie użycia zmiennych niż na formalnej stronie C++. Może spróbuj to zrobić najpierw w języku C, a potem dopiero przerobić na C++?

    Ja bym próbował takiej konstrukcji:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Prościej wytłumaczyć się nie da.
    Powodzenia!

    0
  • #7 30 Cze 2011 10:11
    Gaatt
    Poziom 10  

    Coś udało mi się zaprogramować, jednak kompilator wyrzuca kilka błędów. Uprzejmie proszę o ich usunięcie (Pliki są w załączniku).Nie jestem także pewny działania programu. Prosiłbym, aby wszystkie zmiany zapisywał Pan w //. Dziękuję za dotychczasową pomoc.

    0
  • #8 30 Cze 2011 11:44
    chudybyk
    Poziom 27  

    O Jezusie w niebiesiech! Ty widzisz i nie grzmisz! ;-)
    Nie robisz błędów, tylko tworzysz poezję. Programowanie to nie szuka a rzemiosło. Trzeba przemyśleć każde słowo i wiedzieć po co się je wstawia.
    Może porywasz się na projekt, który Cie przerasta? Mogę wręcz napisać program za Ciebie, ale chyba nie o to chodzi. Spróbuj napisać kilka prostszych programów - polegających na odczytywaniu i wypisywaniu znaków, na wypisywaniu tablicy, na przesuwaniu kursora (np, generator liczb do totolotka). Potem sam zrozumiesz gdzie robisz błędy. Radzę też odpuścić sobie chwilowo klasy. Pisz wszystko w funkcji main(), aż zaczniesz mieć potrzebę używania bardziej skomplikowanych konstrukcji.
    Kilka luźnych uwag:
    1. Nie używaj polskich znaków w kodzie - nawet w komentarzach ich unikaj. Kompilatory ich nie trawią.
    2. Komentuj każdą zmienną. Po co, w jakim celu jej używasz a nawet jakie może mieć wartości
    3. Zacznij program od czegoś co już działa, nawet od przysłowiowego "hello world" i go powolutku rozbuduj sprawdzając działanie po każdym kawałku.
    4. Myśl tak jak program. Kombinuj co po kolei będzie się działo, jak się będą zmieniać wartości zmiennych i po co.
    Powodzenia!

    0
  • #9 30 Cze 2011 13:01
    Gaatt
    Poziom 10  

    To jeszcze jedno pytanie: o co chodzi z CLabirynt i jak mam to zmienić, aby nie było błędu.

    0
  • #10 30 Cze 2011 13:50
    chudybyk
    Poziom 27  

    Klasa CLabirynt miała opisywać planszę gry (plansz mogłoby być więcej), ponieważ uważam, że nie ma sensu tworzyć więcej niż jednej klasy dla tak prostego programu. Klasy są między innymi po to by grupować logicznie powiązane zmienne i funkcje oraz zapewniać pewne mechanizmy dostępu. (enkapsulacja).
    Błędów w twoim programie jest tyle, że niektórych nie potrafię nazwać. Uważam, że powinieneś program napisać od nowa. Eliminując jeden błąd zaraz będzie następny. Gdyby naprawić wszystkie błędy tak, by doprowadzić do poprawnej kompilacji, to program urośnie dwa razy.
    Zadeklaruj wszystkie potrzebne zmienne i funkcje globalnie. Stwórz funkcje, które będziesz potrzebował. Zapomnij na razie o klasach.

    0
  • #11 01 Lip 2011 13:13
    Gaatt
    Poziom 10  

    Jeżeli mam błąd "redefinition", to o co chodzi i jam mam to naprawić?

    0
  • #12 01 Lip 2011 13:41
    chudybyk
    Poziom 27  

    Spróbuj komunikaty o błędach tłumaczyć sobie słownikiem książkowym lub internetowym.
    "redefinition" oznacza powtórną definicję jakiegoś wyrażenia. Trudno zgadnąć jakiego, bo nie napisałeś całego komunikatu. Być może dyrektywa #include "class.h" powoduje, że kilka razy redefiniujesz te same wyrażenia. Zwykle w plikach nagłówkowych *.h stosuje się konstrukcje #ifndef <token> i wtedy można go dołączać wielokrotnie.
    Wprowadzasz sobie chaos z którego nie potrafisz wyjść. Czy próbowałeś korzystać z jakiś podręczników do C lub C++?

    0
  • #13 01 Lip 2011 17:08
    Gaatt
    Poziom 10  

    Tłumaczę sobie. Podana przez Pana konstrukcja nic nie dawała (wręcz odwrotnie), jednak tego typu błędy dziwnym trafem znikły. Teraz do tej samej zmiennej (g_KierunekRuchu) są dwa błędy: "function does not take 1 arguments", "too many arguments in function call".

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Dodano po 1 [minuty]:

    Co mam zmienić, aby wszystko było poprawnie?

    0
  • Pomocny post
    #14 01 Lip 2011 18:06
    chudybyk
    Poziom 27  

    Gaatt napisał:
    Tłumaczę sobie. Podana przez Pana konstrukcja nic nie dawała (wręcz odwrotnie), jednak tego typu błędy dziwnym trafem znikły.

    Jaka konstrukcja? Dyrektywa #ifndef? Próbowałeś doczytać jak i po co się ją stosuje? Nic się nie dzieje "dziwnym trafem".
    Cytat:
    Teraz do tej samej zmiennej (g_KierunekRuchu) są dwa błędy: "function does not take 1 arguments", "too many arguments in function call".

    To tylko wierzchołek góry lodowej Twoich błędów.
    Cytat:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    dlaczego extern? Masz w jakimś innym pliku zadeklarowaną tę zmienną? Po co Ci ta zmienna w ogóle?
    Cytat:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Komunikat błędu wskazuje, że funkcja Ruch() nie powinna mieć argumentów. Popatrz dokładnie jak ją zdefiniowałeś. Dlaczego jako argument funkcji przekazujesz wyrażenie przypisania? Czy na pewno wiesz co robisz - takie konstrukcje są czasem wykorzystywane jako kruczki języka C, ale najczęściej są skutkiem błędów. Po co w ogóle używasz tu zmiennej g_KierunekRuchu?
    Cytat:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Po co Ci kolejne wywołanie funkcji Ruch()?
    Cytat:
    Co mam zmienić, aby wszystko było poprawnie?

    Aby wszystko było poprawne należy zmienić podejście. Najpierw poczytaj coś o języku, którego chcesz używać, a potem sprawdzaj czy wszystko działa tak jak zrozumiałeś.
    Nie mam zamiaru uczyć Cię podstaw języka, zasad i filozofii pisania programów a w szczególności poprawiać Twoich trywialnych błędów, które wynikają pewnie ze wstrętu do czytania podręczników. Nie nauczysz się tego poprzez to forum, bo to wymaga zaangażowania a nie tylko usunięcia kilku, kilkuset, a może kilku tysięcy błędów w Twoim programie.
    Polecam odwiedzić księgarnię.

    0
  • #15 01 Lip 2011 18:39
    Gaatt
    Poziom 10  

    Czytam i uczę się z popularnego e-booka "Od zera do gier kodera".

    Dodano po 12 [minuty]:

    I teraz tak myślę ,że mnie przekonałeś. Wrócę do tematu kiedy zgromadzę odpowiednią wiedzę wiedzę.

    0
  • #16 07 Lip 2011 10:34
    Gaatt
    Poziom 10  

    Zacząłem pisać program po raz kolejny. Wydaje mi się, że teraz jest w porządku (na pewno było w porządku, kiedy jeszcze się kompilowało).Program jest jeszcze bardziej uproszczony: nie ma ścian, mety, plansza jest jednowymiarowa. Wystąpił podczas kompilacji, gdy jednym z parametrów funkcji była tablica.Błąd: unresolved external symbol "void __cdecl WyświetlPlansze(int,int)" (?WyświetlPlansze@@YAXHH@Z) referenced in function _main. Zupełnie nie rozumiem o co chodzi kompilatorowi mimo przetłumaczenia tekstu. Domyślam się, że może w jakiś sposób należy wykorzystać wskaźniki, jednak jeszcze się o nich nie uczyłem. Proszę o pomoc. Pliki są w załączniku.

    0
  • #17 07 Lip 2011 11:36
    chudybyk
    Poziom 27  

    Kompilator nie znalazł funkcji void WyświetlPlansze(int, int), bo nie była zdefiniowana. Jest tylko prototyp tej funkcji w pliku ruch.h.
    Zdefiniowałeś funkcję o tej nazwie void WyświetlPlansze(int gracz_X, int Pole[2]) - ale ta funkcja nie jest tą zadeklarowaną - to jej przeciążona "siostra" - zamiast dwóch argumentów typu int przyjmuje int i tablicę. Tablice są traktowane w C i C++ jak wskaźniki, więc nawet, jeśli kompilator przyjmie taką konstrukcję, to spodziewa się tam wskaźnika. Poczytaj o funkcjach przeciążonych, wskaźnikach i tablicach.
    W języku C argumenty są przekazywane tylko i wyłącznie przez wartość. To oznacza, że bezpośrednio można przekazać do funkcji tylko wartości typów prostych (podstawowych) a inne muszą być przekazywane pośrednio, czyli przez wskaźniki. Nie da się przekazać wieloelementowej tablicy, która jest typem złożonym, lepiej jest od razu zadeklarować wskaźnik. Np. tak:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Teraz można wywołać tę funkcję jako
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Pamiętaj, że tutaj zmienna Pole jest tablicą i jest traktowana jak wskaźnik. Oczywiście należy pamiętać, żeby w funkcji nie przekroczyć zakresu tablicy.
    Jeśli jesteś formalistą, możesz spróbować użyć deklaracji:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Ta deklaracja jest bardziej skomplikowana, ale również powinna zadziałać. zmienna "tab" jest tutaj wskaźnikiem na tablicę dwuelementową zmiennych typu int.
    Pozwolisz, że nie będę się wgłębiał w logiczną stronę programu, który jest w wersji rozwojowej.
    Pozdrawiam!

    0
  • #18 07 Lip 2011 20:46
    Gaatt
    Poziom 10  

    Czy należy coś, w związku z tymi konstrukcjami jeszcze dopisać?
    Czy próbował to Pan kompilować? (u mnie oba sposoby nie działają)
    Czy można jakoś obejść użycie wskaźników? (jeszcze się o nich nie uczyłem)

    0
  • #19 08 Lip 2011 00:06
    chudybyk
    Poziom 27  

    Gaatt napisał:
    Czy należy coś, w związku z tymi konstrukcjami jeszcze dopisać?

    Podpowiedziałem Ci prawdopodobne rozwiązanie Twojego problemu z kompilacją. Nie zamierzam się wgłębiać w resztę Twojego programu, bo nie rozumiem Twojego toku myślenia.
    Cytat:
    Czy próbował to Pan kompilować? (u mnie oba sposoby nie działają)

    Nie próbowałem tego kompilować. I bez tego wiem, że będą błędy, a o działaniu nie ma mowy. Powtórzę co już pisałem - nie używaj polskich znaków w kodzie. Nazwa funkcji WyświetlPlansze zawiera "ś" - samo to jest powodem, dla którego kompilacja się nie powiedzie. Innych przyczyn mogę mnożyć.
    Cytat:
    Czy można jakoś obejść użycie wskaźników? (jeszcze się o nich nie uczyłem)

    Niewiele można zrobić w C i C++ pisząc programy bez znajomości wskaźników. To naprawdę fundamenty tego języka.

    0
  • #20 09 Lip 2011 21:35
    Gaatt
    Poziom 10  

    Wszystko umieściłem w funkcji main(), aby uniknąć tablicy jako parametru funkcji i działało poprawnie, jednak jak później dostrzegłem kod był nieco skomplikowany. Teraz już napisałem cały listing programu. Oto on:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Mam kilka pytań:
    1) Pytanie jest w zamieszczonym listingu.
    2) W jaki sposób mam zmienić kod, aby nie potrzebował potwierdzenia ruchu enter'em?
    3) Co zrobić, aby sterowanie było na strzałki?
    Proszę o udzielenie odpowiedzi na zadane pytania.

    0
  • #21 11 Lip 2011 22:57
    Gaatt
    Poziom 10  

    Na pytanie 1 sam znalazłem odpowiedź.
    Teraz listing wygląda następująco:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Pozostały dwa pytania:
    2) W jaki sposób mam zmienić kod, aby nie potrzebował potwierdzenia ruchu enter'em?
    3) Co zrobić, aby sterowanie było na strzałki?

    Chyba nie tylko chudybyk (któremu bardzo dziękuję za pomoc w pisaniu kodu) przegląda ten temat i zna odpowiedź na te pytania. Myślę ,że są także inni dobrzy programiści, których proszę o włączenie się do dyskusji. Jak widzicie ja też myślę, a nie tylko czekam na odpowiedź, jednak są takie problemy, z którymi sam sobie nie poradzę. Do ich rozwiązania potrzebuję Was! Proszę o pomoc.

    0
  • #22 12 Lip 2011 22:41
    Gaatt
    Poziom 10  

    Sam poradziłem sobie już ze wszystkim. I jeszcze jedno pytanie: Jak zlikwidować migotanie okna konsoli po odświeżeniu?

    0