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

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

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

Dátum: 19. 4. 2020, pred štyrmi rokmi, aktualizované: 4. 9. 2021, pred tromi rokmi

V tomto článku sú zverejnené krátke ukážky kódov. (Časom môžu pribúdať ďalšie.)

obrázok

 

Stručný opis

Program vygeneruje tridsať iskričiek, ktoré sa otáčajú a „trbliecu“ (menia náhodne farbu). Každá iskrička sa resetne (zmení polohu, smer, farbu, rýchlosť otáčania…) po kliknutí myšou na ľubovoľné miesto na ploche. (Čiže celá scéna sa po kliknutí myšou resetne.)

V triede Iskrička (ktorá je vnorenou triedou (angl. nested class) triedy Iskričky si môžete všimnúť jednu zvláštnosť. Za definíciou atribútu zmena je blok, ktorý „k ničomu nepatrí“ a obsahuje jediný príkaz (klik();). Toto je takzvaný anonymný blok a v tomto prípade je to zároveň inicializačný blok. Vykoná sa pri vzniku inštancie. V podstate tvorí (v tomto prípade) doplnok ku konštruktoru (ak by ho trieda mala, čo nie je tento prípad, čiže môžeme povedať, že v tomto prípade tento blok nahrádza konštruktor).

Pozor, nie každý anonymný blok je inicializačný! Len tie anonymné bloky, ktoré sú priamo v tele triedy sú inicializačné (vykonávajú sa pri konštrukcii). Ak by bol anonymný blok v tele metódy, tak plní inú úlohu: obmedzuje platnosť lokálnych premenných. Akákoľvek premenná, ktorá je definovaná (prípadne deklarovaná) v rámci anonymného bloku (aj toho inicializačného) je platná len v rámci tohto bloku. (Poznámka: O oblasti platnosti premenných tiež niekedy hovoríme aj ako o ich viditeľnosti; angl. visibility; príklad: the variable is visible within a scope. V tom kontexte sa v angličtine tiež hovorí o „oblasti alebo (poli) pôsobnosti (prípadne obzore)“ premenných – scope; variable scope.)

~

import knižnica.GRobot;
import static knižnica.Svet.*;

public class Iskričky extends GRobot
{
	private class Iskrička extends GRobot
	{
		private int zmena = 1; { klik(); }

		@Override public void klik()
		{
			farba(biela);
			náhodnáPoloha();
			náhodnýSmer();
			otáčajTvar(náhodnéReálneČíslo(10, 15));
			if (0 == náhodnéCeléČíslo() % 2)
				otáčajTvar(-otáčanieTvaru());
		}

		@Override public void kresliTvar()
		{
			odskoč();

			for (int i = 0; i < 4; ++i)
			{
				dopredu(veľkosť() / 2);
				choďPoOblúku(90, veľkosť() / 2);
				dopredu(veľkosť() / 2);
				vpravo(180);
			}
		}

		@Override public void aktivita()
		{
			náhodnáFarba();
			veľkosť(veľkosť() + zmena);
			if (veľkosť() > 15) zmena = -1;
			else if (veľkosť() < 10) zmena = 1;
		}
	}

	private Iskričky()
	{
		super(400, 400);
		farbaPozadia(tmavomodrá.tmavšia(0.4));
		for (int i = 0; i < 30; ++i) new Iskrička();
		skry();
	}

	public static void main(String... args)
	{
		použiKonfiguráciu("Iskričky.cfg");
		new Iskričky();
	}
}

obrázok

 

Stručný opis

Klikaním na plochu sa cyklicky mení kreslený tvar. Zmenu určuje premenná tvar, podľa ktorej sa volí metóda na kreslenie a zároveň aj metóda na detekciu prítomnosti myši v tvare. Ak je myš v tvare, vypíše sa v ňom text „Ahoj, svet!“

Tento príklad tiež ukazuje funkčnosť menej známej (i keď historicky jednej z najstarších) vlastnosti zvanej pôsobisko. Je to obdĺžniková (prípadne štvorcová, ak sú strany rovnaké) oblasť, v ktorej sa robot pohyboval (do ktorej zasiahol) od posledného resetu príkazom domov. Táto vlastnosť môže poslúžiť napríklad na testovacie účely.

~

import knižnica.*;
import static knižnica.Svet.*;

public class RotujúceTvary extends GRobot
{
	private int tvar = 2;

	private RotujúceTvary()
	{
		super(500, 500);
		zbaľ();

		// Nastavenie vlastností:
		farba(100, 0, 0, 50);
		kresliPôsobisko();
		farbaPozadia(240, 255, 240);
		veľkosť(30);
		pomer(2);
	}

	// Ďalší tvar a reset pôsobiska:
	@Override public void klik() { ++tvar; domov(); }

	// Aktualizácia:
	@Override public void pohybMyši() { prekresli(); }

	@Override public void kresliTvar()
	{
		// Rozšíri pôsobisko:
		skočNaMyš();
		bod();

		// Návrat domov (ktorý neresetuje pôsobisko) a otočenie na myš:
		domov();
		otočNaMyš();

		// Upraví veľkosť pri symetrických tvaroch:
		if (0 == ((tvar / 2) % 5) % 2)
			veľkosť(2 * veľkosť());

		for (double d = 10; d >= 1; d /= 3)
		{
			hrúbkaPera(d);

			// Nakreslí tvar podľa premennej „tvar“:
			switch (tvar % 10)
			{
			case 0: kružnica(); break;
			case 1: kruh(); break;
			case 2: elipsa(); break;
			case 3: vyplňElipsu(); break;
			case 4: štvorec(); break;
			case 5: vyplňŠtvorec(); break;
			case 6: obdĺžnik(); break;
			case 7: vyplňObdĺžnik(); break;
			case 8: hviezda(); break;
			case 9: vyplňHviezdu(); break;
			}
		}

		// Vpísanie textu, ak je myš v tvare:
		switch ((tvar / 2) % 5)
		{
		case 0: if (myšVKruhu()) text("Ahoj, svet!"); break;
		case 1: if (myšVElipse()) text("Ahoj, svet!"); break;
		case 2: if (myšVoŠtvorci()) text("Ahoj, svet!"); break;
		case 3: if (myšVObdĺžniku()) text("Ahoj, svet!"); break;
		case 4: if (myšVHviezde()) text("Ahoj, svet!"); break;
		}
	}

	public static void main(String[] args)
	{
		nekresli();
		new RotujúceTvary();
		kresli();
	}
}

obrázok

 

Stručný opis

Tento príklad sa podobá na rotujúce tvary, ale zaoberá sa mierne inými záležitosťami.

Pri pohybe myšou sa v strede plátna otáča vopred vygenerovaný obrázok (jeho generovanie (nakreslenie jeho obsahu) je uzavreté do metódy vyrobObrázok). Poloha myši je zvýraznená hrubou bodkou a po kliknutí ľubovoľného tlačidla myši, okrem stredného, sa začne vstup (vstupným riadkom v spodnej časti okna). Odozvou na potvrdenie vstupu je zobrazenie prostého echa (ozveny zadaného reťazca) v oznamovacom dialógu.

Kliknutie stredného tlačidla myši prekreslí scénu a pípne.

~

import knižnica.*;
import static knižnica.Svet.*;
import static knižnica.ÚdajeUdalostí.*;

public class RotujúciObrázok extends GRobot
{
	private Obrázok obrázok;

	private RotujúciObrázok()
	{
		farba(100, 0, 0, 50);
		farbaPozadia(100, 100, 255);

		skry();
		vyrobObrázok();
		kresliObrázok();

		new ObsluhaUdalostí()
		{
			@Override public void potvrdenieÚdajov()
			{
				správa(prevezmiReťazec());
			}

			@Override public void klik()
			{
				if (tlačidloMyši(STREDNÉ))
				{
					prekresli();
					pípni();
					return;
				}

				if (!začniVstup("Správa:")) pípni();
				kresliObrázok();
			}

			@Override public void pohybMyši() { kresliObrázok(); }
			@Override public void zadanieZnaku() { pípni(); }
		};
	}

	private void vyrobObrázok()
	{
		obrázok = new Obrázok(100, 50);
		kresliDoObrázka(obrázok);
		obrázok.vyplň(0, 200, 200, 200);
		hrúbkaPera(10);
		pečiatka();
		text("Ahoj, svet!");
		kresliNaPodlahu();
	}

	private void kresliObrázok()
	{
		podlaha.vymaž();

		skočNaMyš();
		bod();

		domov();
		otočNaMyš();
		obrázok(obrázok);
	}

	public static void main(String[] args)
	{
		nekresli();
		new RotujúciObrázok();
		kresli();
	}
}

obrázok

obrázok

 

Stručný opis

Konštruktor spúšťa dve metódy robota: uhlováRýchlosť otvárané v novom okne
(obvykle ide o externý odkaz)rozbehniSa otvárané v novom okne
(obvykle ide o externý odkaz). Prvá nastaví uhlovú rýchlosť (to jest rýchlosť otáčania) robota na 15 (to jest 15° doľava za jeden tik). Druhá nastavuje dve hodnoty naraz: zrýchlenie (0,5 bodu za tik) a maximálnu rýchlosť (80 bodov za tik).

Tieto nastavenia robota spôsobia, že sa začne postupne rozbiehať vpred počas otáčania sa konštantnou rýchlosťou, pričom (keďže má spustené pero) kreslí čiaru v tvare špirály. Keďže má nastavenú maximálnu rýchlosť, jeho dráha sa po čase stabilizuje na kružnici s určitým polomerom. Kreslenie špirálovej dráhy sa reštartuje klikaním myšou, pričom po prvom kliknutí sa robot zastaví, po ďalšom opäť rozbehne a tak ďalej, čo spôsobí efekt „vetvenia“ špirál.

~

import knižnica.GRobot;
import knižnica.ObsluhaUdalostí;
import static knižnica.Svet.*;

public class ŠpirálováDráha extends GRobot
{
	private ŠpirálováDráha()
	{
		uhlováRýchlosť(15);
		rozbehniSa(0.5, 80);
		zbaľ();
	}

	@Override public void tik()
	{
		if (0 == náhodnéCeléČíslo(10))
			kružnica(5);
	}

	@Override public void klik()
	{
		if (aktívny())
			zastav();
		else
			rozbehniSa();
	}

	public static void main(String[] args)
	{
		new ŠpirálováDráha();
	}
}

obrázok

 

Stručný opis

Špirálnici fungujú principiálne rovnako ako robot v predchádzajúcej ukážke – špirálová dráha. Každý špirálnik sa dá aktivovať a deaktivovať kliknutím na neho. Špirálnik sa po prekročení určitej hraničnej rýchlosti automaticky zastaví a presunie na novú lokalitu.

~

import knižnica.GRobot;
import knižnica.ObsluhaUdalostí;
import knižnica.Zoznam;
import static knižnica.Svet.*;

public class Špirálnici extends GRobot
{
	private static class Špirálnik extends GRobot
	{
		private Špirálnik()
		{
			ohranič();
			náhodnáPoloha();
			náhodnýSmer();

			zrýchlenie(0.1, false);
			if (0 == náhodnéCeléČíslo(0, 1))
				uhlováRýchlosť(náhodnéReálneČíslo(10, 20), false);
			else
				uhlováRýchlosť(náhodnéReálneČíslo(-10, -20), false);
		}

		@Override public void klik()
		{
			if (myšVKruhu())
			{
				if (aktívny())
					deaktivuj();
				else
					aktivuj();
			}
		}

		@Override public void aktivita()
		{
			if (rýchlosť() > 20)
			{
				náhodnáPoloha();
				zastav();
			}
		}
	}


	public static void main(String[] args)
	{
		for (int i = 0; i < 10; ++i) new Špirálnik();
		zbaľ();
	}
}

obrázok

 

Stručný opis

Na ploche sa zobrazujú krúžky, pričom trvanie zobrazenia je vymedzené určitým časovým limitom, v ktorom má používateľ stihnúť do krúžku kliknúť. Ak to nestihne, zaznie zvuk pípnutia. Ak sa netrafí, zaznie zvuk pípnutia. Skóre nie je rátané.

~

import knižnica.GRobot;
import knižnica.Svet;
import knižnica.ÚdajeUdalostí;

public class KlikacíKrúžok extends GRobot
{
	// Časový limit zobrazenia krúžku.
	private int limit;

	// Konštruktor.
	private KlikacíKrúžok()
	{
		hrúbkaČiary(10);
		farba(zelená);
		vlastnýTvar(r -> r.krúžok()); // (kreslenie vlastného tvaru)

		novýKrúžok();

		Svet.zbaľ();
		Svet.spustiČasovač();
	}

	/*// Alternatíva k príkazu vlastnýTvar v konštruktore. Oplatilo by sa
	// ju použiť, keby bol tvar kreslenia zložitejší, aby bol zdrojový kód
	// prehľadnejší.
	@Override public void kresliTvar()
	{
		krúžok();
	}*/

	// Metóda resetujúca reprezentatívne vlastnosti krúžku: poloha, veľkosť
	// a časový limit. Je volaná v konštruktore, pri správnom kliknutí a po
	// uplynutí časového limitu.
	public void novýKrúžok()
	{
		náhodnáPoloha();
		veľkosť(Svet.náhodnéCeléČíslo(30, 60));
		limit = (int)Svet.náhodnéCeléČíslo(25, 75);
	}


	// Reakcia na kliknutie.
	@Override public void klik()
	{
		if (ÚdajeUdalostí.tlačidloMyši(ĽAVÉ))
		{
			if (vzdialenosťOdMyši() < veľkosť())
				novýKrúžok();
			else
				Svet.pípni();
		}
	}

	// Reakcia časovača.
	@Override public void tik()
	{
		if (--limit <= 0)
		{
			Svet.pípni();
			novýKrúžok();
		}
	}


	// (Hlavná metóda – vstupný bod programu.)
	public static void main(String[] args)
	{
		new KlikacíKrúžok();
	}
}

obrázok

 

Stručný opis

Minimálny kód(*) ukazujúci alternatívny (takpovediac „algoritmický“) spôsob kreslenia štvorca. (Keby nejestvovala metóda štvorec otvárané v novom okne
(obvykle ide o externý odkaz).)


(*) Poznámka: Nie je to celkom minimálny kód, ale v záujme čitateľnosti už nebol ďalej skracovaný. Príklad by fungoval rovnako dobre, keby sme vynechali piaty riadok (private Štvorec()). Konštruktor by sa tým zmenil na anonymný blok (pozri príklad Iskričky), ktorý by v tomto prípade zároveň plnil úlohu inicializačného bloku.)

