Programátoři z pekel zde za šat a stravu programují čipová pseuda. Nyní s favicon!

Programujeme v BASICu: Seriózní programy (2)

I přes záplavy a následná vedra jsem se konečně dostal k tomu, dovést do konce druhý díl. Zapněte Spectra, nažhavte emulátory, tady je.

Čím začít seriózní programy, než něčím výukovým? Sinclairovy počítače, narozdíl od těch od Atari či Commodore, totiž nebyly navrhovány jako hračky určené pro domácí gamesení, ale jako seriózní výukové stroje. Školní a výukové nasazení se tak vysloveně předpokládalo, byť bylo nakonec díky BBC Computer Literacy Project asi nebylo tak slavné, jak se čekalo.


Jak skloubit vzdělávání a geografické algoritmy, které jsem minule předvedl? Nevím jak vám, ale mě se okamžitě vybavila slepá mapa a hledání zadaných měst. Následující program ukazuje ve slepé mapě postupně deset měst náhodně vybraných z třiceti nahraných z pásky a dává uživateli na výběr ze tří možností. Dvě další města jsou pro zvýšení obtížnosti vybrána tak, že se jedná o nejbližší města k tomu správnému. Pojďme si projít kód po blocích, které spolu souvisí:


10 DIM p(2,135): DIM c(2,30): DIM n$(30,18): LET ps=135: LET cs=30: LET lc=10: LET cf=0
20 LOAD "p" DATA p(): LOAD "n" DATA n$(): LOAD "c" DATA c()
30 DIM m$(3,18): DIM m(2,2)
40 RANDOMIZE
50 BORDER 7: PAPER 7: INK 0: CLS
60 PRINT FLASH 1;AT 10, 9;"Cekejte prosim"
70 GO SUB 1100
80 GO SUB 1200

V první části programu se deklarují patřičná pole pro body hranic na slepé mapě (p), body měst (c) a názvy měst (n). Zároveň se do příslušných proměnných naplní počet bodů hranic (ps), počet měst (cs) a počet měst která se ve hře budou hádat (lc). Města se nahrají z pásky (.tap soubor je ke stažení v závěru článku), deklarují se pracovní pole použitá v dalších blocích, inicializuje se generátor náhodných čísel, připraví se obrazovka a zavolá se podprogram na řádku 1100, který vykreslí slepou mapu.

Prvních sedm řádků se v celém programu volá pouze jednou, nahrávání dat i hledání rohů slepé mapy není třeba provádět opakovaně.


100 REM Hadani mesta
110 LET score=0
120 FOR l=1 TO lc
130 PRINT AT 19,0;,,; FLASH 1;"Generuji otazku c. ";l; FLASH 0;,,,
140 LET m(1,1)=999: LET m(1,2)=999
150 LET s=INT (RND*cs)+1
160 LET t=INT (RND*3)+1
170 LET m$(t)=n$(s)
180 FOR i=1 TO cs
190 IF i=s THEN GO TO 230
200 LET dst=SQR ((c(1,i)-c(1,s))*(c(1,i)-c(1,s)) + (c(2,i)-c(2,s))*(c(2,i)-c(2,s)))
210 IF dst < m(1,1) THEN LET m(1,2)=m(1,1): LET m(2,2)=m(2,1): LET m(1,1)=dst: LET m(2,1)=i: GO TO 230 220 IF dst < m(1,2) THEN LET m(1,2)=dst: LET m(2,2)=i 230 NEXT i 240 LET x=1 250 FOR i=1 TO 3 260 IF i<>t THEN LET m$(i)=n$(m(2,x)): LET x=x+1
270 NEXT i
280 PLOT INT 1+(c(2,s)-xmin)*rx,INT 24+(c(1,s)-ymin)*ry: DRAW 2,0 : DRAW 0,2: DRAW -2,0: DRAW 0,-2

V druhé části programu je náhodně vybráno město, které se bude hádat (řádek 150) a toto město se zařadí na náhoné místo v tříprvkovém poli m$, které představuje ony tři možnosti, z nichž uživatel volí (160, 170). Poté se hledají dvě další nejbliží města prostřednictvím dvojrozměrného pole m, v němž první položka označuje vzdálenost a druhá město (index v seznamu měst m$). Vzdálenost je počítána pomocí obyčejné Pythagorovy věty, použití sofistikovanější metody pro pouhé řazení dle vzdálenosti není nutné, navíc by hledání neúměrně prodloužilo. I tento kód trvá pro nalezení dvou měst mezi devětadvaceti zhruba sedm sekund, když jsem zkusil hledat mezi stovkou měst, bylo to již skoro půl minuty.

