Chci geek triko! Chci geek triko!
Extra 10 % bodů navíc a tričko zdarma při zadání kódu "TRIKO10"

Diskuze: hra pacman

Java Java hra pacman American English version English version

Aktivity (1)
Avatar
Michal
Člen
Avatar
Michal:3. září 23:43

ahoj
začal jsem před pár dny s programováním v javě (rovnou v javafx, protože tu píšou, že swing už je zastaralý) :-P
programuju hru PacMan (už jsem ji kdysi dělal ve VBA, takže to pro mě není nic nového, ale to jsem dělal strukturovaně, částečně modulárně, i přes třídy)
tentokrát jsem si nejdříve vytvořil herní arénu, na ní jsem si inicioval pacmana a duchy (duchové jsou potomci pacmana), parádně se mi je podařilo oddědit od pacmana,
a teď přijde má otázka: pokud Pacman (předek) sní kouli a začne honit duchy (potomky), tak jak jim to má oznámit? (duchové totiž musí změnit svou grafiku a začít před ním utíkat) nejdříve jsem to udělal přes arénu, pak jsem si řekl, že když je duch potomek pacmana, tak se mohou bavit přímo (měl jsem tam ale dost velký problém s iniciací a vzdal jsem to - myslím, že mi to napovědělo, že takhle to nejde), něco mi říká, že by se měli bavit přes herní arénu, kde byli společně iniciovaní (honění duchů pacmanem není režim pacmana, ale herní režim celé hry)
začal jsem si přístup OOP teprve osvojovat, mám ještě celkem mezery :)
v excelu už bych to měl dávno zbastlené, ale kvůli OOP mám celkem zpoždění :)
ale musím uznat, že java a její mikrosofťácký synek C# jsou daleko luxusnější pro programování (pokud v tom člověk umí)
m.

 
Odpovědět 3. září 23:43
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:4. září 10:03

dědičnost znamená, že má potomek stejné vlastnosti, jako předek (všechny vlastnosti předka). To ale neznamená, že musí být mezi nimi vazba 1:1. Potomek si může metody překrývat. Takže pokud má třeba pacman metodu jdi vpravo, tak potomek může mít podmínku v této metodě, že pokud nějaký objekt je v takovém a takovém stavu, tak pro něj to znamená, jdi vlevo.

V pacmanovi krásně využiješ nejrůznější návrhové vzory. Singleton, state (o kterém jsem teď mluvil a ten se pro tu hru krásně hodí), to samé třeba messenger, abys nebyl závislý na jednom konkrétním objektu, atd.
Jinak k javě FX mám teď zásadní výhradu.... a to práce s vlákny. Nedávno jsem zjistil při doučování, že v javě FX asi nefunguje join, jak by měl a doteď to hledám. To jen tak pro info, že všechno pro má i své proti.

Nahoru Odpovědět 4. září 10:03
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Michal
Člen
Avatar
Michal:4. září 12:35

díky za typy
dědění rozumím, ale nevím, jak vyřešit čistou metodou toto:

dejme tomu, že je pacman v režimu, kdy honí duchy
duch se to ale musí dozvědět, jinak bude dál pacmana honit

vytvořil jsem si tedy v pacmanovi vlastnost "režim" a veřejnou metodu, kterou volá duch, aby se dozvěděl,v jakém režimu pacman je, jediné, co se ale duch dozví o pacmanově režimu, je "null"
vlastnost "režim" mám samozřejmě řádně inicializovanou, a "null" mi to hází podle mě proto, že se duch ptá na svou poděděnou vlastnost, která žádnou hodnotu nemá
potřeboval bych do metody nastavil, aby duchovi vracel hodnotu předka (něco jako "return ancestor.rezim" namísto return rezim)

 
Nahoru Odpovědět 4. září 12:35
Avatar
Michal
Člen
Avatar
Michal:4. září 12:55