~

import knižnica.GRobot;

public class Štvorec extends GRobot
{
	private Štvorec()
	{
		for (int i = 0; i < 4; ++i)
		{
			vpred(100);
			vpravo(90);
		}
	}

	public static void main(String[] args)
	{
		new Štvorec();
	}
}

obrázok

 

Stručný opis

Minimálny kód(*) ukazujúci jeden zo spôsobov nakreslenia špirály (resp. polygónu pripomínajúceho špirálu).


(*) Poznámka: Nie je to celkom minimálny kód. Platí to isté ako pri príklade Štvorec. Plus, aby bolo špirálu lepšie vidieť bez nevyhnutnosti ručného zväčšovania okna, sú do kódu pridané dva nadbytočné riadky: druhý, staticky importujúci Svet a osemnásty, „baliaci“ okno sveta = meniaci jeho veľkosť tak, aby sa do neho zmestilo celé plátno. Veľkosť okna sa automaticky zmení hneď po dokreslení špirály. Príkaz zbaľ() nemá zmysel umiestniť pred príkaz new Špirála(), pretože svet v tom čase ešte nejestvuje.

~

import knižnica.GRobot;
import static knižnica.Svet.*;

public class Špirála extends GRobot
{
	private Špirála()
	{
		for (int i = 0; i < 100; ++i)
		{
			vpred(i);
			vpravo(20);
		}
	}

