Tehtävät viikolle 4

Pakolliset tehtävät on merkitty harmalla taustavärillä. Punaisella taustavärillä merkatut ovat kontrollitehtäviä, jotka näytetään ohjaajalle harjoitustilaisuudessa!

HUOM: nimeä tiedostot otsikossa olevan sanan mukaan

Kahvikassa2000

Kahvikassa

Kahvikassa2000 toimii siten, että ohjelma kysyy ensin juojan nimeä ja sitten kuppien määrää. Tämän jälkeen ohjelma tallentaa nimelle juodut kupit. Jos juoja on jo järjestelmässä, lisää ohjelma aikaisemmin juotujen kuppien määrään uudet kupit. Ohessa on runko ohjelmaan. Käytä tallentajan sisäisenä rakenteena HashMap-luokkaa. Toteuta ohjelmaan toistorakenne (katso esimerkkitulostusta). Ohjelman suorituksen ei tarvitse loppua koskaan.

import java.util.Scanner;

public class Kahvikassa2000 {

    public static void main(String[] args) {

        Tallentaja kk = new Tallentaja();     
        Scanner lukija = new Scanner(System.in);

        // TODO: toistorakenne, toistetaan ikuisesti kyselyä ja tulostelua
		System.out.println("Kuka juo kahvia?");
        System.out.println("Kuinka monta kuppia?");
        
        kk.talleta(kuka, monta);

        System.out.println("\n"+kk+"\n");
    }
}
Kuka juo kahvia?
Matti L
Kuinka monta kuppia?
2

{Matti L=2}

Kuka juo kahvia?
Matti V
Kuinka monta kuppia?
1

{Matti V=1, Matti L=2}

Kuka juo kahvia?
Donald Knuth
Kuinka monta kuppia?
2

{Donald Knuth=2, Matti V=1, Matti L=2}

Kuka juo kahvia?
Matti L
Kuinka monta kuppia?
2

{Donald Knuth=2, Matti V=1, Matti L=4}

Kuka juo kahvia?
...

Sanat

Valitaan sanat

Tee ohjelma, joka kysyy käyttäjältä sanat seuraavasti:

Anna sanat, joiden lukumäärä lasketaan. Tyhjä lopettaa.
MielEni
MINUn
tekevi

Olet kiinnostunut sanoista:
[mieleni, minun, tekevi]

HUOM: talleta sana siten, että se on kokonaan pienillä kirjaimilla (katso Stringin API:sta sopiva apuväline tähän)

Sanojen laskeminen

Jatka ohjelmaa siten, että luetaan tiedostosta kalevala.txt sanat (talleta tiedosto projektin juureen) ja lasketaan sanan esiintymä jos se on listassa.

Sana määritellään siten, että se aloittaa rivin tai sitä ennen (tai jälkeen) on välilyönti.

Esimerkiksi rivillä: "Mieleni minun tekevi, ei ole sanaa mieleni, koska sana tässä määritelmässä on "Mieleni, eikä mieleni.

// Sanojen lukemisen toteutus siten, että sanat ovat ArrayList-muuttujassa sanat

Kirjanlukija kl = new Kirjanlukija("kalevala.txt");
Sanalaskuri sl = new Sanalaskuri();

while (kl.lukuKesken()) {
    sana = kl.seuraavaSana()
	
    // TODO: tee sanasta kokonaan pienillä kirjoitettu ("Mieleni" -> "mieleni")
	
    if (sanat.contains(sana)) {
        sl.talletaEsiintyma(sana);
 }
}

System.out.println("Sanoja löytyi seuraavat määrät:");
System.out.println(sl);
Anna sanat, joiden lukumäärä lasketaan. Tyhjä lopettaa.
MieLENI
minun
TEKEVI

Olet kiinnostunut sanoista:
[mieleni, minun, tekevi]

Sanoja löytyi seuraavat määrät:
{mieleni=3, minun=69, tekevi=4}