Nalezená města jsou posléze zapsána do pole m$ a na mapu je zakreslen čtvereček na poloze hádaného města.


300 FOR i=1 TO 3: PRINT AT 18+i,0;i;" - ";m$(i),: NEXT i
310 LET i$=INKEY$
320 IF CODE i$ <49 OR CODE i$ >51 THEN GO TO 310
330 IF m$(VAL i$)=n$(s) THEN BORDER 4: PAUSE 25: BORDER 7: LET score=score+1: G
O TO 350
340 BORDER 2: PAUSE 25: BORDER 7
350 OVER 1: DRAW 2,0 : DRAW 0,2: DRAW -2,0: DRAW 0,-2: OVER 0
360 NEXT l
400 CLS
410 PRINT AT 8,11; FLASH 1;"Konec hry"
420 PRINT AT 11,0;"Vase uspesnost: ";score/lc*100;"%"
430 PRINT AT 21,0;"Chcete to zkusit znovu [a/n]?";
440 LET i$=INKEY$
450 IF i$="a" OR i$="A" THEN GO TO 80
460 IF i$="n" OR i$="N" THEN GO TO 9999
470 GO TO 440

Třetí blok programu řeší interakci s uživatelem. Jsou v něm vypsány tři možnosti, z nichž se jedna volí stiskem klávesy s příslušným číslem (řádky 300 až 320). Pokud je město uhodnuto správně, blikne border zeleně a zvýší se dosažené skóre, v opačném případě blikne červeně.

Ukázka z programu

Cyklus hádání se opakuje tolikrát, kolikrát určuje proměnná lc, následně se vyhodnotí procentuální úspěšnost a uživateli je nabídnuta možnost začít znovu.


1100 LET ymin=p(1,1): LET xmin=p(2,1): LET ymax=ymin: LET xmax=xmin
1110 FOR a=1 TO ps
1120 IF p(1,a) > ymax THEN LET ymax=p(1,a)
1130 IF p(2,a) > xmax THEN LET xmax=p(2,a)
1140 IF p(1,a) < ymin THEN LET ymin=p(1,a) 1150 IF p(2,a) < xmin THEN LET xmin=p(2,a) 1160 NEXT a 1170 LET rx=xmax-xmin: LET ry=ymax-ymin 1180 LET rx=253/rx: LET ry=151/ry 1190 RETURN 1200 CLS 1210 FOR a=1 TO ps-1 1220 PLOT 1+(p(2,a)-xmin)*rx, 24+(p(1,a)-ymin)*ry 1230 DRAW rx*(p(2,a+1)-p(2,a)),ry*(p(1,a+1)-p(1,a)) 1240 NEXT a 1250 RETURN

Poslední část je v podstatě drobně upravený kód z minula. Řádky 1100 až 1190 se starají o hledání rohů mapy a stačí je zavolat jednou po načtení dat z pásky. Řádky 1200 až 1250 kreslí samotnou mapu.

Za zmínku stojí řádky 1180 a 1220, kde jsou změny v souvislosti s y-souřadnicí, respektive tím, že se vykreslovací prostor pro mapu zmenšil o tři řádky, v nichž probíhá konverzace s uživatelem. První uvedený řádek definuje prostor pro osu y na 151 bodů,řádek 1220 pak posouvá kreslení mapy o 24 pixelů nahoru a tím nechává tři volné textové řádky ve spodní části obrazovky.


Program je jistě možné vylepšit, například v případě špatné odpovědi by mohl uživateli sdělit správnou odpověď. To ale nechám laskavému čtenáři za domácí úkol. A přihodím cvičení ještě jedno - sestavte algoritmus, který vytvoří cestu z Aše do Zlína (obě města v seznamu jsou) a to tak, že:

  • Začne se v Aši, skončí se ve Zlíně.
  • Bude se skákat z aktuálního města na nejbližší město tak dlouho, až tímto městem bude Zlín.
  • Stále se půjde jen ze západu na východ, pokud bude nejbližší město od aktuálního opačným směrem, bude se ignorovat a vybere se takové, které je ve směru správném.

Stačí, když algoritmus vypíše seznam měst v pořadí, v jakém jimi bude cesta probíhat, není třeba cestu kreslit do mapy. Jakmile mi dorazí první řešení, začnu tvořit třetí díl, takže je jen na vás, zda to bude za dalších pět týdnů či dříve.

PS: Soubor s daty najdete zde.