TlačiťTlačiť Slovenčina English Hľadať RSS

© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 27. 4. 2024.

Stránka sa načítava, prosím čakajte…

Dátum: 26. 10. 2013, pred viacerými rokmi, aktualizované: 30. 7. 2020, pred štyrmi rokmi

Na tejto stránke je publikovaný ukážkový projekt, ktorý môže tvoriť základ pre hru v žánri textovej adventúry. Ide len o návrh malej časti rozhrania hry. Termín textová adventúra označuje žáner hry, ktorá komunikuje s hráčom výhradne textovou formou. Aj napriek negrafickej orientácii projektu sú v ňom používané viaceré súčasti programovacieho rámca grafického robota. otvárané v novom okne
(obvykle ide o externý odkaz)

  
obrázok 
Ukážka okna po spustení aplikácie a zadaní niekoľkých príkazov. 
 

~

import knižnica.*;

/**
 * Na programovaní textovej adventúry sa dá pekne predviesť podstata
 * objektového modelovania. Budeme pracovať s bežnými pojmami z reálneho
 * sveta, ale namiesto ich reálneho zobrazovania budeme pracovať s ich
 * textovými opismi, čo je pre tento žáner hry charakteristické.
 *
 * Na ukážku je v tomto projekte vytvorených niekoľko jednoduchých tried
 * reprezentujúcich miestnosti, predmety a hráča (avatara).
 *
 * Pri objektovom modelovaní ide o to, aby:
 *   – vlastnosti boli vyjadrené premennými, ktoré sú súkromné,
 *   – ku každej vlastnosti bolo poskytnuté programátorské rozhranie, to jest
 *     definícia jednej alebo viacerých verejných metód, ktoré slúžia na
 *     prácu s touto vlastnosťou.
 *
 * Toto rozhranie môže byť tvorené v podstate tromi základnými „druhmi“ metód:
 *   – metódami, ktoré slúžia na zápis vlastností,
 *   – metódami, ktoré slúžia na čítanie vlastností,
 *   – metódami, ktoré slúžia na „inú prácu“ s vlastnosťami (to môže byť
 *     čokoľvek; napríklad použitie objektu v súčinnosti s iným objektom,
 *     vnútorné spracovanie údajov a podobne).
 *
 * Každá trieda sa stará výhradne o svoje „životné funkcie.“ Vytvorené
 * inštancie tried „oživujú“ hru. Používajú na to programátorské rozhranie
 * tried, to jest ich verejné metódy.
 */

public class Adventúra extends GRobot
{
	private final static Písmo písmoKonzoly =
		new Písmo("Verdana", Písmo.NORMÁLNE, 14);

	// Definície miestností:
	private final Miestnosť škola = new Miestnosť("škola", "Si v škole.");
	private final Miestnosť ulica = new Miestnosť("ulica", "Si na ulici.");
	private final Miestnosť park = new Miestnosť("park", "Si v parku.");

	// Definície predmetov:
	private final Predmet kniha = new Predmet("kniha", "Toto je kniha.");
	private final Predmet lopta = new Predmet("lopta", "Toto je lopta.");
	private final Predmet list = new Predmet("list", "Toto je list.");

	// Definícia avatara:
	private final Avatar avatar = new Avatar(škola);


	// Konštruktor
	public Adventúra()
	{
		// Priradenie vlastností jednotlivým inštanciám miestností.
		//    V tomto štádiu rozprogramovania to súvisí najmä s prepojením
		//    miestostí navzájom. Názov a opis miestnosti sú priradené priamo
		//    v pri konštrukcii (to jest pri new Miestnosť("…", "…") – pozri
		//    vyššie). Okrem toho tu môžu byť uvedené rôzne prepojenia –
		//    napríklad sú tu vložené predmety do jednotlivých miestností.

		// Škola:
		škola.prepojMaS(ulica);
		škola.vložPredmet(kniha);

		// Ulica:
		ulica.prepojMaS(škola);
		ulica.prepojMaS(park);
		ulica.vložPredmet(lopta);

		// Park:
		park.prepojMaS(ulica);
		park.vložPredmet(list);

		// Definícia obsluhy udalostí s jedinou reakciou spracúvajúcou
		// potvrdenie údajov v príkazovom riadku.
		new ObsluhaUdalostí()
		{
			public void potvrdenieÚdajov() { spracujPríkaz(); }
		};

		// Nastavenie iného písma vnútornej konzoly sveta (na zlepšenie
		// čitateľnosti).
		Svet.písmo(písmoKonzoly);

		// Zobrazenie a aktivácia vstupného riadka.
		Svet.neskrývajVstupnýRiadok();
		Svet.začniVstup("Zadaj príkaz:");

		// Výpis počiatočného stavu hry.
		vypíšStav();
	}

	/**
	 * Výpis aktuálneho stavu hry.
	 */
	public void vypíšStav()
	{
		// Vypíše sa opis miestnosti, v ktorej sa práve nachádza avatar.
		avatar.kdeSom().vypíšOpis();

		// Vypíše sa zoznam dverí.
		avatar.kdeSom().vypíšZoznamDverí();

		// Výpis predmetov prítomných/viditeľných v miestnosti.
		avatar.kdeSom().vypíšZoznamPredmetov();

		// Výpis zoznamu predmetov v inventári avatara.
		avatar.vypíšInventár();

		// Vynechanie prázdneho riadka.
		Svet.vypíšRiadok();
	}


