Symulator sportowy - powiązania klas Zawodnik i Mecz

0

Tworzę klasy Zwodnik i Mecz. Klasa zwodnik ma zdefinowaną zaprzyjaźnioną klasę Mecz albo zaprzyjaźnioną funkcję rozegraj z klasy Mecz (jeszcze nie zdecydowałem), żeby mógł gmerać w polach zawodnika.
Lepiej będzie tworzyć obiekt Mecz, który ma i wywołuje funkcję rozegraj z dwoma zawodnikami przekazanymi jako referencja, przekazać zawodników w konstruktorze i uruchomić tę funkcję od razu w konstruktorze klasy Mecz czy utworzyć globalną funkcję mecz, która ma przekazane jako referencję zawodników oraz mecz?

Na tę chwilę klasa Mecz ma w konstruktorze dwa obiekty klasy Zawodnik. Uruchamia funkcję rozegraj, ale ona rówież musi mieć przekazane dwa obiekty no i okazuje się, że z powodzeniem można przekazać inne obiekty niż były przekazane konstruktorze a to nie o to chodzi.

3

Na tę chwilę klasa Mecz ma w konstruktorze dwa obiekty klasy Zawodnik.

Dobrze

Uruchamia funkcję rozegraj, ale ona rówież musi mieć przekazane dwa obiekty no i okazuje się, że ...

Pora mysleć jako nie o "funkcji" a "metodzie", która działa na już posiadanych przez obiekt danych (więc bezargumentowa)

4

J.W. oraz żadnych zaprzyjaźnień, bo to co potrzeba do walki w klasie Mecz, powinno być zwyczajnie upublicznione do odczytu klasą Zawodnik, np.:

double getHelth()const { return ...; }
double getDamage()const { return ...; }
double getAvoid()const { return ...; }
0
ZrobieDobrze napisał(a):

Pora mysleć jako nie o "funkcji" a "metodzie", która działa na już posiadanych przez obiekt danych (więc bezargumentowa)

Tylko, że mamy błąd zakresu.

error: player1 was not declared in this scope 

Metody publiczne Zawodnik ma. Tylko dla jakiego obiektu metoda bezargumentowa z klasy Mecz ma je wywołać?

0

Tak wystarczy?

player.h

class Player
{
    public:
        Player();
        Player(string fn, string sn, int a, string nat);
        virtual ~Player();

        string Getfirstname() { return firstname; }
        string Getsecondname() { return secondname; }

        void Setfirstname(string val) { firstname = val; }
        void Setsecondname(string val) { secondname = val; }

    protected:

    private:
        string firstname;
        string secondname;
        int age;
        string nationality;
};

player.cpp
Player::Player(string fn, string sn, int a, string nat)
{
    firstname = fn;
    secondname = sn;
    age = a;
    nationality = nat;
}

game.h
class Player;

class Game
{
    public:
        Game (Player&,Player&);                // jako referencja
        virtual ~Game();

        void Play();             // nie ma znaczenia co ona robi, niech mu imię zmieni

    protected:

    private:
};

game.cpp

Game::Game(Player& player1, Player& player2)
{
    //

}


void Game::Play ()
{
    player1.Setfirstname("lll");     // nie da rady. Play() nie wie kto to 'player1' == błąd zakresu
}
0

Mam wysłać kompletny?

0

No dobra, masz konstruktor Game z prawidłowo listą parametrów ... tyle że nic z nimi nie robisz, nie ma dalszego ciagu.
Masz skopiowac do pól (których nie masz)

0

No nie, wyciąłem większość,żeby nie zaciemniała obrazu.

Game::Game(Player& player1, Player& player2)
{
    ResetPlayerPoints (player1);
    ResetPlayerPoints (player2);
    ResetPlayerGems (player1);
    ResetPlayerGems (player2);
    ResetPlayerSets (player1);
    ResetPlayerSets (player2);

    Play(player1,  player2);
}

Metody Reset i Play (pl1,pl2)... są zdefiniowane i taki konstruktor działa. Metoda Play (player1, player 2) rozgrywa jakiś tam mecz. Ale rozmawialiśmy na początku o bezargumentowej.

ps. bo równie dobrze mogę w main.cpp wywołać metodę PLay (pl1,pl2) dla innych obiektów niż te dwa przekazane przy tworzeniu obiektu i też zadziała.

0