	public static void main(String[] args)
	{
		new Špirála();
		zbaľ();
	}
}

obrázok

 

Stručný opis

Nadviazenie na príklad Štvorec. Príklad je prakticky identický a ukazuje ako sa dá zopár drobnými zmenami docieliť diametrálne odlišný výsledok. (Pozri tiež príklad Špirála.)

~

import knižnica.GRobot;

public class Hviezda extends GRobot
{
	private Hviezda()
	{
		for (int i = 0; i < 100; ++i)
		{
			vpred(200);
			vpravo(175);
		}
	}

	public static void main(String[] args)
	{
		new Hviezda();
	}
}

obrázok

 

Stručný opis

Táto ukážka predvádza, ako nakresliť trojuholník podľa zadaných dĺžok strán trojuholníka.

~

import knižnica.Bod;
import knižnica.GRobot;
import static knižnica.Svet.*;

public class Trojuholník extends GRobot
{
	// Mierka:
	private double m = 50;

	// Vzdialenosť textového označenia vrcholov od kresby trojuholníka:
	private double d = 20;

	// Dĺžky strán trojuholníka:
	private double a = 7, b = 6, c = 5;


	// Vypočítané relatívne súradnice bodu A (násobené mierkou):
	private double x = 0, y = 0;

	// Súradnice posunutia obrázka (o polovicu výšky a šírky v mierke):
	private double dx = 0, dy = 0;