přesněji řečeno:
režim pacmana potřebuju zjišťovat ve třídě Duch (potomek třídy Pacman) v překryté metodě Pohyb, která se volá pomocí časovače

 
Nahoru Odpovědět 4. září 12:55
Avatar
Odpovídá na Michal
Matúš Olejník:4. září 12:56

Nestíham písať z mobilu ale môžeš pozrieť tuto, kde je v podstate riešená tvoja otázka :) . Vytvoriť si vlastný listener.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět  +1 4. září 12:56
/* I am not sure why this works but it fixes the problem */
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:4. září 13:17

Řešení je vždy několik a musíš vybrat takové, aby odpovídalo právě tvému projektu.
Nejjednodušší řešení, co může být, tak aby si při vytváření každého ducha každý duch pamatoval instanci pacmana. Případně by mohla existovat tovární metoda pacmana, kterou bys vždy zavolal a na ní bys volal stavovou metodu pacmana, ve které bys zjistil, v jakém stavu pacman je.
Příklad tovární metody:

public class Ghost extends Pacman {
        public void move() {
                //definition
                if(Pacman.getInstance().isDanger()) {
                        //move from pacman
                }
                //definition
        }
}

Příklad pamatování si instance (což by možná v tomto případě mohlo být i dobrý. Budeš mít jistotu, že pracuješ s konkrétní instancí, takže nebudeš muset řešit problém, když bys spustil novou hru, tak že bys chytal pacmana, který už třeba neexistuje, protože bys ho zapomněl převytvořit:), atd.)

public class Ghost extends Pacman {
        private final Pacman pacman;
        public Ghost(<barvička>, <pozice>, <další parametry>, Pacman currentPacman) {
                pacman = currentPacman;
        }

        public void move() {
                //definition
                if(pacman.isDanger() ) {
                        //move from pacman
                }
                //definition
        }
}

S tím, že Pacman bude v sobě obsahovat metodu isDanger(), která bude kontrolovat, že sežral ten protein a může baštit duchy. No a docela dobré je, že tuto metodu takto dědí i duch. Takže pro pacmana je v případě, že nic nesežral, zase danger duch:) Takže to je právě zajímavý případ, kdy se dědičnost vyplatí jak potomkovi vůči předkovi, tak i dokonce naopak. I když to není samotný smysl dědičnosti, tak teď bys to krásně mohl takhle využít:)

S tím, že pro předka je duch danger, pokud nic nesežral. Pokud sežral, tak je on danger a naopak duch danger není, takže v podstatě v potomkovi převrátíš podmínku. A dokonce by to šlo udělat logičtěji. Že bys v duchovi nic nemusel definovat, ale stačilo by, kdybys v metodě isDanger(), kterou zdědíš z pacmana, tak převrátil výsledek.

@Override
public boolean isDanger() {
        return super.isDanger() == true ? false : true;
}

A jsi vysmátý:) a veškerou logiku definuješ v pacmanovi

Nahoru Odpovědět 4. září 13:17
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Michal
Člen
Avatar
Michal:4. září 17:51

Díky oběma za odpověď. Nakonec jsem tam nechal to svoje staré řešení. Pacman při změně režimu informuje arénu o této změně. A duchové každý tah zjišťují aktuální režim.

 
Nahoru Odpovědět 4. září 17:51
Avatar
Jirka
Člen
Avatar
Odpovídá na Lubor Pešek
Jirka:4. září 18:27

Ahoj.

Já bych to řešil spíše tak, že bych nejprve deklaroval abstraktní třídu Postava, ze které bych dědil jak třídu Duch, tak třídu Pacman, protože jde o zcela odlišné postavy s odlišným chování. Je sice pravda, že se nám nyní dědění Ducha z Pacmana hodí, ale s dalším vývojem nejspíše narazíme.

public abstract class Postava {
private AbsolutePosition ap;

public void move(AbsolutePosition ap);
public void move(RelativePosition rp);

public Postava(AbsolutePosition ap) {
this.ap = ap;
}
}