Esimerkkitulosteen lukumäärien pitäisi olla oikein annetulla syötteellä.

Kokeile ohjelmaa myös muilla sanoilla. Jos sanaa ei löydy, ei sitä myöskään näytetä lopputuloksessa. Ei siis tarvitse tehdä ohjelmaa siten, että tulostuksessa lukisi {mieleni=3, minun=69, crazypartyillä=0}

Olutmuistion tallentaminen

Kirjoittaminen

Jatka aikaisemmin tehdyn olutlistan toteutusta siten, että olutlistan voi myös tallettaa. Olutlista tallennetaan tiedostoon kun ohjelma suljetaan. Kannattanee siis toteuttaa metodi talletaMuistiot(ArrayList<Olutmuistio> muistiot), joka kirjoittaa sen tiedoston päälle mistä oluet alussa luetaan ohjelman lopussa vallitsevan tilan. Katso edellisestä tehtävästä, että noudatat samaa rakennetta tiedostossa:

Nimi
Olut 1
Olut 2

Nimi2
Olut A
Olut B

Kokeile lisäyksen jälkeen käynnistää ohjelma uudestaan, säilyyvätkö talletetut oluet ohjelmassa käynnistyksien välillä?

Dokumentti

Suurin osa tekstidokumenteista on rakenteellisia. Tässä tehtävässä toteutetaan yksinkertainen dokumentti. Tee koko tehtävä saman projektin sisään!

Dokumentti

Luokalla dokumentti on attribuuttina nimi ja tiivistelmä. Luo luokka Dokumentti ja sille getterit ja setterit. Lisää dokumentille myös metodi tulosta(), joka tulostaa dokumentin sisällön. Testaa Dokumentin toimintaa alla olevan koodiesimerkin ja esimerkkitulosteen avulla. Voit tehdä dokumentin nimen sisennyksen tabulaattorin \t avulla.

Dokumentti doc = new Dokumentti("Olio-ohjelmoinnin peruskäsitteet");
doc.setTiivistelma("Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.");
doc.tulosta();
	Olio-ohjelmoinnin peruskäsitteet
  
Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.

TekstiElementti

Tekstielementillä on attribuuttina teksti. Luo luokka TekstiElementti, ja sille sopivat getterit ja setterit. Luo sille myös metodi tulosta(), joka tulostaa tekstielementin sisällön.

TekstiElementti elementti = new TekstiElementti();
elementti.setTeksti("Ensimmäinen peruskäsite on Kapselointi.");
elementti.tulosta();
Ensimmäinen peruskäsite on Kapselointi.

Lista Tekstielementtejä Dokumentissa

Lisää Dokumentti-luokan attribuutiksi lista tekstielementtejä. Lisää dokumentille myös metodi lisaaElementti(), joka saa parametrikseen TekstiElementti-tyyppisen olion. Muuta dokumentin tulostusta vastaamaan seuraavaa esimerkkiä.

Dokumentti doc = new Dokumentti("Olio-ohjelmoinnin peruskäsitteet");
doc.setTiivistelma("Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.");

TekstiElementti elementti = new TekstiElementti();
elementti.setTeksti("Ensimmäinen peruskäsite on Kapselointi.");
doc.lisaaElementti(elementti);

elementti = new TekstiElementti();
elementti.setTeksti("Toinen peruskäsite on Abstrahointi.");
doc.lisaaElementti(elementti);

doc.tulosta();
	Olio-ohjelmoinnin peruskäsitteet
  
Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.

Ensimmäinen peruskäsite on Kapselointi.
Toinen peruskäsite on Abstrahointi.

ListaElementti

ListaElementti sisältää listan TekstiElemettejä-olioita. Luo luokka ListaElementti, ja testaa sen toteutusta seuraavalla esimerkillä.