	/**
	 * Pokus o prechod do miestnosti identifikovanej zadaným názvom. Ak
	 * metóda uspeje, vráti true, inak vráti false.
	 */
	public boolean choďDo(String názovMiestnosti)
	{
		// Hľadajú sa dvere:
		Miestnosť prechod = avatar.kdeSom().hľadajDvere(názovMiestnosti);

		if (null != prechod)
		{
			// Zmena miestnosti a vrátenie hodnoty true, ktorá v tomto
			// prípade znamená úspešnosť akcie.
			avatar.presuňDo(prechod);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}

	/**
	 * Pokus o zobratie predmetu identifikovaného zadaným názvom. V prípade,
	 * že je akcia úspešná vráti metóda hodnotu true, inak false.
	 */
	public boolean zober(String názovPredmetu)
	{
		// Hľadá sa predmet v aktuálnej miestnosti:
		Predmet predmet = avatar.kdeSom().hľadajPredmet(názovPredmetu);

		if (null != predmet)
		{
			// Zobratie predmetu pozostáva z dvoch čiastkových akcií:
			// odstránenie predmetu zo zoznamu predmetov aktuálnej miestnosti
			// a vloženie predmetu do inventára avatara. Návratová hodnota
			// true signalizuje, že akcia bola úspešná (to de facto znamená,
			// že predmet bol nájdený v aktuálnej miestnosti, pretože žiadne
			// iné podmienky nie sú v súčasnosti overované).
			avatar.kdeSom().odstráňPredmet(predmet);
			avatar.vložPredmet(predmet);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}

	/**
	 * Pokus o položenie predmetu identifikovaného zadaným názvom. V prípade,
	 * že je akcia úspešná vráti metóda hodnotu true, inak false.
	 */
	public boolean polož(String názovPredmetu)
	{
		// Hľadá sa predmet v inventári avatara:
		Predmet predmet = avatar.hľadajPredmet(názovPredmetu);

		if (null != predmet)
		{
			// Podobne ako zobratie predmetu, aj položenie pozostáva z dvoch
			// čiastkových akcií: odstránenie predmetu z inventára
			// a vloženie do zoznamu predmetov aktuálnej miestnosti. Opäť,
			// návratová hodnota true signalizuje, že akcia bola úspešná.
			avatar.odstráňPredmet(predmet);
			avatar.kdeSom().vložPredmet(predmet);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}


	// Rozpoznanie príkazu a spustenie prislúchajúcich akcií.
	public void spracujPríkaz()
	{
		// Definícia reťazca „príkaz“ (s hodnotou prevzatou zo vstupného
		// riadka) a deklarácia reťazca „parameter.“
		String príkaz = Svet.prevezmiReťazec(), parameter;

		// Vypísanie príkazu (ozvena) a jeho prevod na malé písmená.
		vypíšText(modrá, príkaz);
		príkaz = príkaz.toLowerCase();

		// Ak sa zadaný príkaz začína slovom „choď“ (rovnako v ďalších
		// prípadoch):
		if (príkaz.startsWith("choď "))
		{
			// Prvých päť znakov (to jest aj medzera za slovom) sa preskočí
			// a zvyšok textu sa uloží do premennej „parameter.“
			parameter = príkaz.substring(5);

			// Pokus o prechod do zadanej miestnosti (to jest tej,
			// ktorej meno je v premennej „parameter“).
			if (choďDo(parameter))
			{
				// V prípade úspechu sa vymaže obrazovka
				// a vypíše sa nový stav hry.
				strop.vymažTexty();
				vypíšStav();
			}
			else
				// (Výpis chybového stavu – rovnako v ďalších prípadoch…)
				vypíšText(červená, "Odtiaľto sa tam nedá ísť!", true);
		}
		else if (príkaz.startsWith("zober "))
		{
			// Principiálne rovnaké získanie parametra ako pri príkaze choď.
			parameter = príkaz.substring(6);

			// Pokus o zobratie predmetu
			if (zober(parameter))
				// V prípade úspechu sa vypíše pozitívna spätná väzba
				vypíšText(zelená, "Zobral si predmet: " +
					parameter + ".", true);
			else
				vypíšText(červená, "Nič také tu nevidíš!", true);
		}
		else if (príkaz.startsWith("polož "))
		{
			// Principiálne rovnaké získanie parametra ako pri príkaze choď.
			parameter = príkaz.substring(6);

			// Pokus o zobratie predmetu
			if (polož(parameter))
				// V prípade úspechu sa vypíše pozitívna spätná väzba
				vypíšText(zelená, "Položil si predmet: " +
					parameter + ".", true);
			else
				vypíšText(červená, "Nič také nemáš!", true);
		}
		else if (príkaz.startsWith("pomoc"))
		{
			vypíšText(zelená, "Pomocník");
			vypíšText(zelená, "K dispozícii sú nasledujúce príkazy: choď, " +
				"zober, polož, pomoc a koniec. Väčšina príkazov vyžaduje " +
				"zadanie parametra. Napríklad: choď ulica, zober kniha " +
				"a pod.", true);
		}
		else if (príkaz.startsWith("koniec"))
		{
			Svet.koniec();
		}
		else
		{
			vypíšText(červená, "Neznámy príkaz!", true);
		}
	}


	/**
	 * Vlastná metóda na výpis textov. Prijíma farbu textu, text a argument
	 * určujúci, či sa má po vypísaní textu vynechať jeden prázdny riadok.
	 */
	public static void vypíšText(Farba farba, String text,
		boolean vynechajRiadok)
	{
		Svet.farbaTextu(farba);
		Svet.vypíšRiadok(text);
		if (vynechajRiadok) Svet.vypíšRiadok();
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale neprijíma argument určujúci, či sa má po vypísaní textu vynechať
	 * jeden prázdny riadok. Správa sa tak, ako keby bolo zadané false.
	 */
	public static void vypíšText(Farba farba, String text)
	{
		vypíšText(farba, text, false);
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale neprijíma argument určujúci farbu textu. Správa sa tak, ako keby
	 * bola zadaná čierna.
	 */
	public static void vypíšText(String text)
	{
		vypíšText(čierna, text, false);
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale namiesto argumentu typu String prijíma argument typu StringBuffer.
	 * To je užitočné, pretože viaceré metódy ďalších tried tohto projektu
	 * skladajú svoj výstup práve do premennej typu StringBuffer.
	 */
	public static void vypíšText(StringBuffer text)
	{
		vypíšText(čierna, text.toString(), false);
	}


	// Vytvorením novej inštancie adventúry sa automaticky spustí
	// konštruktor Adventúra(), ktorý inicializuje novú hru (vytvorí
	// prepojenia medzi miestnosťami a pod.).
	public static void main(String[] args)
	{
		new Adventúra();
	}
}

~

import knižnica.*;

/**
 * Trieda slúži na definíciu rôznych vlastností miestnosti.
 */
public class Miestnosť
{
	// Zoznam dverí vedúcich z tejto miestnosti do ďalších (predvolene je
	// prázdny).
	private final Zoznam<Miestnosť> dvere = new Zoznam<Miestnosť>();

	// Zoznam predmetov, ktoré sú prítomné (viditeľné) v tejto miestnosti
	// (predvolene je prázdny).
	private final Zoznam<Predmet> zoznamPredmetov = new Zoznam<Predmet>();

	// Názov tejto miestnosti – jediný konštruktor tejto triedy vyžaduje
	// jeho zadanie.
	private String názov;

	// Slovný opis miestnosti – jediný konštruktor tejto triedy vyžaduje
	// jeho zadanie.
	private String opis;


	/**
	 * Konštruktor vyžaduje zadanie názvu a slovného opisu miestnosti.
	 */
	public Miestnosť(String názov, String opis)
	{
		priraďNázov(názov);
		priraďOpis(opis);
	}


	/**
	 * Vloženie predmetu do zoznamu predmetov tejto miestnosti.
	 */
	public void vložPredmet(Predmet predmet)
	{
		zoznamPredmetov.pridaj(predmet);
	}

	/**
	 * Odstránenie predmetu zo zoznamu predmetov tejto miestnosti.
	 */
	public void odstráňPredmet(Predmet predmet)
	{
		zoznamPredmetov.odober(predmet);
	}

	/**
	 * Nájdenie predmetu v zozname predmetov podľa názvu.
	 */
	public Predmet hľadajPredmet(String názovPredmetu)
	{
		// Hľadám predmet (pri hľadaní používam metódu porovnajNázov).
		// Keď ho nájdem, vrátim nájdenú inštanciu predmetu.
		for (Predmet predmet : zoznamPredmetov)
			if (predmet.porovnajNázov(názovPredmetu))
				return predmet;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu predmetov, ktoré sú prítomné (viditeľné)
	 * v tejto miestnosti, na obrazovku.
	 */
	public void vypíšZoznamPredmetov()
	{
		if (zoznamPredmetov.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Vidíš tu nasledujúce predmety: " +
				zoznamPredmetov.daj(0).názov());

		for (int i = 1; i < zoznamPredmetov.veľkosť(); ++i)
			zoznam.append(", " + zoznamPredmetov.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Vytvorenie prepojenia s inou miestnosťou, to jest pridanie inštancie
	 * inej miestnosti do vnútorného zoznamu dverí tejto miestnosti. Do tých
	 * miestností, ktoré sú v tomto zozname dverí jestvuje jednosmerný
	 * priechod z tejto miestnosti (čiže hráč môže opustiť túto miestnosť
	 * a vstúpiť do hociktorej miestnosti v zozname dverí; z toho vyplýva,
	 * že v skutočnosti nejestvuje žiadna konkrétna trieda „Dvere.“)
	 * Na to, aby bol priechod obojsmerný, musí byť definované aj spätné
	 * prepojenie.
	 */
	public void prepojMaS(Miestnosť ináMiestnosť)
	{
		dvere.pridaj(ináMiestnosť);
	}

	/**
	 * Nájdenie miestnosti v zozname dverí podľa názvu.
	 */
	public Miestnosť hľadajDvere(String cieľováMiestnosť)
	{
		// Hľadám dvere (pri hľadaní používam metódu porovnajNázov).
		// Keď ich nájdem, vrátim nájdenú inštanciu miestnosti.
		for (Miestnosť cieľ : dvere)
			if (cieľ.porovnajNázov(cieľováMiestnosť))
				return cieľ;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu dverí na obrazovku.
	 */
	public void vypíšZoznamDverí()
	{
		if (dvere.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Môžeš ísť na tieto miesta: " + dvere.daj(0).názov());

		for (int i = 1; i < dvere.veľkosť(); ++i)
			zoznam.append(", " + dvere.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Priradenie nového názvu. Túto metódu používa konštruktor, ale môže
	 * poslúžiť aj na zmenu názvu miestnosti počas hry.
	 */
	public void priraďNázov(String novýNázov)
	{
		názov = novýNázov;
	}

	/**
	 * Táto metóda zistí, či sa názov tejto miestnosti zhoduje so zadaným
	 * reťazcom. To je využiteľné pri hľadaní konkrétnej miestnosti
	 * v zozname miestností. (Riešenie porovnávania názvu s pomocou
	 * samostatnej metódy je užitočné, lebo otvára možnosti ďalšieho
	 * rozširovania modelu: v prípade potreby sa do tejto metódy môže pridať
	 * ďalšie spracovanie názvu na porovnanie, čo sa vďaka tomu, že názov
	 * nebudeme nikdy porovnávať priamo prejaví celoplošne.)
	 */
	public boolean porovnajNázov(String názovNaPorovnanie)
	{
		return názov.equalsIgnoreCase(názovNaPorovnanie);
	}

	/**
	 * Táto metóda vráti názov tejto miestnosti.
	 */
	public String názov()
	{
		return názov;
	}


	/**
	 * Priradenie nového slovného opisu miestnosti. Túto metódu používa
	 * konštruktor a môže poslúžiť na zmenu slovného opisu miestnosti počas
	 * hry.
	 */
	public void priraďOpis(String novýOpis)
	{
		opis = novýOpis;
	}

	/**
	 * Táto metóda slúži na výpis slovného opisu miestnosti na obrazovku.
	 */
	public void vypíšOpis()
	{
		if (null != opis)
			Adventúra.vypíšText(opis);
	}
}

~

// import knižnica.*; // (Zatiaľ priamo nepoužíva žiadnu triedu rámca.)

/**
 * Trieda slúži na definovanie vlastností predmetov v hre.
 */
public class Predmet
{
	// Názov tohto predmetu – jediný konštruktor tejto triedy vyžaduje jeho
	// zadanie.
	private String názov;

	// Slovný opis tohto predmetu – jediný konštruktor tejto triedy vyžaduje
	// jeho zadanie.
	private String opis;

	/**
	 * Konštruktor vyžaduje zadanie názvu a slovného opisu predmetu.
	 */
	public Predmet(String názov, String opis)
	{
		priraďNázov(názov);
		priraďOpis(opis);
	}


	/**
	 * Priradenie nového názvu. Túto metódu používa konštruktor, ale môže
	 * poslúžiť aj na zmenu názvu predmetu počas hry.
	 */
	public void priraďNázov(String novýNázov)
	{
		názov = novýNázov;
	}

	/**
	 * Táto metóda zistí, či sa názov tohto predmetu zhoduje so zadaným
	 * reťazcom. To je využiteľné pri hľadaní konkrétneho predmetu.
	 * (Pozri aj informácie v opise metódy Miestnosť.porovnajNázov.)
	 */
	public boolean porovnajNázov(String názovNaPorovnanie)
	{
		return názov.equalsIgnoreCase(názovNaPorovnanie);
	}

	/**
	 * Táto metóda vráti názov tohto predmetu.
	 */
	public String názov()
	{
		return názov;
	}


	/**
	 * Priradenie nového slovného opisu predmetu. Túto metódu používa
	 * konštruktor a môže poslúžiť aj na zmenu slovného opisu predmetu počas
	 * hry.
	 */
	public void priraďOpis(String novýOpis)
	{
		opis = novýOpis;
	}

	/**
	 * Táto metóda slúži na výpis slovného opisu predmetu na obrazovku.
	 */
	public void vypíšOpis()
	{
		if (null != opis)
			Adventúra.vypíšText(opis);
	}
}

~

import knižnica.*;

/**
 * Trieda slúži na reprezentáciu avatara hráča v hre.
 */
public class Avatar
{
	// Zoznam predmetov, ktoré vlastní avatar (predvolene je prázdny).
	private final Zoznam<Predmet> inventár = new Zoznam<Predmet>();

	// Aktuálna miestnosť, v ktorej sa avatar práve nachádza.
	private Miestnosť kdeSom;

	/**
	 * Konštruktor vyžaduje zadanie začiatočnej pozície avatara, to jest
	 * miestnosti, v ktorej sa hra začína.
	 */
	public Avatar(Miestnosť začiatok)
	{
		kdeSom = začiatok;
	}


	/**
	 * Vloženie predmetu do inventára.
	 */
	public void vložPredmet(Predmet predmet)
	{
		inventár.pridaj(predmet);
	}

	/**
	 * Odstránenie predmetu z inventára.
	 */
	public void odstráňPredmet(Predmet predmet)
	{
		inventár.odober(predmet);
	}

	/**
	 * Nájdenie predmetu v inventári podľa názvu.
	 */
	public Predmet hľadajPredmet(String názovPredmetu)
	{
		// Hľadám predmet (pri hľadaní používam metódu porovnajNázov).
		// Keď ho nájdem, vrátim nájdenú inštanciu.
		for (Predmet predmet : inventár)
			if (predmet.porovnajNázov(názovPredmetu))
				return predmet;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu predmetov (inventára), ktoré avatar
	 * vlastní, na obrazovku.
	 */
	public void vypíšInventár()
	{
		if (inventár.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Vlastníš tieto predmety: " + inventár.daj(0).názov());

		for (int i = 1; i < inventár.veľkosť(); ++i)
			zoznam.append(", " + inventár.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Táto metóda slúži na zmenu polohy avatara, čiže na prechod do inej
	 * miestnosti.
	 */
	public void presuňDo(Miestnosť miestnosť)
	{
		kdeSom = miestnosť;
	}

	/**
	 * Táto metóda vráti aktuálnu polohu avatara, čiže inštanciu miestnosti,
	 * v ktorej sa práve nachádza.
	 */
	public Miestnosť kdeSom()
	{
		return kdeSom;
	}
}

Poznámka: Tento projekt je starší. Bude potrebné ho aktualizovať tak, aby bol kompatibilný s najnovšou verziou programovacieho rámca GRobot. (Stalo sa.)

Na tejto stránke je publikovaný ukážkový projekt pre textovú adventúru. Ide len o návrh malej časti rozhrania pre textovú adventúru. Termín textová adventúra označuje hru komunikujúcu s hráčom výhradne textovou formou. Aj napriek negrafickej orientácii projektu sú v ňom používané niektoré časti skupiny tried grafického robota. otvárané v novom okne
(obvykle ide o externý odkaz) Na vygenerovanie prázdneho projektu odporúčam použiť Generátor projektov BlueJ (dostupný v sekcii Softvér na prevzatie).

  
obrázok 
Triedy projektu. 
 

Zdrojové súbory projektu na prevzatie (bez skupiny tried grafického robota):

 

~

/**
 * Na programovaní textovej adventúry sa dá pekne predviesť podstata
 * objektového modelovania. Budeme pracovať s bežnými pojmami z reálneho
 * sveta, ale namiesto ich reálneho zobrazovania budeme pracovať s textovými
 * opismi, čo je charakteristické pre tento druh hry.
 *
 * Na ukážku je v tomto projekte vytvorených niekoľko jednoduchých tried
 * reprezentujúcich miestnosti, predmety a hráča (avatara).
 *
 * Pri objektovom modelovaní ide o to, aby:
 *   – vlastnosti boli vyjadrené premennými, ktoré sú súkromné,
 *   – ku každej vlastnosti bolo poskytnuté programátorské rozhranie, to jest
 *     definícia jednej alebo viacerých verejných metód, ktoré slúžia na
 *     prácu s touto vlastnosťou,
 *   – rozrhanie sa môže skladať z troch základných „druhov“ metód:
 *      – metódy na zápis vlastností,
 *      – metódy na čítanie vlastností,
 *      – metódy na „inú prácu“ s vlastnosťami (napr. použitie)…
 *
 * Každá trieda sa stará výhradne o svoje „životné funkcie“. Vytvorené
 * inštancie tried „oživujú“ hru. Používajú na to programátorské rozhranie
 * tried, to jest ich verejné metódy.
 */

public class Adventúra extends GRobot
{
	private final static Písmo písmoKonzoly =
		new Písmo("Verdana", Písmo.NORMÁLNE, 14);

	// Definície miestností:
	private final Miestnosť škola = new Miestnosť("škola", "Si v škole.");
	private final Miestnosť ulica = new Miestnosť("ulica", "Si na ulici.");
	private final Miestnosť park = new Miestnosť("park", "Si v parku.");

	// Definície predmetov:
	private final Predmet kniha = new Predmet("kniha", "Toto je kniha.");
	private final Predmet lopta = new Predmet("lopta", "Toto je lopta.");
	private final Predmet list = new Predmet("list", "Toto je list.");

	// Definícia avatara:
	private final Avatar avatar = new Avatar(škola);


	// Konštruktor
	public Adventúra()
	{
		// Priradenie vlastností jednotlivým inštanciám miestností.
		//    V tomto štádiu rozprogramovania to súvisí najmä s prepojením
		//    miestostí navzájom. Názov a opis miestnosti sú priradené priamo
		//    v pri konštrukcii (to jest pri new Miestnosť("…", "…") – pozri
		//    vyššie). Okrem toho tu môžu byť uvedené rôzne prepojenia –
		//    napríklad sú tu vložené predmety do jednotlivých miestností.

		// Škola:
		škola.prepojMaS(ulica);
		škola.vložPredmet(kniha);

		// Ulica:
		ulica.prepojMaS(škola);
		ulica.prepojMaS(park);
		ulica.vložPredmet(lopta);

		// Park:
		park.prepojMaS(ulica);
		park.vložPredmet(list);

		// Definícia obsluhy udalostí s jedinou reakciou spracúvajúcou
		// potvrdenie údajov v príkazovom riadku.
		new ObsluhaUdalostí()
		{
			public void potvrdenieÚdajov() { spracujPríkaz(); }
		};

		//
		svet.písmo(písmoKonzoly);

		// Zobrazenie a aktivácia vstupného riadka.
		svet.neskrývajVstupnýRiadok();
		svet.začniVstup("Zadaj príkaz:");

		// Výpis počiatočného stavu hry.
		vypíšStav();
	}

	/**
	 * Výpis aktuálneho stavu hry.
	 */
	public void vypíšStav()
	{
		// Vypíše sa opis miestnosti, v ktorej sa práve nachádza avatar.
		avatar.kdeSom().vypíšOpis();

		// Vypíše sa zoznam dverí.
		avatar.kdeSom().vypíšZoznamDverí();

		// Výpis predmetov prítomných/viditeľných v miestnosti.
		avatar.kdeSom().vypíšZoznamPredmetov();

		// Výpis zoznamu predmetov v inventári avatara.
		avatar.vypíšInventár();

		// Vynechanie prázdneho riadka.
		svet.vypíšRiadok();
	}


	/**
	 * Pokus o prechod do miestnosti identifikovanej zadaným názvom. Ak
	 * metóda uspeje, vráti true, inak vráti false.
	 */
	public boolean choďDo(String názovMiestnosti)
	{
		// Hľadajú sa dvere:
		Miestnosť prechod = avatar.kdeSom().hľadajDvere(názovMiestnosti);

		if (null != prechod)
		{
			// Zmena miestnosti a vrátenie hodnoty true, ktorá v tomto
			// prípade znamená úspešnosť akcie.
			avatar.presuňDo(prechod);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}

	/**
	 * Pokus o zobratie predmetu identifikovaného zadaným názvom. V prípade,
	 * že je akcia úspešá vráti metóda hodnotu true, inak false.
	 */
	public boolean zober(String názovPredmetu)
	{
		// Hľadá sa predmet v aktuálnej miestnosti:
		Predmet predmet = avatar.kdeSom().hľadajPredmet(názovPredmetu);

		if (null != predmet)
		{
			// Zobratie predmetu pozostáva z dvoch čiastkových akcií:
			// odstránenie predmetu zo zoznamu predmetov aktuálnej miestnosti
			// a vloženie predmetu do inventára avatara. Návratová hodnota
			// true signalizuje, že akcia bola úspešná (to de facto znamená,
			// že predmet bol nájdený v aktuálnej miestnosti, pretože žiadne
			// iné podmienky nie sú v súčasnosti overované).
			avatar.kdeSom().odstráňPredmet(predmet);
			avatar.vložPredmet(predmet);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}

	/**
	 * Pokus o položenie predmetu identifikovaného zadaným názvom. V prípade,
	 * že je akcia úspešá vráti metóda hodnotu true, inak false.
	 */
	public boolean polož(String názovPredmetu)
	{
		// Hľadá sa predmet v inventári avatara:
		Predmet predmet = avatar.hľadajPredmet(názovPredmetu);

		if (null != predmet)
		{
			// Podobne ako zobratie predmetu, aj položenie pozostáva z dvoch
			// čiastkových akcií: odstránenie predmetu zo inventára
			// a vloženie do zoznamu predmetov aktuálnej miestnosti. Opäť,
			// návratová hodnota true signalizuje, že akcia bola úspešná.
			avatar.odstráňPredmet(predmet);
			avatar.kdeSom().vložPredmet(predmet);
			return true;
		}

		// Hodnota false informuje o neúspešnosti vykonania požadovanej akcie.
		return false;
	}


	// Rozpoznanie príkazu a spustenie príslušných akcií.
	public void spracujPríkaz()
	{
		// Definícia reťazca „príkaz“ (s hodnotou prevzatou zo vstupného
		// riadka) a deklarácia reťazca „parameter“.
		String príkaz = svet.prevezmiReťazec(), parameter;

		// Vypísanie príkazu (ozvena) a jeho prevod na malé písmená.
		vypíšText(modrá, príkaz);
		príkaz = príkaz.toLowerCase();

		// Ak zadaný príkaz začína slovom „choď“
		if (príkaz.startsWith("choď "))
		{
			// Prvých päť znakov (to jest aj medzera za slovom) sa preskočí
			// a zvyšok textu sa uloží do premennej „parameter“.
			parameter = príkaz.substring(5);

			// Pokus o prechod do zadanej miestnosti (to jest tej,
			// ktorej meno je v premennej „parameter“).
			if (choďDo(parameter))
			{
				// V prípade úspechu sa vymaže obrazovka
				// a vypíše sa nový stav hry.
				strop.vymažTexty();
				vypíšStav();
			}
			else
				vypíšText(červená, "Odtiaľto sa tam nedá ísť!", true);
		}
		else if (príkaz.startsWith("zober "))
		{
			// Principiálne rovnaké získanie parametra ako pri príkaze choď.
			parameter = príkaz.substring(6);

			// Pokus o zobratie predmetu
			if (zober(parameter))
				// V prípade úspechu sa vypíše pozitívna spätná väzba
				vypíšText(zelená, "Zobral si predmet: " +
					parameter + ".", true);
			else
				vypíšText(červená, "Nič také tu nevidíš!", true);
		}
		else if (príkaz.startsWith("polož "))
		{
			// Principiálne rovnaké získanie parametra ako pri príkaze choď.
			parameter = príkaz.substring(6);

			// Pokus o zobratie predmetu
			if (polož(parameter))
				// V prípade úspechu sa vypíše pozitívna spätná väzba
				vypíšText(zelená, "Položil si predmet: " +
					parameter + ".", true);
			else
				vypíšText(červená, "Nič také nemáš!", true);
		}
		else if (príkaz.startsWith("pomoc"))
		{
			vypíšText(zelená, "Pomocník");
			vypíšText(zelená, "K dispozícii sú nasledujúce príkazy: choď, " +
				"zober, polož, pomoc a koniec. Väčšina príkazov vyžaduje " +
				"zadanie parametra. Napríklad: choď ulica, zober kniha " +
				"a pod.", true);
		}
		else if (príkaz.startsWith("koniec"))
		{
			svet.koniec();
		}
		else
		{
			vypíšText(červená, "Neznámy príkaz!", true);
		}
	}


	/**
	 * Vlastná metóda na výpis textov. Prijíma farbu textu, text a argument
	 * určujúci, či sa má po vypísaní textu vynechať jeden prázdny riadok.
	 */
	public static void vypíšText(Farba farba, String text,
		boolean vynechajRiadok)
	{
		svet.farbaTextu(farba);
		svet.vypíšRiadok(text);
		if (vynechajRiadok) svet.vypíšRiadok();
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale neprijíma argument určujúci, či sa má po vypísaní textu vynechať
	 * jeden prázdny riadok. Správa sa tak, ako keby bolo zadané false.
	 */
	public static void vypíšText(Farba farba, String text)
	{
		vypíšText(farba, text, false);
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale neprijíma argument určujúci farbu textu. Správa sa tak, ako keby
	 * bola zadaná čierna.
	 */
	public static void vypíšText(String text)
	{
		vypíšText(čierna, text, false);
	}

	/**
	 * Vlastná metóda na výpis textov. Správa sa ako predchádzajúca metóda,
	 * ale namiesto argumentu typu String prijíma argument typu StringBuffer.
	 */
	public static void vypíšText(StringBuffer text)
	{
		vypíšText(čierna, text.toString(), false);
	}


	// Vytvorením novej inštancie adventúry sa automaticky spustí
	// konštruktor Adventúra(), ktorý inicializuje novú hru (vytvorí
	// prepojenia medzi miestnosťami a pod.).
	public static void main(String[] args)
	{
		new Adventúra();
	}
}

~

/**
 * Trieda slúži na definíciu rôznych vlastností miestnosti.
 */
public class Miestnosť
{
	// Zoznam dverí vedúcich z tejto miestnosti do ďalších (predvolene je
	// prázdny).
	private final GRobot.Zoznam<Miestnosť> dvere =
		new GRobot.Zoznam<Miestnosť>();

	// Zoznam predmetov, ktoré sú prítomné (viditeľné) v tejto miestnosti
	// (predvolene je prázdny).
	private final GRobot.Zoznam<Predmet> zoznamPredmetov =
		new GRobot.Zoznam<Predmet>();

	// Názov tejto miestnosti – jeho zadanie vyžaduje jediný konštruktor.
	private String názov;

	// Slovný opis miestnosti – jeho zadanie vyžaduje jediný konštruktor.
	private String opis;


	/**
	 * Konštruktor vyžaduje zadanie názvu a slovného opisu miestnosti.
	 */
	public Miestnosť(String názov, String opis)
	{
		priraďNázov(názov);
		priraďOpis(opis);
	}


	/**
	 * Vloženie predmetu do zoznamu.
	 */
	public void vložPredmet(Predmet predmet)
	{
		zoznamPredmetov.pridaj(predmet);
	}

	/**
	 * Odstránenie predmetu zo zoznamu.
	 */
	public void odstráňPredmet(Predmet predmet)
	{
		zoznamPredmetov.odober(predmet);
	}

	/**
	 * Nájdenie predmetu v zozname podľa názvu.
	 */
	public Predmet hľadajPredmet(String názovPredmetu)
	{
		// Hľadám predmet (pri hľadaní používam metódu porovnajNázov).
		// Keď ho nájdem, vrátim nájdenú inštanciu.
		for (Predmet predmet : zoznamPredmetov)
			if (predmet.porovnajNázov(názovPredmetu))
				return predmet;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu predmetov, ktoré sú prítomné (viditeľné)
	 * v tejto miestnosti, na obrazovku.
	 */
	public void vypíšZoznamPredmetov()
	{
		if (zoznamPredmetov.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Vidíš tu nasledujúce predmety: " +
				zoznamPredmetov.daj(0).názov());

		for (int i = 1; i < zoznamPredmetov.veľkosť(); ++i)
			zoznam.append(", " + zoznamPredmetov.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Vytvorenie prepojenia s inou miestnosťou, to jest pridanie inštancie
	 * inej miestnosti do vnútorného zoznamu tejto miestnosti. Tie
	 * miestnosti, ktoré sú v zozname dverí, do tých jestvuje jednosmerný
	 * prechod, čiže hráč môže opustiť túto miestnosť a vstúpiť do hociktorej
	 * miestnosti v zozname dverí. (Z toho vyplýva, že v skutočnosti
	 * nejestvuje žiadna konkrétna trieda „Dvere“.) Na to, aby bol prechod
	 * obojsmerný, musí byť definované aj spätné prepojenie.
	 */
	public void prepojMaS(Miestnosť ináMiestnosť)
	{
		dvere.pridaj(ináMiestnosť);
	}

	/**
	 * Nájdenie miestnosti v zozname dverí podľa názvu.
	 */
	public Miestnosť hľadajDvere(String cieľováMiestnosť)
	{
		// Hľadám dvere (pri hľadaní používam metódu porovnajNázov).
		// Keď ich nájdem, vrátim nájdenú inštanciu.
		for (Miestnosť cieľ : dvere)
			if (cieľ.porovnajNázov(cieľováMiestnosť))
				return cieľ;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu dverí na obrazovku.
	 */
	public void vypíšZoznamDverí()
	{
		if (dvere.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Môžeš ísť na tieto miesta: " + dvere.daj(0).názov());

		for (int i = 1; i < dvere.veľkosť(); ++i)
			zoznam.append(", " + dvere.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Priradenie nového názvu. Túto metódu používa konštruktor, ale môže
	 * poslúžiť aj na zmenu názvu miestnosti počas hry.
	 */
	public void priraďNázov(String novýNázov)
	{
		názov = novýNázov;
	}

	/**
	 * Metóda zistí, či sa názov tejto miestnosti zhoduje so zadaným
	 * reťazcom. To je využiteľné pri hľadaní konkrétnej miestnosti
	 * v zozname miestností.
	 */
	public boolean porovnajNázov(String názovNaPorovnanie)
	{
		return názov.equalsIgnoreCase(názovNaPorovnanie);
	}

	/**
	 * Metóda vráti názov tejto miestnosti.
	 */
	public String názov()
	{
		return názov;
	}


	/**
	 * Priradenie nového slovného opisu miestnosti. Túto metódu používa
	 * konštruktor a môže poslúžiť na zmenu slovného opisu miestnosti počas
	 * hry.
	 */
	public void priraďOpis(String novýOpis)
	{
		opis = novýOpis;
	}

	/**
	 * Táto metóda slúži na výpis slovného opisu miestnosti na obrazovku.
	 */
	public void vypíšOpis()
	{
		if (null != opis)
			Adventúra.vypíšText(opis);
	}
}

~

/**
 * Trieda slúži na definovanie vlastností predmetov v hre.
 */
public class Predmet
{
	// Názov tohto predmetu – jeho zadanie vyžaduje jediný konštruktor.
	private String názov;

	// Slovný opis tohto predmetu – jeho zadanie vyžaduje jediný konštruktor.
	private String opis;

	/**
	 * Konštruktor vyžaduje zadanie názvu a slovného opisu predmetu.
	 */
	public Predmet(String názov, String opis)
	{
		priraďNázov(názov);
		priraďOpis(opis);
	}


	/**
	 * Priradenie nového názvu. Túto metódu používa konštruktor, ale môže
	 * poslúžiť aj na zmenu názvu predmetu počas hry.
	 */
	public void priraďNázov(String novýNázov)
	{
		názov = novýNázov;
	}

	/**
	 * Metóda zistí, či sa názov tohto predmetu zhoduje so zadaným
	 * reťazcom. To je využiteľné pri hľadaní konkrétneho predmetu.
	 */
	public boolean porovnajNázov(String názovNaPorovnanie)
	{
		return názov.equalsIgnoreCase(názovNaPorovnanie);
	}

	/**
	 * Metóda vráti názov tohto predmetu.
	 */
	public String názov()
	{
		return názov;
	}


	/**
	 * Priradenie nového slovného opisu predmetu. Túto metódu používa
	 * konštruktor a môže poslúžiť na zmenu slovného opisu predmetu počas
	 * hry.
	 */
	public void priraďOpis(String novýOpis)
	{
		opis = novýOpis;
	}

	/**
	 * Táto metóda slúži na výpis slovného opisu predmetu na obrazovku.
	 */
	public void vypíšOpis()
	{
		if (null != opis)
			Adventúra.vypíšText(opis);
	}
}

~

/**
 * Trieda slúži na reprezentáciu avatara hráča v hre.
 */
public class Avatar
{
	// Zoznam predmetov, ktoré vlastní avatar (predvolene je prázdny).
	private final GRobot.Zoznam<Predmet> inventár =
		new GRobot.Zoznam<Predmet>();

	// Aktuálna miestnosť, v ktorej sa avatar nachádza.
	private Miestnosť kdeSom;

	/**
	 * Konštruktor vyžaduje zadanie začiatočnej pozície avatara, to jest
	 * miestnosti, v ktorej sa hra začína.
	 */
	public Avatar(Miestnosť začiatok)
	{
		kdeSom = začiatok;
	}


	/**
	 * Vloženie predmetu do inventára.
	 */
	public void vložPredmet(Predmet predmet)
	{
		inventár.pridaj(predmet);
	}

	/**
	 * Odstránenie predmetu z inventára.
	 */
	public void odstráňPredmet(Predmet predmet)
	{
		inventár.odober(predmet);
	}

	/**
	 * Nájdenie predmetu v inventári podľa názvu.
	 */
	public Predmet hľadajPredmet(String názovPredmetu)
	{
		// Hľadám predmet (pri hľadaní používam metódu porovnajNázov).
		// Keď ho nájdem, vrátim nájdenú inštanciu.
		for (Predmet predmet : inventár)
			if (predmet.porovnajNázov(názovPredmetu))
				return predmet;

		// Inak vrátim null.
		return null;
	}

	/**
	 * Zostavenie a výpis zoznamu predmetov (inventára), ktoré avatar
	 * vlastní, na obrazovku.
	 */
	public void vypíšInventár()
	{
		if (inventár.veľkosť() <= 0) return;

		StringBuffer zoznam = new StringBuffer(
			"Vlastníš tieto predmety: " + inventár.daj(0).názov());

		for (int i = 1; i < inventár.veľkosť(); ++i)
			zoznam.append(", " + inventár.daj(i).názov());

		zoznam.append(".");
		Adventúra.vypíšText(zoznam);
	}


	/**
	 * Metóda slúži na zmenu polohy avatara, čiže na prechod do inej
	 * miestnosti.
	 */
	public void presuňDo(Miestnosť miestnosť)
	{
		kdeSom = miestnosť;
	}

	/**
	 * Metóda vráti aktuálnu polohu avatara, čiže inštanciu miestnosti,
	 * v ktorej sa nachádza.
	 */
	public Miestnosť kdeSom()
	{
		return kdeSom;
	}
}