Szukam w internetach i różnych książkach i jeszcze nigdzie nie znalazłem, żeby klasa która ma przekazane dwa obiekty innej klasy miała metodę bezargumentową, któa to metoda korzysta z tych obiektów. Wszędzie metoda ma w parametrach przekazne dwa obiekty.

I w ten sposób dotarłem do rozwiązania.

class Player
{
...
}

class Game 
{
  ...
  Game();
  void Play (Player&, Player&);
...
}

... i później po utworzeniu 2 obiektów klasy Player p1 i p2 i obiektu klasy Game g odpalamy g.Play(p1,p2).

1
Radziu napisał(a):

Szukam w internetach i różnych książkach i jeszcze nigdzie nie znalazłem, żeby

Przychodzi czas, ze kod należy napisać, a nie skopiować

Radziu napisał(a):

No nie, wyciąłem większość,żeby nie zaciemniała obrazu.

Game::Game(Player& player1, Player& player2)
{

...>

Play(player1,  player2);

}

Konstruktor nie powinien wykonywać akcji (to długa opowieść dlaczego)
Powinien konstruować. na przykład podane mu dwa argumenty zapamiętać w swoich polach

0
ZrobieDobrze napisał(a):
Radziu napisał(a):

Szukam w internetach i różnych książkach i jeszcze nigdzie nie znalazłem, żeby

Przychodzi czas, ze kod należy napisać, a nie skopiować

Radziu napisał(a):

No nie, wyciąłem większość,żeby nie zaciemniała obrazu.

Game::Game(Player& player1, Player& player2)
{

...>

Play(player1,  player2);

}

Konstruktor nie powinien wykonywać akcji (to długa opowieść dlaczego)
Powinien konstruować. na przykład podane mu dwa argumenty zapamiętać w swoich polach

  1. Sam piszę, tylko jak nie wiem jak coś prawidłowo zrobić to szukam

    1. wywaliłem już metodę z konstruktora. Jest domyślny i po prostu klasa Game() ma metodę Play(Player&,Player&) tak jak podałem w poście 4 po północy
0

Jest:

game.h

#include "Player.h"
class Player;

class Game
{
    public:
        Game();
        Game (Player&,Player&);
        virtual ~Game();

        void Play(Player&,Player&);
        void Play();

    protected:

    private:

        Player* p1;
        Player* p2;
};

Tu nie chce się zgodzić na obiekt Player zamiast wskaźnika. Robiłem coś takiego w uinnym projekcie, ale tam wszystkie klasy były w jednym pliku. Tu nibu jest #include i deklaracja zapowiadająca, ale i tak nie działa. Ale z drugiej strony ze wskaźnikiem i tak jest lepiej.

game.cpp
Game::Game(Player& player1, Player& player2)
{
    p1 = &player1;
    p2 = &player2;
}

void Game::Play ()
{
    p1->Setfirstname("lll");
    cout << endl << "XXX: " << p1->Getfirstname() << " XXX" << endl;
}

Niech mu dla sprawdzenia czy działa zmieni imię. Działa. Potem i tak metodę setfirstname wywalę, tylko konstruktor będzie nadawał imię, potem już nie ma zmieniania, bo USC się nie zgodził ;)

2
Radziu napisał(a):

Game::Game(Player& player1, Player& player2)
{
p1 = &player1;
p2 = &player2;
}

Po kiego przechodzisz na wskaźniki?
Czemu nie zrobić składowe referencjami?
Wskaźniki są po to aby mieć możliwość ustawić go na nullptr

2
_13th_Dragon napisał(a):
Radziu napisał(a):

Game::Game(Player& player1, Player& player2)
{
p1 = &player1;
p2 = &player2;
}

Po kiego przechodzisz na wskaźniki?
Czemu nie zrobić składowe referencjami?

a) znacząca nazwa
b) lepsze by było const referencja, ale @Radziu ja już naprawdę w tym mega wątku NIE ROZUMIEM co poeta miał na myśli, i czy const & czegoś nie przeszkadza.

Radziu napisał(a):

Jest:

void Game::Play ()
{
p1->Setfirstname("lll");
cout << endl << "XXX: " << p1->Getfirstname() << " XXX" << endl;
}


Niech mu dla sprawdzenia czy działa zmieni imię. Działa. Potem i tak metodę setfirstname wywalę, tylko konstruktor będzie nadawał imię, potem już nie ma zmieniania, bo USC się nie zgodził ;)