ListaElementti lista = new ListaElementti();
TekstiElementti elementti = new TekstiElementti();
elementti.setTeksti("Ensimmäinen peruskäsite on Kapselointi.");
lista.lisaaElementti(elementti);

elementti = new TekstiElementti();
elementti.setTeksti("Toinen peruskäsite on Abstrahointi.");
lista.lisaaElementti(elementti);

lista.tulosta();
- Ensimmäinen peruskäsite on Kapselointi.
- Toinen peruskäsite on Abstrahointi.

Elementti

Sekä TekstiElementillä, että ListaElementillä on yhteisiä piirteitä. Luodaan niille yhteinen yläluokka Elementti, jolla on abstrakti metodi tulosta(). Metodin tulosta()-kutsuminen tulostaa elementin sisällön. Lisää Elementti-luokalle myös attribuutti nimi ja sille sopivat getterit ja setterit. Lisää luokalle Elementti myös konstruktori, joka saa parametrikseen String-tyyppisen olion.

Peri myös luokat TekstiElementti ja ListaElementti luokasta Elementti siten, että TekstiElementti asettaa yläluokkansa attribuutin nimi (käytä super()-konstruktoria!) arvoksi merkkijonon "teksti" ja ListaElementti asettaa yläluokkansa attribuutin nimi arvoksi merkkijonon "lista". Esimerkiksi luokan ListaElementti konstruktoriin tulee kutsu super("lista"). Vaikka tässä tehtävässä ei tallennusta ja lataamista toteutetakaan, nimeä voidaan käyttää elementtien tunnistamiseen niitä tallennettaessa ja lukiessa.

Muuta Dokumenttia

Muuta Dokumentti-luokkaa siten, että se sisältää listan Elementti-olioita Tekstielementtien sijaan. Muuta myös lisaaElementti()-metodia vastaavasti. Ohjelman pitäisi toimia nyt seuraavasti.

Dokumentti dokumentti = new Dokumentti("Olio-ohjelmoinnin peruskäsitteet");
dokumentti.setTiivistelma("Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.");

ListaElementti lista = new ListaElementti();
TekstiElementti elementti = new TekstiElementti();
elementti.setTeksti("Ensimmäinen peruskäsite on Kapselointi.");
lista.lisaaElementti(elementti);

elementti = new TekstiElementti();
elementti.setTeksti("Toinen peruskäsite on Abstrahointi.");
lista.lisaaElementti(elementti);

dokumentti.lisaaElementti(lista);

dokumentti.tulosta();
	Olio-ohjelmoinnin peruskäsitteet

Tämä dokumentti kertoo olio-ohjelmoinnin peruskäsitteistä.

 - Ensimmäinen peruskäsite on Kapselointi.
 - Toinen peruskäsite on Abstrahointi.

Elokuvakirjasto

Erilaiset elokuvat ja muut viihdekäyttöön tarkoitetut mediat päätyvät Mattien huomassa usein hyvin sekaisin. Autetaan heitä tekemällä heille elokuvakirjasto.

Media

Sekä elokuvat, että musiikkilevyt ovat medioita, joten on hyvä aloittaa perusrakenteesta Media. Luo abstrakti luokka Media, jolla on attribuutti nimi. Medialla on myös abstrakti metodi getMediaTyyppi(), joka kertoo median tyypin.

Elokuva

Elokuvalla on median tietojen lisäksi genre. Toteuta luokka Elokuva. Lisää elokuvalle myös toString()-metodi.

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
System.out.println(tuulenViemaa);
System.out.println("Mediatyyppi: " + tuulenViemaa.getMediaTyyppi());
Draama: Tuulen viemää
Mediatyyppi: elokuva

Kirjasto

Kirjasto sisältää listan Media-olioita ja sillä on nimi. Kirjastoon voi lisätä Media-olioita lisaa()-metodilla. Luo luokka Kirjasto. Luo kirjastolle myös toString()-metodi!