Před Duchem deklarujeme Pacmana:

public class Pacman extends Postava {
private protein;

public Pacman(AbsolutePosition ap, Protein protein, etc.)
super(ap);
this.protein = protein;
etc.
}

Dále definujeme Ducha jako potomka Postavy:

public class Duch extends Postava {
private barva;

public Duch(AbsolutePosition ap, Barva barva, etc.)
super(ap);
this.barva = barva;
etc.
}

A takto to rozvíjet. Podle pravidla, že každý rodič může být zastoupen svým potomkem.

Nahoru Odpovědět  +1 4. září 18:27
Kdo nic nedělá, nic nezkazí.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:4. září 18:50

Podle pravidla, že každý rodič může být zastoupen svým potomkem

Trošku nelogická věta...
Možná jsi myslel spíš, že potomka můžeme přetypovat na datový typ rodiče, ale naopak to nejde, protože třída přeci nemůže vědět, kdo z ní bude dědit. Jediná třída, která to ví, je konečná třída. Z té nikdo dědit nebude.

Jinak samozřejmě, existuje spousta možností, jak programovat. V tom je právě ta krása a kouzlo. A je jen na programátorovi, jakým směrem se ubere a pro co se rozhodne. Já osobně používám abstraktní třídu jako rozšíření rozhraní, ne dědičnosti. To je každého věc, jak se k danému kódu dohrabe, ale hlavně by měl svůj postup i vždy zdůvodnit - proč to či ono tak je.

Nahoru Odpovědět 4. září 18:50
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Jirka
Člen
Avatar
Odpovídá na Lubor Pešek
Jirka:4. září 19:09

Mluví se o tzv. Principu Liskové.

Třeba zde: https://cs.wikipedia.org/…toupen%C3%AD .

Viz. též Rudolf Pecinovský, Java 8.

Nahoru Odpovědět 4. září 19:09
Kdo nic nedělá, nic nezkazí.
Avatar
dez1nd
Člen
Avatar
Odpovídá na Jirka
dez1nd:5. září 10:17

Ano, protože každý potomek dědí vše od předka a v tom případě může dojít k nahrazení předka potomkem. Obráceně to nejde, protože potomek může mít vlastnosti navíc, které předek nemá.

 
Nahoru Odpovědět  +1 5. září 10:17
Avatar
dez1nd
Člen
Avatar
Odpovídá na Lubor Pešek
dez1nd:5. září 10:19

Trošku nelogická věta...

Co je na tom nelogického ?

 
Nahoru Odpovědět 5. září 10:19
Avatar
Jirka
Člen
Avatar
Odpovídá na dez1nd
Jirka:5. září 10:53

Děkuji :)

Nahoru Odpovědět 5. září 10:53
Kdo nic nedělá, nic nezkazí.
Avatar
Lubor Pešek
Člen
Avatar
Odpovídá na dez1nd
Lubor Pešek:5. září 11:35

Právě, že z pohledu OOP objekt datového typu předka přetypovat datovým typem potomka. Aspoň takto ta věta v kontextu vyzněla

Nahoru Odpovědět 5. září 11:35
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Michal
Člen
Avatar
Michal:5. září 11:42

Hezky se tu rozvinula debata, ale můj problém moc neřešila.
O společném předku samozřejmě uvažuju, ale učím se to a chci si to všechno osahat.
:)
Takže info pro vás:
Hledal jsem maximálně jednoduché řešení, které bude zároveň přirozené. Tj. žádné vytváření dalších objektů či komunikace přes prostředníka (přes arénu, protože ve třídě Aréna nepotřebuju režimHry znát)
Řešení Listener už bylo hodně blízko mé představě.
Nakonec jsem to vyřešil úplně jednoduše: třída pacman má seznam všech objektů (vytvořil jsem si ho), které přes ni byly inicializovány. Vytvořil jsem si tedy ve zděděné třídě Duch veřejnou metodu "oznameniZmeny­RezimuHry (RezimHry rh)" a z rodičovské třídy Pacman jsem těm duchům prostě řekl, že je teď bude pacman honit.

 
Nahoru Odpovědět 5. září 11:42
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal
DarkCoder:5. září 12:23