Za nic nie rozumiem tego zdania. Temu misiu.

Ja jestem przeciwnikiem drukowania wszędzie. Wyobraź sobie, ze to w jakiejś platformie webowej na chodzić ...
bardziej pro by było

struct/class Result ...

Result Game::Play ()

Albo inne podejście. O ILE metoda MUSI drukować (rzadko, ale tak bywa), ma w argumencie & ostream aby to nie był sztywny cout

void Game::Play (std::ostream & str)
{
   str << ... 
}
0
ZrobieDobrze napisał(a):
_13th_Dragon napisał(a):
Radziu napisał(a):

Game::Game(Player& player1, Player& player2)
{
p1 = &player1;
p2 = &player2;
}

Po kiego przechodzisz na wskaźniki?
Czemu nie zrobić składowe referencjami?

a) znacząca nazwa
b) lepsze by było const referencja, ale @Radziu ja już naprawdę w tym mega wątku NIE ROZUMIEM co poeta miał na myśli, i czy const & czegoś nie przeszkadza.

Znacząca nazwa ?
Będzie const refrencja.
Poeta miał na myśli - jak prawidłowo tworzyć powiązania klas ze sobą.

Radziu napisał(a):

Jest:

void Game::Play ()
{
p1->Setfirstname("lll");
cout << endl << "XXX: " << p1->Getfirstname() << " XXX" << endl;
}


Niech mu dla sprawdzenia czy działa zmieni imię. Działa. Potem i tak metodę setfirstname wywalę, tylko konstruktor będzie nadawał imię, potem już nie ma zmieniania, bo USC się nie zgodził ;)

Za nic nie rozumiem tego zdania. Temu misiu.

Dla sprawzdenia czy metada Play() widzi obiekty.

Ja jestem przeciwnikiem drukowania wszędzie. Wyobraź sobie, ze to w jakiejś platformie webowej na chodzić ...
bardziej pro by było

Ja tu się uczę a nie umieszczam w platformei webowej :) dla sprawdzenia czy działa daję cout. Przecież potem to wywalę.

0

Dobra weszło jak referencja. rzeczywiście o listę inicjalizacyjną chodziło.

game.h

#include "Player.h"
class Player;

class Game
{
    public:
        Game (Player&,Player&);
        virtual ~Game();

        void Play(Player&,Player&);
        void Play();

    protected:

    private:

        Player& p1;
        Player& p2;
};


game.cpp
Game::Game(Player& player1, Player& player2)
:p1(player1),p2(player2)
{
  
}

void Game::Play ()
{
    p1.Setcurrent_points("158");
}
0

Powiedz mi czemu robisz jakieś Setcurrent_points oni mają walczyć nie zmieniać swoich charakterystyk, czy coś mnie ominęło?

0
_13th_Dragon napisał(a):

Powiedz mi czemu robisz jakieś Setcurrent_points oni mają walczyć nie zmieniać swoich charakterystyk, czy coś mnie ominęło?

Coś Cię ominęło :)
Właśnie teraz po namyśle doszedłem do wniosku, że const referencja nie będzie, bo oni grają mecz. W tej chwili mam wersję, że w tenisa (ale kij z tym, równie dobrze mogą zagrać w pici polo). No i dlatego metoda Game::Play() musi zmieniac ich statystyki, że np. gracz zdobył punkt.

0

Ogólnie to dziękuję koledzy za pomoc.

0
Radziu napisał(a):

No i dlatego metoda Game::Play() musi zmieniac ich statystyki, że np. gracz zdobył punkt.

Jak ty grasz np w tenisa i zdobywasz jakiś punkt to ktoś ci ten punkt gdzieś wsadza żeby stał się częścią ciebie?
Czemu punkty zdobyty graczem są częścią gracza?

0
_13th_Dragon napisał(a):
Radziu napisał(a):

No i dlatego metoda Game::Play() musi zmieniac ich statystyki, że np. gracz zdobył punkt.

Jak ty grasz np w tenisa i zdobywasz jakiś punkt to ktoś ci ten punkt gdzieś wsadza żeby stał się częścią ciebie?
Czemu punkty zdobyty graczem są częścią gracza?