Kirjasto leffaKirjasto = new Kirjasto("Elokuvani");

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
leffaKirjasto.lisaa(tuulenViemaa);
Elokuva yksiLensiYliKaenpesan = new Elokuva("Yksi lensi yli käenpesän", "Komedia");
leffaKirjasto.lisaa(yksiLensiYliKaenpesan);

System.out.println(leffaKirjasto);
--[ Elokuvani ]--

Draama: Tuulen viemää
-------------------------------------------------
Komedia: Yksi lensi yli käenpesän
-------------------------------------------------

Kirjastosta hakeminen

Luo kirjastolle metodi haeAlulla(), joka saa parametrikseen hakusanan. Metodilla voidaan hakea medioita nimen alun perusteella. Luokasta String löytyy tähänkin sopiva metodi. Metodi palauttaa listan elokuvista, joihin haku osuu. Toteuta vertailu siten, että merkkien koolla ei ole väliä!

Kirjasto leffaKirjasto = new Kirjasto("Elokuvani");

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
leffaKirjasto.lisaa(tuulenViemaa);
Elokuva yksiLensiYliKaenpesan = new Elokuva("Yksi lensi yli käenpesän", "Komedia");
leffaKirjasto.lisaa(yksiLensiYliKaenpesan);

for(Media m: leffaKirjasto.haeAlulla("tu")) {
  System.out.println(m);
}
Draama: Tuulen viemää

Huomaa että koska Kirjasto sisältää Elokuva-olioita, myös Media-viite osoittaa oikeasti Elokuva-olioon. Tällöin Medialle tapahtuva toString()-metodikutsu on oikeasti Elokuvan toString()-kutsu.

Tulostettava

Metodi haeAlulla() palauttaa aina Media-tyyppisiä olioita, vaikka haluamme tällä hetkellä vain tulostaa median tiedot. Muuta abstraktia luokkaa Media siten, että sillä on rajapinta Tulostettava, joka mahdollistaa seuraavanlaisen toiminnallisuuden. Muuta myös hakumetodeja siten, että ne palauttavat listan Tulostettava-viitteitä.

Kirjasto leffaKirjasto = new Kirjasto("Elokuvani");

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
leffaKirjasto.lisaa(tuulenViemaa);
Elokuva yksiLensiYliKaenpesan = new Elokuva("Yksi lensi yli käenpesän", "Komedia");
leffaKirjasto.lisaa(yksiLensiYliKaenpesan);

for(Tulostettava t: leffaKirjasto.haeAlulla("tu")) {
  System.out.println(t);
}
Draama: Tuulen viemää

Elokuvakirjasto

Luo luokka Elokuvakirjasto, joka laajentaa luokkaa Kirjasto. Elokuvakirjasto pitää Mediakirjaston hakutoiminnallisuuden lisäksi listaa eri genren omaavista elokuvista. Toteuta genrelistaukset Hajautustauluna, kukin genre siis osoittaa listaan elokuvia. Lisää luokalle myös metodi lisaa(), jolle annetaan parametriksi Elokuva-tyyppinen olio.

Elokuvaa lisättäessä lisää se hajautustaulun osoittamaan listaan genren perusteella. Kutsu myös yläluokan lisaa()-metodia, jolloin elokuva menee myös mediakirjastoon.

ElokuvaKirjasto leffaKirjasto = new ElokuvaKirjasto("Elokuvani");

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
leffaKirjasto.lisaa(tuulenViemaa);
Elokuva yksiLensiYliKaenpesan = new Elokuva("Yksi lensi yli käenpesän", "Komedia");
leffaKirjasto.lisaa(yksiLensiYliKaenpesan);

for(Tulostettava t: leffaKirjasto.haeAlulla("tu")) {
  System.out.println(t);
}
Draama: Tuulen viemää

Haku genren perusteella

Lisää elokuvakirjastolle metodi haeGenre(), joka saa parametrikseen merkkijono-olion. Metodi haeGenre() palauttaa listan Elokuva-olioita. Toteuta genren haku myös siten, että se ei välitä kirjainten koosta!

