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

Gra Turowa - Object C++

Object Storage Arubacloud
+2 głosów
1,733 wizyt
pytanie zadane 6 lipca 2015 w C i C++ przez tarnasm Gaduła (3,030 p.)

Hej,

Pisze grę turową w konsoli. Moim założeniem jest aby gracz był tworzony o wartościach domyślych i juz wiem, że tutaj z pomocą przychodzi mi konstruktor. Natomiast współczynniki przeciwnika (PC) chciałbym aby były generowane losowo aczkolwiek w pewnym zakresie. I tutaj nachodzą mnie dwa pytania. 

1. Czy jest inny sposób, niż wykorzystanie funkcji RAND w celu  wygenerowania losowo wartości dla atrybutów zawartych w klasie w momencie tworzenia obiektu?

2. Jak odejmować HP obiektu jednego od drugiego? (Zarówno gracz jak i NPC będą miały ten atrybut wspólnie jako własnie int HP). Pomyślałem przed momentem o funkcjach zaprzyjaźnionych. Ale jak to konceptualnie ogarnąć/wykorzystać to nie mam pojęcia. 

Pozdrawiam

3 odpowiedzi

+1 głos
odpowiedź 6 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
wybrane 8 lipca 2015 przez tarnasm
 
Najlepsza

Gracz i przeciwnik dziedziczą z innej klasy? (klasy głównej?)

 

Jeśli chodzi o problem "2" to nie lepiej funkcja publiczna o nazwie "Atakuj" która przyjmuje jeden albo 2 parametry?

Jeden parametr to damage a drugi adres przeciwnika/gracza (Tu przychodzi z pomocąKlasa virtualna)

Albo może gracz/przeciwnika będzie posiadał funkcję "atakuj(Typ_danych przeciwnika)" (tu też się przyda klasa virtualna która informuje że klasa inna zawiera funkcję "atakuj")

 

Na szybko napisany przykład:

#include <iostream>
#include <conio.h>

using namespace std;

bool en = false;

class loncznik
{
    public:
    virtual void Defense(loncznik * Odkogo,int damage);
    virtual void Atakuj(loncznik * przeciwnik);
};

class Gracz : public loncznik
{
    int hp;
    int damage;

    public:
    Gracz(int hps ,int damages): hp(hps) , damage(damages)
    {}
    void Atakuj(loncznik * przeciwnik)
    {
        przeciwnik->Defense(this,damage);
    }
    private:
    void Defense(loncznik * Odkogo, int damage)
    {
        cout << this << " Dostaje od " << Odkogo << " " << damage << "obrazen!" << endl;
        if(hp>damage)
            hp -= damage;
            else
            {
                cout << this << " umiera!";
                hp = 0;
            }
    }

};

class Bot : public loncznik
{
    int hp;
    int damage;
public:
    Bot(int hps ,int damages): hp(hps) , damage(damages)
    {}

    void Atakuj(loncznik * przeciwnik)
    {
        przeciwnik->Defense(this,damage);
    }
    private:
    void Defense(loncznik * Odkogo, int damage)
    {
        cout << this << " Dostaje od " << Odkogo << " " << damage << "obrazen!" << endl;
        if(hp>damage)
            hp -= damage;
            else
            {
                en = true;
                cout << this << " umiera!";
                hp = 0;
            }
    }
};


int main() {

    Gracz player(100,10);
    Bot bot(100,10);

    while(!en)
    {
        player.Atakuj(&bot);
        if(en) break;
        bot.Atakuj(&player);
    }


    return 0;
}

O wiele lepszym pomysłem jest zrobienie takie coś:

#include <iostream>
#include <conio.h>

using namespace std;

bool en = false;

class live
{
    int hp;
    int damage;

    public:
    live(int hps ,int damages) : hp(hps) , damage(damages)
    {}

    void Atakuj(live * przeciwnik)
    {
        przeciwnik->Defense(this,damage);
    }
   private:
    void Defense(live * Odkogo, int damage)
    {
        cout << this << " Dostaje od " << Odkogo << " " << damage << "obrazen!" << endl;
        if(hp>damage)
            hp -= damage;
            else
            {
                en = true;
                cout << this << " umiera!";
                hp = 0;
            }
    }
};