	// Na oddelenie hodnôt (súradníc), ktoré sú používané na kreslenie od
	// aktuálnych hodnôt dĺžok strán a mierky je potrebné vypočítať dĺžku
	// strany a prenásobenú mierkou:
	private double ma = 0;

	// Na mierne urýchlenie kreslenia je vhodné vypočítať rozdiel medzi
	// dĺžkou strany a (čo je vlastne x-ová súradnica bodu C) a x-ovej
	// súradnice bodu A (prenásobenú mierkou):
	private double Δxa = 0;


	// Príznak kreslenia:
	private boolean kresli = false;


	// Konštruktor.
	private Trojuholník()
	{
		prepočítaj();
		hrúbkaČiary(2);
	}


	// Pomocná metóda prepočítavajúca všetky údaje potrebné na kreslenie.
	// Keby sa zmení hodnota mierky alebo dĺžka niektorej zo strán, musela
	// by byť spustená táto metóda, aby sa zmeny prejavili aj v kresbe.
	private void prepočítaj()
	{
		// Testujeme zostrojiteľnosť trojuholníka:
		if (kresli = a + b > c && b + c > a && a + c > b)
		{
			// Pomocné údaje k výpočtu priesečníka strán b a c (čo je bod A):
			double o = a * a - b * b + c * c;
			double p = 4 * a * a;
	
			// Výpočet súradníc bodu A (relatívnych):
			x = o / (2 * a);
			y = Math.sqrt((p * c * c - o * o) / p);
	
			// (Zdroj: mathworld.wolfram.com/Circle-CircleIntersection.html
			// s nasledujúcimi substitúciami: d z riešenia na mathworld je
			// naše a, r je naše b a R je naše c.)
	
			// Dĺžka strany a prenásobená mierkou:
			ma = a * m;
	
			// Prenásobenie súradníc bodu A mierkou:
			x *= m;
			y *= m;
	
			// Rozdiel x-ových súradníc bodov A a C (v mierke):
			Δxa = x - ma;
	
			// Výpočet posunutia tak, aby bol trojuholník vystredený:
			dx = ma / -2;
			dy = y  / -2;
		}
		else
		{
			// Ak trojuholník nie je zostrojiteľný, tak všetko vynulujeme
			// (nemuseli by sme to robiť, pretože v takom prípade je príznak
			// kreslenia nastavený na false):
			x = y = dx = dy = Δxa = 0;
		}
	}