ElokuvaKirjasto leffaKirjasto = new ElokuvaKirjasto("Elokuvani");

Elokuva tuulenViemaa = new Elokuva("Tuulen viemää", "Draama");
leffaKirjasto.lisaa(tuulenViemaa);
Elokuva yksiLensiYliKaenpesan = new Elokuva("Yksi lensi yli käenpesän", "Komedia");
leffaKirjasto.lisaa(yksiLensiYliKaenpesan);

for(Tulostettava t: leffaKirjasto.haeGenre("komedia")) {
  System.out.println(t);
}
Komedia: Yksi lensi yli käenpesän

MusiikkiKirjasto

Matit ovat myös sekaisin musiikkilevyjensä kanssa. Jatketaan edellistä tehtävää siten, että luodaan myös musiikkikirjasto.

MusiikkiLevy

Musiikkilevyllä on attribuutteina nimi, genre ja artisti. Toteuta luokka MusiikkiLevy perimällä se luokasta Elokuva. Ylikirjoita peritty toString()-metodi siten, että tulostus on seuraavanlainen.

MusiikkiLevy levy = new MusiikkiLevy("Ring Ring", "popmusiikki", "ABBA");
System.out.println(levy);
ABBA: Ring Ring (popmusiikki)

MusiikkiKirjasto

Matit eivät niinkään välitä artistista, vaan musiikin genrestä. Toteuta MusiikkiKirjasto, jolla on hakutoiminnallisuus genrelle.

MusiikkiKirjasto kirjasto = new MusiikkiKirjasto("Levyni");
MusiikkiLevy levy = new MusiikkiLevy("Ring Ring", "popmusiikki", "ABBA");
kirjasto.lisaa(levy);

levy = new MusiikkiLevy("Aquarium", "popmusiikki", "Aqua");
kirjasto.lisaa(levy);

for(Tulostettava t: kirjasto.haeGenre("popmusiikki")) {
  System.out.println(t);
}
ABBA: Ring Ring (popmusiikki)
Aqua: Aquarium (popmusiikki)

TauluKirjasto

Matit huomaavat perinnän mahdollistavan ohjelmien luomisen vähällä vaivalla ja yrittävät hyötyä siitä. Luodaan vielä taidehistorialliselle museolle TauluKirjasto.

Taulu

Taululla on nimi ja tekijä. Toteuta luokka taulu.

Taulu taulu = new Taulu("Mona Lisa", "Leonardo da Vinci");
System.out.println(taulu);
Leonardo da Vinci: Mona Lisa

TauluKirjasto

Taulukirjastosta voidaan etsiä vain taulun nimen (alun) perusteella. Toteuta luokka TauluKirjasto. Jos perit toteutuksen muualta, lisää taulukirjastolle metodit hae() ja lisaa(), joilla kapseloidaan peritty toteutus.

TauluKirjasto tauluKirjasto = new TauluKirjasto("Taidehistoriallinen Museo");
Taulu taulu = new Taulu("Mona Lisa", "Leonardo da Vinci");
tauluKirjasto.lisaa(taulu);

taulu = new Taulu("Pyhä Ehtoollinen", "Leonardo da Vinci");
tauluKirjasto.lisaa(taulu);
System.out.println(tauluKirjasto);

System.out.println("Haku:");
for (Tulostettava t: tauluKirjasto.hae("py")) {
  System.out.println(t);
}
--[ Taidehistoriallinen Museo ]--

Leonardo da Vinci: Mona Lisa
-------------------------------------------------
Leonardo da Vinci: Pyhä Ehtoollinen
-------------------------------------------------

Haku:
Leonardo da Vinci: Pyhä Ehtoollinen

Bonus

Jatketaan taas viime viikoilla kehitettyä sokkeloa.

Pisteet

