Stránka sa načítava, prosím čakajte…
© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 19. 4. 2024.
Dátum: 13. 12. 2020, pred štyrmi rokmi
Nim je klasická hra, v ktorej obvykle dvaja hráči striedavo odoberajú objekty (zápalky) z kôpok a ten hráč, ktorý odoberie posledný objekt (zápalku) buď prehrá, alebo vyhrá podľa toho, či ide o „normálnu“ hru, alebo tzv. misère. Aj keď je pri hre Nim bežnejší druhý variant, tu implementujeme „normálnu“ hru (lebo je jednoduchšia na implementáciu).
Tento variant je zjednodušený. Hráči hrajú s jedinou kôpkou zápaliek a môžu odoberať najviac dve zápalky naraz. Vychádzajúc z ukážky SVG kreslenie sme kreslenie implementovali s pomocou SVG podpory rámca GRobot, ale externý SVG súbor sme nahradili klasickým reťazcom, ktorý obsahuje rovnakú SVG definíciu, aká by bola uložená v SVG súbore. Celá hra je tak uložená v jedinom zdrojovom kóde.
Ukážka hrania hry.
Poznámka
V komentári zdrojového kódu triedy Nim
(nižšie; v blízkosti metódy spracujSVG
) je uložený jednoduchší variant SVG zápalky prepísaný do reťazca Javy. Pod komentárom je zároveň uvedený mierne zložitejší variant.
Originál jednoduchšej SVG definície je zverejnený v článku SVG kreslenie.
Originál zložitejšej SVG definície vyzerá takto:
<svg width="12" height="65" version="1.1" viewBox="0 0 12 65" xmlns="http://www.w3.org/2000/svg"> <rect x="6.5" y="13" width="1.5" height="50" fill="#aa0" stroke="#000" stroke-width=".5"/> <rect x="4" y="13" width="2.5" height="50" fill="#cc0" stroke="#000" stroke-width=".5"/> <ellipse cx="6" cy="8" rx="4" ry="6" fill="#800" stroke="#000" stroke-width=".5"/> <ellipse cx="5.5" cy="7.5" rx="3" ry="5" fill="#a00"/> <ellipse cx="4.375" cy="4.625" rx=".875" ry=".875" fill="#fff" fill-opacity=".5"/> </svg>
Zdrojový kód
~
import java.awt.geom.AffineTransform; import knižnica.*; import static knižnica.Svet.*; import static java.io.File.separator; public class Nim extends GRobot { // Atribúty (a vymenovanie stavov). private enum Stav {NOVÁ_HRA, HRÁ_SA, VÝHRA, PREHRA} private int zápaliek; private Stav stav; // Konštrukcia. private Nim() { farbaPozadia(antracitová); farbaTextu(papierová); Svet.písmo("Cambria", 36); začniVstup(); neskrývajVstupnýRiadok(); nováHra(); skry(); mierka(3); } // Hra. private void nováHra() { vymažTexty(); popisVstupnéhoRiadka("Zadajte počet zapáliek: "); zápaliek = 0; stav = Stav.NOVÁ_HRA; prekresliZápalky(); } private void hráSa() { popisVstupnéhoRiadka("Koľko zápaliek chcete odobrať: "); bilancia(); stav = Stav.HRÁ_SA; } private void výhra() { vypíšRiadok("Vyhrali ste!"); popisVstupnéhoRiadka("Chcete začať novú hru? "); stav = Stav.VÝHRA; prekresliZápalky(); } private void prehra() { vypíšRiadok("Prehrali ste…"); popisVstupnéhoRiadka("Chcete začať novú hru? "); stav = Stav.PREHRA; prekresliZápalky(); } private void spracujPočet() { Long číslo = prevezmiCeléČíslo(); if (null == číslo) { pípni(); textVstupnéhoRiadka(prevezmiReťazec()); } else { int počet = číslo.intValue(); if (počet < 5) { pípni(); chyba("Minimálnmy počet je 5"); } else { zápaliek = počet; hráSa(); } } } private void hranieHry() { Long počet = prevezmiCeléČíslo(); if (null == počet) { pípni(); textVstupnéhoRiadka(prevezmiReťazec()); } else if (počet < 1) { textVstupnéhoRiadka(prevezmiReťazec()); pípni(); chyba("Počet musí byť kladný."); } else if (počet > 2) { // textVstupnéhoRiadka(prevezmiReťazec()); pípni(); chyba("Môžete odobrať len jednu alebo dve zápalky."); } else { int odobrať = počet.intValue(); if (odobrať > zápaliek) odobrať = zápaliek; if (1 == odobrať) vypíšRiadok("Odobrali ste jednu zápalku."); else vypíšRiadok("Odobrali ste dve zápalky."); zápaliek -= odobrať; if (zápaliek <= 0) výhra(); else { bilancia(); akciaPočítača(); } } } private void čakanie() { String odpoveď = prevezmiReťazec().trim().toLowerCase(); if ("a".equals(odpoveď) || "á".equals(odpoveď) || "ano".equals(odpoveď) || "áno".equals(odpoveď)) nováHra(); else if ("n".equals(odpoveď) || "nie".equals(odpoveď)) koniec(); } private void akciaPočítača() { int odobrať = (int)náhodnéCeléČíslo(1, 2); if (odobrať > zápaliek) odobrať = zápaliek; if (1 == odobrať) vypíšRiadok("Počítač odobral jednu zápalku."); else vypíšRiadok("Počítač odobral dve zápalky."); zápaliek -= odobrať; if (zápaliek <= 0) prehra(); else bilancia(); } // Kreslenie. private void nakresliZápalku() { Farba farba = farba(); double hrúbkaČiary = hrúbkaČiary(); int počet = svgPodpora.počet(); for (int i = 0; i < počet; ++i) { Farba farbaTvaru = svgPodpora.farbaVýplne(i); if (null != farbaTvaru) { farba(farbaTvaru); vyplňTvar(svgPodpora.dajVýsledný(i), true); } farbaTvaru = svgPodpora.farbaČiary(i); if (null != farbaTvaru) { double hrúbkaČiaryTvaru = svgPodpora.hrúbkaČiary(i) * mierka(); if (Double.isFinite(hrúbkaČiaryTvaru)) hrúbkaČiary(hrúbkaČiaryTvaru); else hrúbkaČiary(1); farba(farbaTvaru); kresliTvar(svgPodpora.dajVýsledný(i), true); } } hrúbkaČiary(hrúbkaČiary); farba(farba); } private void prekresliZápalky() { nekresli(); podlaha.vymažGrafiku(); Poloha p = poloha(); preskočVľavo((zápaliek - 1) * 6 * mierka()); for (int i = 0; i < zápaliek; ++i) { nakresliZápalku(); preskočVpravo(12 * mierka()); } skočNa(p); kresli(); } private void bilancia() { vypíš("Na ploche "); switch (stav) { case NOVÁ_HRA: switch (zápaliek) { case 1: vypíš("je jedna zapálka"); break; case 2: case 3: case 4: vypíš("sú ", zápaliek, " zapálky"); break; default: vypíš("je ", zápaliek," zapáliek"); } break; default: switch (zápaliek) { case 1: vypíš("zostala jedna zapálka"); break; case 2: case 3: case 4: vypíš("zostali ", zápaliek, " zapálky"); break; default: vypíš("zostalo ", zápaliek," zapáliek"); } break; } vypíšRiadok("."); prekresliZápalky(); } // Reakcie. @Override public void potvrdenieVstupu() { switch (stav) { case NOVÁ_HRA: spracujPočet(); break; case HRÁ_SA: hranieHry(); break; default: čakanie(); } } // Statická časť. private final static String svgZápalka = /*"<svg width=\"12\" height=\"65\" version=\"1.1\" " + "viewBox=\"0 0 12 65\">\n" + "\t<rect x=\"4\" y=\"13\" width=\"4\" height=\"50\" " + "fill=\"#cc0\"/>\n" + "\t<ellipse cx=\"6\" cy=\"8\" rx=\"4\" ry=\"6\" " + "fill=\"#a00\"/>\n" + "</svg>";*/ "<svg width=\"12\" height=\"65\" version=\"1.1\" viewBox=\"" + "0 0 12 65\"\n\txmlns=\"http://www.w3.org/2000/svg\">\n" + "\t<rect x=\"6.5\" y=\"13\" width=\"1.5\" height=\"50\" " + "fill=\"#aa0\"\n\t\tstroke=\"#000\" stroke-width=\"" + ".5\"/>\n" + "\t<rect x=\"4\" y=\"13\" width=\"2.5\" height=\"50\" " + "fill=\"#cc0\"\n\t\tstroke=\"#000\" stroke-width=\"" + ".5\"/>\n" + "\t<ellipse cx=\"6\" cy=\"8\" rx=\"4\" ry=\"6\" " + "fill=\"#800\"\n\t\tstroke=\"#000\" stroke-width=\"" + ".5\"/>\n" + "\t<ellipse cx=\"5.5\" cy=\"7.5\" rx=\"3\" ry=\"5\" " + "fill=\"#a00\"/>\n" + "\t<ellipse cx=\"4.375\" cy=\"4.625\" rx=\".875\" " + "ry=\".875\"\n\t\tfill=\"#fff\" fill-opacity=\"" + ".5\"/>\n" + "</svg>"; private static void spracujSVG() { int n; if (-1 != (n = svgPodpora.pridajSVG(svgZápalka))) { Bod stred = svgPodpora.stredKresby(); AffineTransform posun = AffineTransform. getTranslateInstance(-stred.polohaX(), stred.polohaY()); int počet = svgPodpora.počet(); for (int i = 0; i < počet; ++i) svgPodpora.pridajTransformácie(i, posun); } } public static void main(String[] args) { použiKonfiguráciu("Nim.cfg"); spracujSVG(); new Nim(); if (prvéSpustenie()) zbaľ(); } }