	// Reakcia kreslenia.
	@Override public void kresliTvar()
	{
		if (kresli)
		{
			Bod A, B, C, D;
			D = poloha();
			preskoč(dx, dy);
			B = poloha();
			posuň(ma, 0);
			C = poloha();
			posuň(Δxa, y);
			A = poloha();
			posuň(-x, -y);
	
			skočNa(A);
			otočNa(D);
			odskoč(d);
			uhol(SEVER);
			text("A");
	
			skočNa(B);
			otočNa(D);
			odskoč(d);
			uhol(SEVER);
			text("B");
	
			skočNa(C);
			otočNa(D);
			odskoč(d);
			uhol(SEVER);
			text("C");
		}
	}


	public static void main(String[] args)
	{
		nekresli();
		new Trojuholník();
		kresli();
	}
}

obrázok

 

~

import knižnica.GRobot;
import static knižnica.Svet.*;

public class Mitsubishi extends GRobot
{
	private Mitsubishi()
	{
		super(200, 200);
		zbaľ(); vystreď();

		farba(červená);
		vpravo(30);
		zdvihniPero();
		začniCestu();

		for (int i = 0; i < 3; ++i)
		{
			vpred(50);
			vľavo(60);
			vpred(50);
			vľavo(120);
			vpred(50);
			vľavo(60);
			vpred(50);
		}

		vyplňCestu();
		skry();

		farba(čierna);
		vľavo(30);
		dozadu(70);
		text("Mitsubishi");
	}

	public static void main(String[] args)
	{
		new Mitsubishi();
	}
}

Zvoľte ukážku…