Tähän mennessä olemme pyrkineet pelaajallamme maaliin mahdollisimman suurella pistemäärällä. Muuta pelin toteutusta siten, että jokaisessa ei vielä käydyssä ruudussa on piste, joka täytyy kerätä. Ennen kuin kaikki pisteet on kerätty, ei pelaaja voi päästä maaliin. Muuta kentän tulostusta seuraavaksi. Muuta myös pisteytystä siten, että pelaajalta ei kulu pisteitä etenemisestä. Mörkö ei syö pisteitä, mutta mörön aloituskohdassa ei myöskään ole pistettä!

  
XXXXXXXXXXXXXXXXXXXXX
XO..X.X.....X.X.X..XX
X.X...X.XXX.X....X..X
X.XXX.....X.X.XX..X.X
X.XAX.XXX........XX.X
X.X...X.X.X.XXX...X.X
X...X...X.X...X.X.X.M
X.X.X.X.....X.X.X...X
X.X..WX.XAX.....X.X.X
XXXXXXXXXXXXXXXXXXXXX
Pelaaja sijainnissa (1, 1), pisteet 0

Anna liikkumissuunta: a
XXXXXXXXXXXXXXXXXXXXX
X ..X.X.....X.X.X..XX
XOX...X.XXX.X....X..X
X.XXX.....X.X.XX..X.X
X.XAX.XXX........XX.X
X.X...X.X.X.XXX...X.X
X...X...X.X...X.X.X.M
X.X.XWX.....X.X.X...X
X.X.. X.XAX.....X.X.X
XXXXXXXXXXXXXXXXXXXXX
Pelaaja sijainnissa (1, 2), pisteet 1

Anna liikkumissuunta: a
XXXXXXXXXXXXXXXXXXXXX
X ..X.X.....X.X.X..XX
X X...X.XXX.X....X..X
XOXXX.....X.X.XX..X.X
X.XAX.XXX........XX.X
X.X...X.X.X.XXX...X.X
X...XW..X.X...X.X.X.M
X.X.X.X.....X.X.X...X
X.X.. X.XAX.....X.X.X
XXXXXXXXXXXXXXXXXXXXX
Pelaaja sijainnissa (1, 2), pisteet 2

Reitin valinta

Mörkömme on jo aika pahis jos se osaa mennä pelaajaa kohti. Muutetaan mörköä siten, että sillä on aina suunta, mihin se on menossa. Kun mörkö lähtee liikkumaan johonkin suuntaan, se liikkuu sinne päin kunnes se joko osuu seinään, tai päätyy risteyskohtaan. Risteyskohdassa mörkö valitsee uuden suunnan siten, että 50% todennäköisyydellä valitaan suunta, joka kulkee pelaajaa kohti. Muulloin valitaan satunnainen suunta.

Toteuta mörölle suuntatoiminnallisuus.

Useampi mörkö

Lisää kenttään mahdollisuus useammalle mörölle. Möröt voivat liikkua toistensa yli. Kokeile toteutusta seuraavalla taulukolla.

int[][] taulukko = {
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
  {1, 2, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1},
  {1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1},
  {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1},
  {1, 0, 1, 3, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 99, 0, 1, 1, 0, 1},
  {1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1},
  {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, -1},
  {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 99, 1, 0, 1, 0, 1, 0, 0, 0, 1},
  {1, 0, 1, 0, 0, 99, 1, 0, 1, 3, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1},
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};

Pelaa

Pelaa peliä seuraavalla kentällä.

int[][] taulukko = {
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1},
    {1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1},
    {1,1,1,1,1,1,0,1,0,1,1,1,99,1,1,1,0,1,0,1,1,1,1,1,1},
    {1,1,1,4,0,0,0,0,0,1,1,99,99,99,1,1,0,0,0,0,0,4,1,1,1},
    {1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1},
    {1,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,1,0,0,0,0,0,0,1},
    {1,0,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
  };