Finished Monopoly.txt.

This commit is contained in:
Relintai 2021-03-29 15:41:51 +02:00
parent 4d8ad3bb2e
commit 53cb378bfb
2 changed files with 505 additions and 173 deletions

View File

@ -1,201 +1,533 @@
Írni fogunk egy leegyszerűsített monopoly szerűséget. Írni fogunk egy leegyszerűsített monopoly szerűséget.
Ha a vektorod remove() függvénye nem tartja meg a sorrendet, akkor adj hozzá egy remove_keep_order() függvényt. Ebben a példában már használni fogunk öröklődést, és polimorfizmust is!
----------------------------------------------------------------------
Ahol csak lehet, használd fel az előzőleg megírt osztályaidat!
Ha szükséged van egy függvényre, amely nem található meg még a már
kész osztályodban, akkor azt add hozzá.
Például ha a Math osztályodba a te megoldásodhoz hiányzik valamilyen
függvény, akkor oda írd meg, ne csak direktbe felhasználd valamelyik
beépített header-ből!
Ha a vektorod remove() függvénye nem tartja meg a sorrendet, akkor
adj hozzá egy remove_keep_order() függvényt.
Egyéb:
Kicsit kiegyszerűsítettem az UML diagramokat, már gyakorlatilag c++
kódként néznek ki. Az előző feladatokban a tárgy által elvárt módon
voltak írva, de mostantól nem fogom annyira átszerkeszteni.
----------------------------------------------------------------------
class Tile A játékszabályok, amiket implementálni fogunk:
A játék n db játákossal indul. Mindenkinek van valamennyi pénze
(legyen egyeenként megadható). És van egy játékmező. (Mint a valódi
monopolyban kb).
A játékmezőn vannak mezők. Ezeknek a típusai:
- TaxTile - Amikor a játékos rálép ennyi adót kell fizetnie.
- OwnableTile - Ez olyan mező, amit meg lehet venni. Van vátelára,
illetve egy belépési költsége. Ha egy játékos rálép, és még senkié,
akkor az a játékos megveheti a vételárért cserébe. Ha nem veszi meg,
nem kell fizetnie semit. Ha valaki megveszi, akkor mindenki másnak,
aki rálép meg kell fiyetnie a tulajdonosnak a belépési díjat.
Ha a tulajdonos kiesik a játékból, akkor az összes tulajdona
felszabadul.
String name; - GainTile - Aki rálép az egy meghatározott össszeget kap.
virtual void player_arrived(Player *p);
- LuckTile - Aki rálép kaphat megadott %-nyi eséllyel,
két megadott érték közötti pénzt.
---------- - JailTile - Aki rálép, a megadott környi ideig börtönbe kerül, azaz
annzi körig nem léphet.
class Player Egy játékos akkor esik ki, ha elfogyott minden pénze.
String name; Az nyer, aki a legutoljára bent marad.
int tile_index;
int money;
int jail_time;
bool _lost;
virtual bool ask_buy(String name, int price); A játékosok előre meghatározott, fix sorrendben jönnek egymás után,
virtual void pay_entry(int val, Player *to); a körük elején dobnak 1db 6 oldalú dobókockával, majd anyit lépnek,
void pay_tax(int val); amennyit dobtak, és a mező amire érkeztek hatásal lesz rájuk.
void receive_payment(int val);
void lost();
bool did_lose();
virtual void act(); A játékosok a játékmezőn körbe-körbe haladnak.
virtual int throw_dice();
virtual void on_lose();
A játékot úgy fogjuk megírni, hogy legyenek különböző szemályiségü
gépi játékosok:
Agresszív: Mindent megvesz, amíg van rá pénze.
Konzervatív: Ha a mező ára kevesebb, mint a pénzének a fele, akkor megveszi,
Ügyeskedő: 50% eséllyel megveszi a mezőt, ha van rá lehetősége.
Emberi: Megkérdezi a felhasználót, hogy mit akar tenni.
Csaló: Mindent megvesz, amit csak tud. (csak 4, 5, 6-okat dobhat)
---------- A játokosok beállításait, és a mezőket is fájlból tötsük be.
class Playerloader Konzolos program lesz, szóval mindent ami fontos, a konzolra kell
majd kiírnunk, és a konzolról kell beolvasni, ha kérdezni szeretnénk a
felhasználótól.
vec pl laod_players(file); A feladatm hogy ezt implementáljuk.
save_players(file, Vec p);
Kezdjük a játékos osztályokkal:
---------- |--------------------------------------------------------------------------|
| class Player |
|--------------------------------------------------------------------------|
| + String get_name(); |
| + void set_name(const String &name); |
| |
| + int get_tile_index() const; |
| + void set_tile_index(const int val); |
| |
| + int get_money() const; |
| + void set_money(const int val); |
| |
| + int get_jail_time() const; |
| + void set_jail_time(const int val); |
| |
| + bool get_lost() const; |
| + void set_lost(const bool val); |
| |
| + virtual bool want_buy(const String &tile_name, int price); |
| + virtual int throw_dice(); |
| + virtual void on_lose(); |
| |
| + virtual void print(); |
| |
| + virtual String get_class_name(); |
| |
| + Player(); |
| + virtual ~Player(); |
| |
| - String _name; |
| - int _tile_index; |
| - int _money; |
| - int _jail_time; |
| - bool _lost; |
|--------------------------------------------------------------------------|
class TileLoader Amik nem nyilvánvalók:
isame set_money, set_jail_time -> írjon üzenetet a konzolra.
set_lost(val) -> ha a val true, hívja meg az on_lost() függvényt.
want_buy() függvénnyel fogja meegkérdezni a rendszer, hogy meg akarja-e
venni a játékos a jelenlegi mezőt.
Megj.: nagy programban valószínűleg érdemes lenne a magát a Tile osztályt
odaadni pointerkénkt, viszont a Tile osztálynak is kelleni fog majd, a
Player osztály.
ezek ay oytalzok load savelnek Ezt aműgy meg lehet oldani, méghozzá úgy, hogy a Tile osztály a Player
lehetne static fv playerbe is pl headerje tetején előre van deklarálva (class Tile;), a Player osztály
meg lehetne a boardba a Tile headerje tetején van előre deklarálva (class Player;), és acsak a
de igy egyszerubben ujra tudjuk majd hasznalni .cpp fájlokoban vannak maguk a headerek beincludeolva.
javaban TileFactorynak lenne nevezve
Hogy könnyítsek a dolgotokon, ezt kihagytam, viszont ha valaki elég erőt
érez magában, az mindenképp csinálja így!
Ekkor így fog kinézni a függvény:
virtual bool want_buy(Tile *tile);
(A volt paraméterek elérhetők a Tile osztály gettereivel.)
int throw_dice(); Kockadobás 1-6 ig.
on_lose() A játékos kiírja a konzolra, hogy vesztett. Mindegyik típus
kicsit máshogy.
---------- print() Kiírja magát a játékos a konzolra.
class TaxTile : Tile
int tax; get_class_name() Visszaadja a játékos osztályának a nevét.
virtual void player_arrived(Player *p); pl itt return "Player";
A kényelem miatt van bent, a print()-hez.
|--------------------------------------------------------------------------|
| class AgressivePlayer : public Player |
|--------------------------------------------------------------------------|
| + bool want_buy(const String &tile_name, int price); |
| + void on_lose(); |
| |
| + String get_class_name(); |
| |
| + AgressivePlayer(); |
|--------------------------------------------------------------------------|
Agresszív: Mindent megvesz, amíg van rá pénze.
|--------------------------------------------------------------------------|
| class ConservativePlayer : public Player |
|--------------------------------------------------------------------------|
| + bool want_buy(const String &tile_name, int price); |
| + void on_lose(); |
| |
| + String get_class_name(); |
| |
| + ConservativePlayer(); |
|--------------------------------------------------------------------------|
Konzervatív: Ha a mező ára kevesebb, mint a pénzének a fele, akkor megveszi,
|--------------------------------------------------------------------------|
| class TrickyPlayer : public Player |
|--------------------------------------------------------------------------|
| + bool want_buy(const String &tile_name, int price); |
| + void on_lose(); |
| |
| + String get_class_name(); |
| |
| + TrickyPlayer(); |
|--------------------------------------------------------------------------|
Ügyeskedő: 50% eséllyel megveszi a mezőt, ha van rá lehetősége.
|--------------------------------------------------------------------------|
| class HumanPlayer : public Player |
|--------------------------------------------------------------------------|
| + bool want_buy(const String &tile_name, int price); |
| + void on_lose(); |
| |
| + String get_class_name(); |
| |
| + HumanPlayer(); |
|--------------------------------------------------------------------------|
---------- Emberi: Megkérdezi a felhasználót, hogy mit akar tenni.
class OwnableTile : Tile
int price;
int enter_price;
Player *owner;
virtual void player_arrived(Player *p);
//ask player if he wnats to buy.
//if owned works like tax
//if owner steps on it, he gains enter_price
|--------------------------------------------------------------------------|
---------- | class CheatingPlayer : public Player |
class GainTile : Tile |--------------------------------------------------------------------------|
| + bool want_buy(const String &tile_name, int price); |
int gain; | + int throw_dice(); |
virtual void player_arrived(Player *p); | + void on_lose(); |
| |
| + String get_class_name(); |
---------- | |
class LuckTile : Tile | + CheatingPlayer(); |
|--------------------------------------------------------------------------|
int chance;
int gain_min; Csaló: Mindent megvesz, amit csak tud. (és csak 4, 5, 6-okat dobhat)
int gain_max;
virtual void player_arrived(Player *p);
|--------------------------------------------------------------------------|
---------- | class PlayerLoader |
class JailTile : Tile |--------------------------------------------------------------------------|
| + static Vector<Player *> load_player_file(const String &file_name); |
int jail_time; |--------------------------------------------------------------------------|
virtual void player_arrived(Player *p);
Segít betölteni egy játékosok leírását tartalmaző filet.
(Java-ban valószínűleg PlayerFactory lenne a neve.)
Mindegy, hogy a file hogy néz ki. De itt egy példa:
----------
Player 10000 AA
class AgressivePlayer : Player AgressivePlayer 20000 BC
ConservativePlayer 20000 DA
virtual void act(); TrickyPlayer 20000 FA
HumanPlayer 20000 RR
CheatingPlayer 20000 AF
----------
class ConservativePlayer : Player |--------------------------------------------------------------------------|
| class Tile |
virtual void act(); |--------------------------------------------------------------------------|
| + String get_name(); |
| + void set_name(const String &name); |
| |
---------- | + virtual void on_player_arrived(Player *p); |
| |
class TrickyPlayer : Player | + virtual void reset(); |
| |
virtual void act(); | + virtual void print(); |
| + virtual String get_class_name(); |
| |
| + Tile(); |
---------- | + virtual ~Tile(); |
| |
class HumanPlayer : Player | - String _name; |
|--------------------------------------------------------------------------|
virtual void act();
megkérdezi, hogy mit csináljon A Mező osztály.
A rendszer majd az on_player_arrived() függvényt hívja meg, miután egy
játékos dobott, és rálép a következő mezőre.
---------- Ez a függvény mindent releváns információt írjon a konzolra.
class CheatingPlayer : Player Itt maja a Mező fogja pl növelnia játékos pénzét, vagy börtönbe tenni,
vagy megkjérdezni, hogy meg akarja e venni megát a mezőt.
int throw_result;
reset() csak a OwnableTIle fog itt valamit csinálni, ugyanis ebben
virtual void act(); ki fogja nulláyni a tulajdonosát. (Ez két játék közötti kinullázásra való)
virtual int throw_dice();
A többit, ami esetleg nem triviális, lásd a player-nél.
----------
class Board |--------------------------------------------------------------------------|
| class TaxTile : public Tile |
Vector<Player *> players; |--------------------------------------------------------------------------|
Vector<Tile *> tiles; | + int get_tax() const; |
Vector<Player *> lost_players; | + void set_tax(const int tax); |
| |
int current_player; | + void on_player_arrived(Player *p); |
| + void print(); |
void step(); | + String get_class_name(); |
bool is_finished(); | |
void print_results(); | + TaxTile(); |
| |
void load_tile_file(String f); | - int _tax; |
void load_player_setup_file(String f); |--------------------------------------------------------------------------|
- TaxTile - Amikor a játékos rálép ennyi adót kell fizetnie.
step():
|--------------------------------------------------------------------------|
current player -> throw dice -> wrap index -> get tile -> tile->player_arrived(p) -> if did_lose() remove from game, add to lost_players | class OwnableTile : public Tile |
|--------------------------------------------------------------------------|
current_player++; and wrap; | + int get_price() const; |
| + void set_price(const int val); |
| |
| + int get_enter_price() const; |
| + void set_enter_price(const int val); |
| |
------------ | + Player *get_owner() const; |
| + void set_owner(Player *val); |
main() { | |
Board(); | + void on_player_arrived(Player *p); |
Board.load_tile_file(); | + void print(); |
Board.load_player_setup_file(); | + void reset(); |
| |
//esetleg kerdezhet | + String get_class_name(); |
| |
while (!board.is_finished()) { | + OwnableTile(); |
board.step(); | |
| - int _price; |
sleep 1s | - int _enter_price; |
} | - Player *_owner; |
|--------------------------------------------------------------------------|
board.print_results();
ret 0; - OwnableTile - Ez olyan mező, amit meg lehet venni. Van vátelára,
} illetve egy belépési költsége. Ha egy játékos rálép, és még senkié,
akkor az a játékos megveheti a vételárért cserébe. Ha nem veszi meg,
print_results(): nem kell fizetnie semit. Ha valaki megveszi, akkor mindenki másnak,
aki rálép meg kell fiyetnie a tulajdonosnak a belépési díjat.
1. place, 2nd place print etc. Ha a tulajdonos kiesik a játékból, akkor az összes tulajdona
felszabadul.
|--------------------------------------------------------------------------|
| class GainTile : public Tile |
|--------------------------------------------------------------------------|
| + int get_gain() const; |
| + void set_gain(const int val); |
| |
| + void on_player_arrived(Player *p); |
| + void print(); |
| + String get_class_name(); |
| |
| + GainTile(); |
| |
| - int _gain; |
|--------------------------------------------------------------------------|
- GainTile - Aki rálép az egy meghatározott össszeget kap.
|--------------------------------------------------------------------------|
| class LuckTile : public Tile |
|--------------------------------------------------------------------------|
| + int get_chance() const; |
| + void set_chance(const int val); |
| |
| + int get_gain_min() const; |
| + void set_gain_min(const int val); |
| |
| + int get_gain_max() const; |
| + void set_gain_max(const int val); |
| |
| + void on_player_arrived(Player *p); |
| + void print(); |
| + String get_class_name(); |
| |
| + LuckTile(); |
| |
| - int _chance; |
| - int _gain_min; |
| - int _gain_max; |
|--------------------------------------------------------------------------|
- LuckTile - Aki rálép kaphat megadott %-nyi eséllyel,
két megadott érték közötti pénzt.
|--------------------------------------------------------------------------|
| class JailTile : public Tile |
|--------------------------------------------------------------------------|
| + int get_jail_time() const; |
| + void set_jail_time(const int val); |
| |
| + void on_player_arrived(Player *p); |
| + void print(); |
| + String get_class_name(); |
| |
| + JailTile(); |
| |
| - int _jail_time; |
|--------------------------------------------------------------------------|
- JailTile - Aki rálép, a megadott környi ideig börtönbe kerül, azaz
annzi körig nem léphet.
|--------------------------------------------------------------------------|
| class TileLoader |
|--------------------------------------------------------------------------|
| + static Vector<Tile *> load_tile_file(const String &file_name); |
|--------------------------------------------------------------------------|
Ugyanolyan betöltő osztály, mint a játékos estében.
Példa file szerkezet:
Tile A
TaxTile B 3433
TaxTile C 3433
OwnableTile D 222 22
OwnableTile E 222 22
OwnableTile F 222 22
GainTile G 100
TaxTile H 3433
LuckTile I 50 100 200
TaxTile J 3433
JailTile K 3
TaxTile L 3433
TaxTile M 3433
TaxTile N 3433
|--------------------------------------------------------------------------|
| class Board |
|--------------------------------------------------------------------------|
| + Player *get_current_player(); |
| + Player *get_previous_player(); |
| |
| + int get_turn() const; |
| + void set_turn(const int turn); |
| |
| + Vector<Tile *> get_tiles() const; |
| + void set_tiles(const Vector<Tile *> &tiles); |
| |
| + Vector<Player *> get_active_players() const; |
| + void set_active_players(const Vector<Player *> &players); |
| |
| + Vector<Player *> get_lost_players() const; |
| + void set_lost_players(const Vector<Player *> &players); |
| |
| + void load(const String &tile_file, const String &player_file); |
| + void load_players(const String &file); |
| + void load_tiles(const String &file); |
| |
| + void step(); |
| + void run(); |
| |
| + void on_game_finished(); |
| |
| + void clear(); |
| + void clear_players(); |
| + void reset(); |
| |
| + void print(); |
| |
| + Board(); |
| + Board(const String &tile_file, const String &player_file); |
| + virtual ~Board(); |
| |
| - Vector<Tile *> _tiles; |
| - Vector<Player *> _active_players; |
| - Vector<Player *> _lost_players; |
| - |
| - Player *_previous_player; |
| - int _current_player_index; |
| - int _turn; |
|--------------------------------------------------------------------------|
on_game_finished() a játékról kiír a konyolra mindenféle információt,
miután véget ért.
run() a fő ciklus, a step() fggvényt hívogatja, amíg több mint 1
aktív játékos van. Esetleg kiléphez nagy _turn szám után is.
Ha a ciklus kilépett, hívja meg az on_game_finished()-et.
clear() Minden vektort kiürít.
clear_players() csak a 2 játékos vektort üríti ki.
ne felejtsétek ez felszabadítani a memóriát! (delete).
step():
Egy játékos körének a kezelése.
Az algoritmus:
1. Fogjuk meg az aktív játékost.
2. Ha börtönben van, vonjunk le egy kört a börtönének számából, és kész.
3. Dobassunk vele kockát.
4. Számoljuk ki (modulo), hogy melyik mezőre érkezett. (player get_tile_index())
5. Állítsuk be az új mező indexét neki (set_tile_index()).
6. kérjük ki a megfelelő mezőt a _tiles vektorból, és hívjuk meg a
on_player_arrived(p); függvényét, a játékost adjuk be paraméternek.
7. Állítsuk be a _previous_player osztályváltozót a jelenlegi játékosra.
8. Ha ajátékos vesztett (get_lost()), akkor rakjuk ár a _lost_players
veektorba, majd ellenűrizzük, hogy a _current_player_index nem indexel-e
túl a játékosok vektorán. Ha igen, akkor állítsuk a
_current_player_index-et 0-ra. (ugye eggyel csökkent a vektor mérete.)
9. Egyébként növeljük meg a _current_player_index-et 1-el, és ugyanűgy
ellenűrizzük, hogy a _current_player_index nem indexel-e
túl a játékosok vektorán, ha igen, akkor állítsuk a
_current_player_index-et 0-ra.
main.cpp + int main() :
A main függvénybe csak ennyi legyen:
Math::randomize();
Board b;
b.load("tiles.config", "players.config");
b.run();
b.print();
return 0;
Nyilvánvalóan a "tiles.config", "players.config" fájlokat hozzátok létre.

View File

@ -1,6 +1,6 @@
Player 10000 Jaj Player 10000 AA
AgressivePlayer 20000 FFF AgressivePlayer 20000 BC
ConservativePlayer 20000 Acq ConservativePlayer 20000 DA
TrickyPlayer 20000 dqd TrickyPlayer 20000 FA
HumanPlayer 20000 WFa HumanPlayer 20000 RR
CheatingPlayer 20000 Fqqf CheatingPlayer 20000 AF