class Gracz : public live
{

    public:
    Gracz(int hps ,int damages): live(hps,damages)
    {}

};

class Bot : public live
{
public:
    Bot(int hps ,int damages): live(hps,damages)
    {}
};


int main() {

    Gracz player(100,10);
    Bot bot(100,10);

    while(!en)
    {
        player.Atakuj(&bot);
        if(en) break;
        bot.Atakuj(&player);
    }


    return 0;
}

 

komentarz 6 lipca 2015 przez tarnasm Gaduła (3,030 p.)
edycja 6 lipca 2015 przez tarnasm
Dziękuję bardzo, puki co. Muszę się przyjrzeć temu co napisałeś:) Będę kontynuował temat
komentarz 6 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
Ogólnie polecam ten drugi sposób z dziedziczeniem podstawowych informacji o walce. (zycie,tarcze damage, bronie, itd. itp.)

Ponieważ pisanie tego samego wiele razy jest bezsensu.

No chyba że piszesz trochę inaczej, i metody muszą niestety wyglądać inaczej.
komentarz 6 lipca 2015 przez tarnasm Gaduła (3,030 p.)
Dużo tłumaczy mi twój kod. Ale wiesz co? nie działa :D 1 wywala mi błędy w linkerze więc to chyba u mnie coś nie gra. A drugi się zapętla. Pozostawiłeś mi jakieś dydaktyczne pułapki :D?
komentarz 6 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
Nic nie podstawiłem.

Czyste dziedziczenie, klasy i tworzenie obiektów.

Możesz podać pełną treść błędu i środowisko programistyczne?

Może uda mi tobie pomóć.
komentarz 7 lipca 2015 przez tarnasm Gaduła (3,030 p.)

Bazowo korzystam z Visual Studio. Ale do prób użycia twoich lini kodu zastosowałem również Code Blocks

W przypadku apki nr 1:

CBLOCKS. : ERROR: main.cpp|8|undefined reference to `vtable for loncznik'|

VISUAL ST. : 

Error    1    error LNK2001: unresolved external symbol "public: virtual void __thiscall loncznik::Defense(class loncznik *,int)" (?Defense@loncznik@@UAEXPAV1@H@Z)   
Error    2    error LNK2001: unresolved external symbol "public: virtual void __thiscall loncznik::Atakuj(class loncznik *)" (?Atakuj@loncznik@@UAEXPAV1@@Z)   

W przypadku apki nr 2:

Program się kompiluje ale zapętla w nieskończoność. Zarzucam screen: 

Pozdrawiam:)

 

komentarz 7 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
W apki 2 zapomniałem dodać:

"en = true;" po else w "void Defense"

 

A w pierwszym spróbuj usuń "private" przed "void Defense"
komentarz 7 lipca 2015 przez tarnasm Gaduła (3,030 p.)

W apce drugiej napisałeś:

 public:

    live(int hps ,int damages) : hp(hps) , damage(damages)

    {}

Co to znaczy? Bo rozumiem mamy konstruktor live ale po dwukropku jakies dziedziczenie. Z kąd klasa podstawowa dziedziczy? Nie rozumiem tego zapisu, wyjasnij proszę.

 

komentarz 7 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
live(int zmiennaWprowadzana1 ,int ZmiennaWprowadzana2) : Zmienna_klasy_hp(zmiennaWprowadzana1 ) , Zmienna_obiektu_damage(ZmiennaWprowadzana2)

To to samo co:

live(int zmiennaWprowadzana1 ,int ZmiennaWprowadzana2)
{
Zmienna_klasy_hp = zmiennaWprowadzana1;
Zmienna_klasy_damage = ZmiennaWprowadzana2;
}

To jest takie szybsze wpisywanie zmiennych do obiektu przez konstruktor.

komentarz 7 lipca 2015 przez tarnasm Gaduła (3,030 p.)

yhymm:)

wybacz, że Cię tak wykorzystuję ale mógłbyś jeszcze mi tylko po krótce wyjaśnić co znaczy zapis player.Atakuj(&bot).  początek rozumiem, obiekt wywołuję metodę. Ale w nawiasie podałeś ampersand. On wskazuje na oryginał klasy bot? Jeżeli tak to w jakim celu użyłeś ogólnie tego argumentu?

komentarz 8 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
Ampersand przed obiektem zwraca adres obiektu i nie "kopiuje" całego obiektu dla funkcji. I dostajemy w formie wskaźnika. Ampersand nie wskazuje na klasę ale na obiekt.
+1 głos
odpowiedź 6 lipca 2015 przez Avernis Nałogowiec (27,400 p.)
Ja robiłem grę też turową: tu masz kod http://wklej.org/id/1751403/ I odejmowanie hp zrobiłem jako int atak, lub zaklecieA-C = (zależnie od ataku), a potem tylko był case 1, 2 itd, i jak się wciskało to odejmowało hp zależnie od liczby przypisanej do inta, może pomogłem może, nie xD, czekam na hejty
komentarz 6 lipca 2015 przez Dorion300 Szeryf (90,250 p.)
On pisze obiektowo.

Tu trochę inaczej się pisze....
+1 głos
odpowiedź 6 lipca 2015 przez Radfler VIP (101,030 p.)
Spróbuję pomóc :) 1. Tak, możesz wykorzystać nowe komponenty z C++11! http://en.cppreference.com/w/cpp/numeric/random Moja porada: wykorzystaj klasy mt19937 oraz uniform_int_distribution :) 2. Tu może mam ciekawy pomysł. Stwórz klasę Fighter oraz dziedziczące od niej klasy Player i NPC. W klasie Fighter zrób funkcję czysto wirtualną attack(). Będzie ona zwracała w postaci inta liczbę zadanych obrażeń. Dla tych obu klas pochodnych zrób różne implementacje tej funkcji. Dodaj też funkcję damage(int) (zwykła funkcja), która zada obrażenia danemu graczowi. Później zrób funkcję (nie składową) fight() z argumentami będącymi referencjami typu Fighter (polimorfizm!). Funkcja ta będzie przeprowadzać walkę w pętli w taki sposób: while(gracz.isAlive() && pc.isAlive()) { // sprawdzanie czy wszyscy żyją pc.damage(gracz.attack()); gracz.damage(pc.attack()); } Jak widać każdy gracz ma swoją turę (funkcja attack());
komentarz 6 lipca 2015 przez Radfler VIP (101,030 p.)
Do moderatora: niech ktoś ułoży ten tekst. Na telefonie nie ma takiej możliwości :(
komentarz 8 lipca 2015 przez tarnasm Gaduła (3,030 p.)

Dla tych obu klas pochodnych zrób różne implementacje tej funkcji. 

Co masz na mysli mówiąć różne implementacje? 

komentarz 8 lipca 2015 przez Radfler VIP (101,030 p.)
Skoro masz w klasie podstawowej (Fighter) metodę czysto wirtualną (bez ciała) to w klasie pochodniej musisz zrobić ich implementację :)
komentarz 8 lipca 2015 przez tarnasm Gaduła (3,030 p.)

Prosiłbym Cię o wyjaśnienie rozwiązania które zaprezentowałeś :) 

 W klasie Fighter zrób funkcję czysto wirtualną attack(). Będzie ona zwracała w postaci inta liczbę zadanych obrażeń

Dobrze, ale jeżeli zrobię czystą funkcję wirtualną to jak tego inta mam przesłać? W argumentach?

Dodaj też funkcję damage(int) (zwykła funkcja), która zada obrażenia danemu graczowi.

Miałbym ją zrobić poza klasą? Czy w klasie podstawowej 'Postac'?

Później zrób funkcję (nie składową) fight() z argumentami będącymi referencjami typu Fighter (polimorfizm!)

W funkcji głównej main();?

 

Podobne pytania

+1 głos
3 odpowiedzi 1,888 wizyt
+1 głos
2 odpowiedzi 177 wizyt
pytanie zadane 21 kwietnia 2015 w C i C++ przez Mjollnir951 Użytkownik (770 p.)
0 głosów
1 odpowiedź 161 wizyt
pytanie zadane 23 czerwca 2015 w C i C++ przez timati Bywalec (2,060 p.)

92,555 zapytań

141,402 odpowiedzi

319,540 komentarzy

61,938 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

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!

...