Ve hře existují pouze dva stavy - Pacman je pri kolizi schopen zničit ducha ci nikoli. Proč jednoduše nevytvoriš proměnnou pro Pacmana jejíž status 0 nebo 1 odpovídá tomu, zda na Pacmana působí efekt sežráné koule či nikoli?

Editováno 5. září 12:24
Nahoru Odpovědět 5. září 12:23
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Michal
Člen
Avatar
Michal:5. září 12:56

to ale problém neřeší, taky jsem měl proměnnou, pouze se jinak jmenovala (režimHry), řešil jsem problém, jak to odkomunikovat a správně sdělit ostatním objektům
chtěl jsem jenom vědět, jak by spolu měly tyto objekty ve hře komunikovat a přišel jsem na to:
nejlepší přístup bude přes arénu - ta bude něco jako rozhodčím v zápase - pacman jí nahlásí sežrání koule a aréna rozhodne o změně režimu hry - ve fotbale je to stejné, i když přijde faul a půl hřiště je přesvědčeno o tom, že se bude kopat desítka, tak to musí někdo posvětit

 
Nahoru Odpovědět 5. září 12:56
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal
DarkCoder:5. září 13:40

Ovšem že řeší. Sežrání koule je globální událost která ovlivňuje všechny pohybující se objekty a přenastavuje jejich vlastnosti. Což je jistá forma rozhodčího. Při kolizi dochází k porovnávání vlastnosti objektu, kteří se kolize zůčastnily. Tedy ze správného hlediska můžeš vlastnost ničení přiřadit všem objektům a při vyhodnocování kolize je porovnávat. Ale jelikož víš na základě logiky jak princip kolize probíhá, tak nepotřebuješ duplikovat něco co lze určit přímo. Duplikace vlastnosti je v tomto případě akorát mrhání paměti a procesorového času.

Nahoru Odpovědět 5. září 13:40
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Jirka
Člen
Avatar
Odpovídá na Michal
Jirka:5. září 13:52

Řekl bych, že zmíněný Listener je dobrý pro situace, kdy je v Aréně s Pacmanem více Duchů.

Listener jsem našel zde: https://cs.wikipedia.org/…ávrhový_vzor)

Editováno 5. září 13:54
Nahoru Odpovědět 5. září 13:52
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na DarkCoder
Jirka:5. září 14:24

A co kdyby se změnou stavu hry se změnilo chování Pacmana i Duchů. Například v jednom stavu prchá Pacman, v druhém Duchové, tedy změna jejich chování či algoritmu...

Nahoru Odpovědět 5. září 14:24
Kdo nic nedělá, nic nezkazí.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:5. září 14:43

To vše už je zahrnuto v globální události při sežrání koule. Není to jen o nastavení vlastností Pacmana na lovce. Ta událost je komplexni (dochází ke změně chování objektu, jejich barev, zvuků, apod).

Nahoru Odpovědět 5. září 14:43
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Jirka
Člen
Avatar
Odpovídá na DarkCoder
Jirka:5. září 15:13

Ale ten Observer-Listener se zde uplatní, ne? Abychom nemuseli stále obcházet Pacmana a všechny Duchy. Já bych vložil do List<Duch> (asi ArrayList nebo LinkedList) instance Duchů a jednou za periodu bych je otestoval a eventuálně s nimy o krok pohnul.

Nahoru Odpovědět 5. září 15:13
Kdo nic nedělá, nic nezkazí.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka
DarkCoder:5. září 15:58