No niby nie. Choć z drugiej strony oprócz statystyk mamy też umiejęstności. Ja grywam w piłę i to, że umiem trafić z woleja piłkę lecącą na wysokości biodra, tak żeby poleciała w bramkę a nie w kosmos to już jest częsćią mnie.
Ja w tej chwili robię tak, że wszelkie statystyki i skile gracza są polami obiektu Zawodnik. Na lepsze rozwiązania jeszcze przyjdzie czas. Co proponujesz? Osobną klasę/strukturę na skile i statystyki i klasa Zawodnik ma mieć z nią powiązanie? No, ale jeden zawodnik nie może mieć dostępu do skili i statystyk drugiego.

0

Owszem, ta twoja umiejętność należy do ciebie ale ona musi być tylko do odczytu.
Owszem możesz tą umiejętność z czasem zwiększyć ale z całą pewnością nie podczas meczu.
Mecz musi mieć aktualny stan walki (ewentualnie dodatkowo cały przebieg - nagranie), zaś ze wszystkich statystyk gracza musi korzystać pasywnie - tylko do odczytu.

0
Radziu napisał(a):
_13th_Dragon napisał(a):
Radziu napisał(a):

No i dlatego metoda Game::Play() musi zmieniac ich statystyki, że np. gracz zdobył punkt.

Jak ty grasz np w tenisa i zdobywasz jakiś punkt to ktoś ci ten punkt gdzieś wsadza żeby stał się częścią ciebie?
Czemu punkty zdobyty graczem są częścią gracza?

No niby nie. Choć z drugiej strony oprócz statystyk mamy też umiejęstności. Ja grywam w piłę i to, że umiem trafić ...

No właśnie.

MASZ UMIEJĘTNOŚCI, ale nie jesteś umiejętnosciami.
Zawodnik MA STATYSTYKĘ z nie JEST STATYSTYKĄ. Pies MA łapy, ale nie jest łapami.

(ja bym to na wiele sposobów rozwiązywał, np jakieś agregaty ze zbioru Result'ów, pewnie ograniczone w czasie, bo jak 10 lat temu byłeś dobry, to kwiaty na kółku emerytów, ale nie ma znaczenia w praktyce)

0

No dobra, to będą agregaty z bieżącymi statystykami zawodnioka w czasie meczu, czyli pies ma łapy.Ale jeden raz na zakończenie meczu (albo już po nim?) trzeba w tych agregatach zawodnika podbić, np. liczbę rozegranych spotkań, liczbę zwycięstw/porażek itp. Myslę tez o jakims kontenerze z archiwalnymi wynikami gracza.

1

Dobra myśl, Mecz dodaje dane do kontenera z archiwalnymi wynikami więc statystykę podbijasz tam.

#include <iostream>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

class Sportsmen
{
	private:
	string name;
	double strength;
	double health;
	//...
	public:
	Sportsmen(const string &name,double strength):name(name),strength(strength) {}
	const string &getName()const { return name; }
	double getStrength()const { return strength; }
	double getHealth()const { return health; }
	//...
	bool operator<(const Sportsmen &s)const { return name<s.name; }
};

class SportsmenFight
{
	private:
	const Sportsmen &sportsmen;
	double health;
	public:
	SportsmenFight(const Sportsmen &sportsmen):sportsmen(sportsmen)
	{
		health=sportsmen.getHealth();
	}
	const Sportsmen &getSportsmen()const { return sportsmen; }
};

class Result
{
	public:
	enum State { Win=1,Draw=0,Loose=-1 };
	private:
	State state;
	const Sportsmen &who,&opp;
	public:
	Result(const Sportsmen &who,const Sportsmen &opp,State state):who(who),opp(opp),state(state) {}
};

class Statistics
{
	private:
	multimap<Sportsmen,Result> map;
	public:
	void insert(const Sportsmen &s,const Result &r)
	{
		map.insert(make_pair(s,r));
	}
};

class System
{
	public:
	Statistics statistics;
	vector<Sportsmen> sportsmens;	
	void match(size_t sa,size_t sb)
	{
		SportsmenFight a(sportsmens[sa]);
		SportsmenFight b(sportsmens[sb]);
		Result::State state=Result::Draw;
		bool done=false;
		while(!done)
		{
			//...
			done=true;
			statistics.insert(a.getSportsmen(),Result{a.getSportsmen(),b.getSportsmen(),(Result::State)+state});
			statistics.insert(b.getSportsmen(),Result{b.getSportsmen(),a.getSportsmen(),(Result::State)-state});
		}
	}
};

int main()
{
	return 0;
}

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