To co potřebuješ znát v okamžiku spuštění události je přístup k vlastnostem všem pohybujících se objektů. Ač každý objekt má své vlastnosti, přistupujeme k objektům v teamu neindividualne! V teamu je třeba pracovat úplně jinak. Tak, že společné vlastnosti sdružují do jedne. Tedy nadobjektove. Konkrétní vlastnosti ukazují na jednu nadobjektove, jejíž změna se přenese na vsechny objekty, u kterých se má změna projevit. Úspora procesorového času a paměti tohoto způsobu oproti přístupu ke všem objektům samostatně je extrémní!

Nahoru Odpovědět 5. září 15:58
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Michal
Člen
Avatar
Odpovídá na Jirka
Michal:5. září 17:50

Observer-Listener se zde určitě uplatní, informace se k posluchačům dostane automaticky, takže nemusíš iterovat arraylist, a když máš arraylist, tak nepotřebuješ observer-listener. Je to v podstatě stejné řešení, jenom nemusíš používat slovo implement. Ale i v tom listeneru si vytváříš arraylist posluchačů. takže v mém případě je listener něco navíc.
Jak jsem již ráno psal, udělal jsem to přes arraylist (kde mám odkazy na pacmana i duchy). Zprávu posílá pacman duchům samozřejmě jen, když pacman sežere kouli. Takže duchové nemusí každý cyklus zjišťovat, co se děje. A nezatěžují tedy ani procesor.

 
Nahoru Odpovědět 5. září 17:50
Avatar
Jirka
Člen
Avatar
Odpovídá na DarkCoder
Jirka:5. září 19:16

V tomto případě ano, ale pokud bude zadání gradovat, třeba směrem na více druhů nepřátel, s více různými vlastnostmi, tak si myslím, že potom budeš muset provést refaktoring a postupně změnit objektovou strukturu projektu.

Nahoru Odpovědět 5. září 19:16
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Michal
Jirka:5. září 20:23

Pokud by se ve hře dynamicky měnil počet a typ nepřátel, asi by byl vhodný i klasický Observer-Listener.

Podle Pecinovského by se k výkonové optimalizaci se mělo přikročit až po implementaci problému.

Ještě bych řekl, že později i nepřátelé mohou mít různé chování.

Nahoru Odpovědět 5. září 20:23
Kdo nic nedělá, nic nezkazí.
Avatar
Michal
Člen
Avatar
Odpovídá na Jirka
Michal:6. září 5:14

ano, myslím, že máš pravdu, ale i ten počet a typ nepřátel jako programátor znáš, takže je do toho arraylistu můžeš přidat (tj. se sám rozhodneš, jak tu hru postavíš a naprogramuješ), takže asi záleží na programátorovi, jestli ty dynamické změny bude chtít znát, anebo se nechá překvapit (sebe i objekty hry) a použije listener

 
Nahoru Odpovědět 6. září 5:14
Avatar
Michal
Člen
Avatar
Michal:9. září 1:35

jde to tedy i přes statiku, jak jsem dnes zjistil, je to pohodlnější než listener i iterování arraylistem, ale tady píšou, že statika je zlo, takže to nepoužiju a nebudu tu psát podrobnosti, dokonce po změně hodnoty proměnné v předkovi se hodnota aktualizuje v potomcích

 
Nahoru Odpovědět 9. září 1:35
Avatar
Michal
Člen
Avatar
Odpovídá na Jirka
Michal:11. září 2:18

Pecinovského jsem zatím nečetl, jenom lekci 19 (abstraktní třída) z těchto stránek, o návrzích taky vím kulové. Já většinou dělám všechno obráceně. Nejdříve to pochopím tak nějak sám od sebe, a teprve pak si to ověřuju na základě teorie.
Ze začátku jsem se toho tedy tudíž strašně zalekl, ale když jsem pochopil, že abstraktní třídu nelze instanciovat, tak mě to navedlo a přestal jsem Hrac hrac = new Hrac() cpát pořád do třídy Arena :). Pak jsem dokonce pochopil, že tam můžu nechat Pacman pacman i Duch duch a instanciovat, jak jsem to dosud měl. Nakonec jsem vytvořil na herní aréně nejprve abstraktní třídu ObjektAreny (tím může být jednak ovoce, které se čas od času objeví, aby ho pacman mohl sníst a dostat body, jednak pacman, duch apod. - protože jsou to samostatné objekty a mají společné základní vlastnosti a metody). Tam jsem nadefinoval, že každý takový objekt tedy musí mít jako atribut jméno a metody (inicializace časovače, inicializace grafiky a akce, což je metoda vyvolaná časovačem). Ze třídy ObjektAreny jsem pak vydědil třídu Hrac (tj. Hráč) - nějak se mi podařilo vytvořit konstruktor a pak už to šlo jak po másle. Třída Pacman už je potomkem třídy Hrac, jenom třída Duch je ještě podle třídy Pacman (samotná třída Duch je už hotová, ale v dalších asi 3 třídách mi to ještě hází chyby - budu tam muset pár věcí přetypovat a tak podobně), ale ještě tak hodinu a měl bych mít hotovo. Pak bych výhledově aplikoval ten ActionListener (to se mi podařilo jen na primitivním příkladu, ale ve třídě Pacman jsem si ani neškrtnul.) Ovoce by mělo pacmanovi oznámit, že se objevilo/zmizelo. Přijde mi totiž divný, aby se pacman každý krok dotazoval do arény, jestli se náhodou ovoce neobjevilo. :) Mohl bych si samozřejmě vytvořit datové pole, tam mít informace o pozicích duchů, pacmana, ovoce, zdí arény apod., ale to by bylo příliš snadné a už jsem to tak kdysi dělal. To OOP je fakt dobrý.

 
Nahoru Odpovědět 11. září 2:18
Avatar
Jirka
Člen
Avatar
Odpovídá na Michal
Jirka:11. září 17:29

Je známá věc, že počítače se učí s počítačem. Nejde jen číst sebelepší knihu. Ale ze své praxe vím, že dobrá kniha je opravdu důležitá. Není dobré vynalézat kolo ani návrhové vzory!

Nejlépe je nastudovat si problém a hned ho zkusit v počítači.

Držím palce.

Nahoru Odpovědět 11. září 17:29
Kdo nic nedělá, nic nezkazí.
Avatar
Michal
Člen
Avatar
Odpovídá na Jirka
Michal:11. září 17:44

Podařilo se mi to oddědit, ale bylo to peklo.
Místo ActionListeneru dává ovoce zprávu pacmanovi přes arénu. Výhledově bych mohl napsat třídu rozhodčí, až si načtu nějakou tu teorii.
Příště už to budu psát od začátku oddělené.
Díky za podporu.

 
Nahoru Odpovědět 11. září 17:44
Avatar
Jirka
Člen
Avatar
Odpovídá na Michal
Jirka:11. září 17:53

Nemáš zač.

Ještě je dobré zvládnout testování a refaktorování. Testování je jasné, ale také je třeba to umět. A refaktoring se uplatní při změně struktury programu.

Nahoru Odpovědět 11. září 17:53
Kdo nic nedělá, nic nezkazí.
Avatar
Michal
Člen
Avatar
Odpovídá na Matúš Olejník
Michal:16. září 17:02

Díky
Nakonec jsem se dostal do situace, kdy mi nezbylo než to implementovat, a podařilo se!
V herní aréně jsem si instancioval ManažeraAudia, jenomže když klip dohrál, tak jsem neměl (alespoň já jako začátečník to tak cítím) jinou rozumnou možnost, jak aréně říct z manažeraAudia, že hudba dohrála a že může spustit hru. Asi jsem to měl udělat jinak (u klipu totiž už používám LineEvent - LineListener), ale potřeboval jsem rychle funkční řešení. Funguje to fantasticky.
m.

 
Nahoru Odpovědět 16. září 17:02
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 33 zpráv z 33.