Hi student pls do this assignment

parent 4df04a5b
# Lab 4 Del II: “aMazing Labyrinth”
[Lab 4 Oversikt](LAB-4.md)
## Om oppgaven
I lab-oppgaven denne uken skal vi forbedre [labyrintoppgaven fra
Semesteroppgave 3](src/inf100/h16/sem3/semoppg3.pdf) i INF100 Høst 2016. I denne oppgaven skulle studentene
lage et lite program som leser inn en labyrint fra en fil og så
lar en spiller navigere den.
Labyrinten er lagret i en tekst fil der karakteren `"*"` er en vegg, `" "` (mellomrom) er en åpen plass som spilleren kan gå igjenom, og `"s"` er startposisjonen til spilleren. Vi forenkler innlesingen litt, men du kan legge til innlesing fra fil selv om du vil. I den opprinnelige oppgaven blir spilleren bedt om hvilken retning (nord, sør, øst og vest) han vil gå i, og blir vist hvor han er på kartet – vi skal i stedet bruke (veldig forenklet) “events” til å håndtere tastetrykkene.
## Forbedringer
Du kan [se den opprinnelige oppgaven og løsningsforslaget her](src/inf100/h16/sem3/). Det kan være nyttig å sette seg litt inn i den koden, bare for å forskjellen i hvordan man løser problemer med enkel programmering (INF100) og med bruk av abstraksjon og objekter (INF101).
Vi ønsker å forbedre implementasjonen fra INF100h16 for å
* Gjøre det enklere å teste
* Gjøre det enklere å gjenbruke koden
* Bruke et grafisk grensesnitt
* Håndtere feil i input bedre
I tillegg til et [grafisk grensesnitt](src/inf101/v19/labyrinth/GUIMain.java) har vi lagt ved en [klasse
med en main metode som gjenskaper det tekst-baserte grensesnittet](src/inf101/v19/labyrinth/ConsoleMain.java)
fra den opprinnelige oppgaven.
# Steg 0: Gjør ferdig forrige oppgave
Du trenger å ha gjort Del I av denne oppgaven + hele eller mesteparten av Lab 3. Generelt er det lurt å gjøre ting i rekkefølge – det er bedre å konsentrere seg om å bli ferdig med forrige enn å hoppe videre til neste. Hvis du står fast på en oppgave, spør om hjelp!
# Steg 1: Hent Oppgaven fra git
Etter at du har gjort [Del I](LAB-4-I_GIT.md) kan du hente (klone) oppgaven på vanlig måte fra
```
https://retting.ii.uib.no/<brukernavn>/inf101.v19.lab4.git
```
## Oversikt over koden
* inf101.v19.cell – ting fra Lab 3
* **inf101.v19.datastructures** – IGrid og IList fra Lab 3
* inf101.v19.labyrinth.ILabyrinth – grensesnitt som skal implementeres
* **inf101.v19.labyrinth.Labyrinth** – skal implementeres av deg
* inf101.v19.labyrinth.LabyrinthTest – tester for labyrinten
* inf101.v19.labyrinth.LabyrinthTile – enum (OPEN, WALL, PLAYER, ...)
* inf101.v19.labyrinth.LabyrinthHelper – metoder for å lage labyrint-grids (tilfeldig eller basert på tabeller)
* inf101.v19.labyrinth.Direction – enum (NORTH, SOUTH, EAST, WEST)
* inf101.v19.labyrinth.GUIMain – grafisk hovedprogram
* inf101.v19.labyrinth.ConsoleMain – tekstbasert hovedprogram
**OBS!** Den utleverte labyrint-koden inneholder kompileringsfeil! Disse skal du fikse etterhvert.
## Steg 2: Gjøre IGrid og MyGrid generisk
Vi har lagt ved IGrid og MyGrid fra [Lab 2 og 3](LAB-3.md). Dette skal vi bruke til å holde styr
på hvor spilleren er, hvor det er vegger og de plassene spilleren kan bevege seg.
`MyGrid` er lagd for å holde styr på celle-tilstander, men nå ønsker vi å holde styr på
Labyrintbiter (`LabyrinthTile`).
Istedenfor å forandre MyGrid hver gang vi skal lagre en ny type elementer skal vi
gjøre `IGrid` generisk og forandre `MyGrid` slik at den implementerer det nye IGrid interfacet.
For å gjøre det må IGrid nå være
public interface IGrid<T>
Hvor `T` er typen elementer som skal lagres. Derfor skal `set` ta i mot en `T` istedenfor
en CellState og `get` returnere en `T`. Dessuten vil `copy` returnere en `IGrid<T>`.
På samme måte må `MyGrid` forandres til
public class MyGrid<T>
* Oppdater `IGrid` og `MyGrid` så de blir generiske
* Oppdater også `GridTest` til å fungere med generisk grid; testene er laget for `CellState`-elementer, så du kan her bruke `MyGrid<CellState>` for eksempel. Vi har allerede oppdatert `IList`og `MyList`slik at de er generiske.
## Steg 3: Teste MyGrid
* Testene fra Lab 3 (i `GridTest`) skal fremdeles virke.
## Steg 4: Bruk `MyGrid<T>` i Lab 2/3
Vi har lagt ved programmene fra [Lab 2 og 3](LAB-3.md). Gjør om
programmet slik at det kan bruke `IGrid<T>`/`MyGrid<T>`.
* Sjekk celleautomatene (f.eks. `GameOfLife.java`) og se at de fremdeles fungerer og at celleautomat-programmet `inf101.v19.cell.Main` virker.
* Når du nå ser på koden for automatene (du kan gjerne kopiere over din egen løsning fra Lab 3), vil du se at du får advarsler om at `IGrid is a raw type` på stedene du har brukt IGrid/MyGrid. Slik koden er nå vil Java tolke IGrid/MyGrid som noe som kan lagre hva som helst (`Object`), i stedet for å være begrenset til å lagre `CellState`-elementer. Dette gjør koden litt mindre trygg (hva om noen fyller cellene med ender i stedet for cellstate?) – du bør derfor gå gjennom koden og *parameterisere* IGrid/MyGrid med elementtypen slik at du får f.eks. `IGrid<CellState>` i stedet.
## Steg 5: Lage en implentasjon av ILabyrinth
Vi har lagt ved et interface for klassen som brukergrensesnittet bruker for
å avgjøre oppførselen av Labyrintbitene. Lag en implementasjon av denne
som du kaller `Labyrinth`.
Vi har lagd ved noen tester for denne klassen i
`inf101.v19.labyrinth.LabyrinthTest`. Skriv gjerne egne tester for å sjekke at
implementasjonen din er korrekt.
### Konstruktør
Konstruktøren skal være slik:
public Labyrinth(IGrid<LabyrinthTile> tiles)
* Du må ta en kopi av argumentet før du lagrer det i labyrint-objektet (`tiles.copy()`). Dette er nødvendig for å beskytte innkapslingen av datastrukturen (du lærer mer om dette senere i semesteret).
* Sjekk at ett og bare ett av feltene i `tiles` inneholder `LabyrinthTile.PLAYER`. Det er antakelig praktisk å lagre x,y-koordinatene til spilleren.
* Du bør sjekke at ingen av feltene inneholder `null`
### Metoder (m/hint)
Du må implementere disse metodene:
* `LabyrinthTile getCell(int x, int y)`
* `Color getColor(int x, int y)` – her kan du finne fargen ved hjelp av LabyrinthTile.getColor(); f.eks. getCell(x,y).getColor()
* `int getHeight()` og `int getWidth()` – kan hentes fra grid
* `boolean isPlaying()` – kan evt være `true` alltid (kan brukes for å implementere mer avanserte utgaver)
* `void movePlayer(Direction dir)` – skal flytte spillerens posisjon (se mer om Direction under), eller kaste `MovePlayerException` hvis den nye posisjonen ville vært ulovlig
* `boolean playerCanGo(Direction d)` – returnerer `true` hvis spilleren kan gå i retningen; gyldige felter for spilleren er alle som er innenfor brettet og som ikke inneholder `LabyrinthTile.WALL`
Disse kan du la returnere 0:
* `int getPlayerGold()`
* `int getPlayerHitPoints()`
Det kan lønne seg å lage noen hjelpemetoder: f.eks. `isValidPosition(int x, int y)` for å sjekke om en posisjon er gyldig for spilleren.
For **alle** metodene skal du (om nødvendig) sjekke argumentene før du bruker dem (f.eks. at x,y er innenfor rekkevidde). Ved feil i argumentene skal du `throw new IllegalArgumentException()`.
### Enum
Det følger med to enums:
* Direction – en av `NORTH`, `SOUTH`, `EAST`, `WEST`. Brettet er slik at `y` øker i `NORTH`-retningen og `x` øker i `EAST`-retningen
* LabyrinthTile – her trenger du bare bry deg om `OPEN` (ledig felt), `WALL` (vegg der spilleren ikke kan gå) og `PLAYER` (spilleren)
### Kjøre programmet
Det følger med to klasser med `main`-metoder, en som har grafisk brukergrensesnitt (`GUIMain`) og en som har INF100-style tekstgrensesnitt (`ConsoleMain`). I det grafiske brukegrensesnittet kan du navigere med piltastene eller med knappene.
### Legg merke til at...
* Sammenliknet med INF100 Semesteroppgave 3, har vi nå egne typer for flere av konseptene:
* `IGrid`/`MyGrid` i stedet for `char[][]`
* `LabyrinthTile` i stedet for `char`
* `ILabyrinth`/`Labyrinth` for labyrinten
* `Direction` for retning
* `LabyrinthHelper` for å lage nye labyrinter
* Grid-typene er *abstrakte datatyper* (ADTer). En datatype er abstrakt når vi vet hva vi kan gjøre med verdiene (hvilke metoder vi kan kalle), uten at vi vet nøyaktig hvordan dataene er lagret eller hvordan metodene er implementert. Både `class` og `interface` spesifiserer en abstrakt datatype. I tillegg lager `class` en konkret implementasjon av datatypen (dvs. den sier hvilke feilvariabler som inngår i datastrukturen og hvordan metodene som bruker datastrukturen er implementert). Når du bruker objekter og kaller metoder på dem, jobber du med ADTer. Når du kikker på / endrer klassen til et objekt, jobber du med den konkrete typen (klassen) som implementerer ADTen. En abstrakt datatype har *data innkapslet bak et grensesnitt av veldefinerte metoder*; dvs. at programmeringen vi gjør med objekter i INF101 også er programmering med data abstraksjon og abstrakte datatyper (selv om vi ikke har brukt akkurat disse ordene så mye).
* En del abstrakte datatyper er så vanlige at du kan snakke om dem på en måte hvor de i praksis er enda mer abstrakte. Dvs. når vi snakker om "en liste" eller "en liste-ADT", så vil de fleste programmører vite at det er snakk om noe hvor du kan sette inn og hente ut elementer, og hvor elementene er i rekkefølge, uavhengig av nøyaktig hvilket grensesnitt som brukes. Så både `List` (som følger med i Java) og `IList` (som vi har laget i INF101) er eksempler på liste-ADTen, og de er i praksis ganske like selv om du ikke kan erstatte den ene med den andre. Lister i f.eks. Python er en annen variant av lister. Dvs. at "liste" er et vanlig ADT-konsept; IList og List er konkrete eksempler på ADTen, og MyList og ArrayList er konkrete datatyper som implementerer IList og List ADTene.
* Fordelen med å abstrahere vekk detaljene rundt grid, er at vi slipper å forholde oss til detaljene rundt hvordan ting er lagret. Hvis vil lagrer gridet i en `char[][]` så må alle deler av programmet som bruker gridet forholde seg til at det består av en tabell av tabeller. Man må da også f.eks. ta med i beregning at Java ikke gir noen garanti for at hver undertabell i en `char[][]` er like lang. Og hvis vi har kode som er interessert i bare å se på samlingen av elementer, uavhengig av posisjon i gridet, så må den koden også forholde seg til at vi har en tabell av tabeller. Med IGrid/MyGrid kan vi i stedet f.eks. legge til metoder som lar oss gå gjennom alle elementene i vilkårlig rekkefølge. Vi har også mulighet til å legge til andre hendige metoder om vi vil; f.eks. "fyll alle feltene med X", "gi meg feltet som er NORTH for dette X,Y", "er (x,y) en gyldig koordinat? (uten å måtte skrive ned den litt kompliserte testen (`x >= 0 && x < grid.length && y >= 0 && grid.length > 0 && y < grid[0].length` e.l.) for dette alle steder)
* Ved å trekke ut labyrinten i en egen klasse (i stedet for å blande den sammen med `main`-metoden), er det lett å gjenbruke den i flere situasjoner, f.eks. både med grafisk- og tekstgrensenitt. Samme labyrint-koden kunne f.eks. også brukes med 3D-grafikk.
* Å ha labyrinten i egen klasse er også praktisk når man skal teste den. I prinsippet kunne vi testet labyrinten ved å gi den tekst som input og sjekke utskriften; men det er litt komplisert å få til, og adskillig vanskeligere med programmer som har grafiske brukergrensesnitt. Vi vil derfor aller helst ha mest mulig funksjonalitetet (grid, retning, labyrint, ...) delt opp i seperate klasser som kan testes for seg (*enhetstesting*).
* Vi kunne gjerne gått lenger i dette, og skilt ut ideen om *posisjon* i en egen `Position`-klasse (slik vi gjorde på forelesningene). Da kunne logikken for å håndtere retninger vært plassert sammen med posisioner, i stedet for å være spredd utover.
## Ekstra
Du kan utvide oppgaven i tråd med ideene fra INF100:
* Gull: La spilleren samle inn gull (`LabyrinthTile.GOLD`) som ligger på feltene. Tilfeldighetsgeneratoren legger ut gull allerede, og brukergrensesnittet viser hvor mye gull spilleren har samlet (basert på `getPlayerGold`).
* Monstre: La spilleren sloss med monstre (`LabyrinthTile.MONSTER`). Du kan f.eks. ha hit points som reduseres hvis spilleren taper en kamp. Disse kan vises i brukergrensesnittet (basert på `getPlayerHitPoints`).
* Du bør i såfall lage noen flere tester (f.eks. at `getPlayerGold` øker når spilleren går på et gull-felt).
* Vi har litt veldig enkel kode for å lage tilfeldige labyrinter i `LabyrinthHelper`. Det finnes [mange algoritmer](https://en.wikipedia.org/wiki/Maze_generation_algorithm) for å generere gode labyrinter. Interessant nok kan [celleautomater også brukes til å generere labyrinter](http://www.conwaylife.com/w/index.php?title=Maze).
* Du kan gjerne også implementere filinnlesing i `LabyrinthHelper`.
# Lab 4 Del I: Social Software Engineering: Git, Reviews, Bugs
*"Muligens den mest relevante laben de kommer til å ha under hele studiet spør du meg"* -- tredjeårsstudent
[Lab 4 Oversikt](LAB-4.md)
## Steg 0: Teit melding
Hvis du får beskjeden "You won't be able to pull or push project code via SSH until you add an SSH key to your profile" på websidene, trykk "Don't show again". Av administrative grunner kan du uansett ikke bruke SSH-nøkkel, så meldingen er overflødig. :(
## Steg 1: Finne en løsning på Lab 2/3
### 1.1 Tilgang
Til denne delen av oppgaven trenger du hjelp fra en eller flere andre studenter. Du kan spørre naboen(e) dine på labben, f.eks., eller noen du kjenner. (Du *kan* evt. gjøre alt på egenhånd, men det gir gjerne litt mindre utbytte.)
På samme måte som i Lab 3, bygger Lab 4 på løsningen fra forrige (bare litt, egentlig: primært er det grid-datastrukturen du trenger). Det vil si at du også denne gang skal merge løsningen fra forrige oppgave; forskjellen nå er at dere skal prøve dere på å sende/motta *merge request* til/fra andre studenter, i stedet for å være alene om jobben. Dette er et betydelig mer realistisk scenario enn forrige gang.
Aller først må du gi de aktuelle andre studentene tilgang til prosjektet ditt:
* Gå til prosjektsiden for *din Lab 4* (`https://retting.ii.uib.no/BRUKERNAVN/inf101.v19.lab4`).
* Gå til *Settings -> Members* på menyen på venstre side.
* I *Add member* tabben, søk opp studentene du skal samarbeide med (du kan taste litt av navnet eller brukernavnet). Du kan velge flere samtidig.
* På "Choose a role permission" velg *Reporter* eller *Developer*. (Du kan [lese om prosjekt-rettigheter her](https://docs.gitlab.com/ce/user/permissions.html). Det tryggeste er kanskje å velge *Developer*, for å unngå eventuelle problemer med begrensninger senere; men i praksis bør *Reporter* (eller til og med *Guest*) være tilstrekkelig. *Guest* vil kunne gjør det du trenger å kunne gjøre her (sende merge request og rapportere bug), men ikke kunne laste ned koden og du vil få en feilmelding underveis fordi du ikke får lov å se merge requesten etter at du har laget den.)
* Trykk *Add to project*
* Gjør det samme med din *Lab 3*.
(Ikke bruk *Share with group*, selv om dere er flere; dette er for en annen type gruppe...)
Dere vil få eposter om at dere har fått tilgang.
### 1.2 New Merge Request
Så må du finne din løsning på Lab 3 (`https://retting.ii.uib.no/BRUKERNAVN/inf101.v19.lab3`), og sende den som *merge request* til en av de andre (hvis dere er flere enn to, kan dere f.eks. la person A sende merge request til B, B sende til C, og C sende til A)
* Hvis du vil, kan du gjerne legge inn en liten ekstra feil i Lab 3 koden din, så blir ting litt mer spennende for de du samarabeider med.
* Lag merge request på samme måte som i Lab 3 (*+ Create new merge request* på forsiden til Lab 3), men i stedet for for å velge *din* Lab 4 som target branch, skal du velge en annen students Lab 4 (dvs. student B om du er student A). New merge request siden skal altså ha: "DittBrukerNavn/inf101.v19.lab3 master" på venstre side og "DenAndresBrukernavn/inf101.v19.lab4 master" på høyre side. Husk at du skal merge *fra Lab 3* (har allerede løsning) *til Lab 4* (mangler løsning).
* Hvis du ser på Lab 4 prosjektet ditt, vil du nå (forhåpentligvis) se at du har "Merge requests: 1" i menyen på venstre side. Du vil også gjerne se et ett-tall på merge request knappen øverst til høyre på siden, ved siden av søkefeltet.
## Steg 2: Enkel code review, bug rapporter
### 1.3 Vurdering og merging
Nå skal du se på *din Lab 4* (`https://retting.ii.uib.no/BRUKERNAVN/inf101.v19.lab4`).
Du må kikke på merge requesten som noen har sendt og vurdere om den er "akseptabel". Finn fram til merge requesten (via menyen på venstre side eller knappen øverst til høyre).
Den skal se ut som siden du trykket "Merge" på sist gang. Denne gangen kan du være litt mer kritisk:
* Klikk på Changes, og se gjennom endringene som er gjort
* Du kan legge inn små kommentarer på enkeltlinjer med endringer. Prøv dette.
* Test også diskusjonen, og se hva som skjer.
* Hvis dere har lagt inn feil til hverandre, prøv å se om dere finner de ved å kikke på koden (neppe særlig enkelt!).
* Test gjerne også ut hva som skjer hvis noen gjør flere endringer i Lab 3 etter å ha sendt merge request.
* Når du er fornøyd, kan du trykke *Merge*.
(I verste fall, eller om du er veldig ukomfortabel med å jobbe videre med andres kode (er egentlig bare Grid-koden du trenger), så kan du "Close merge request" og merge din egen Lab 3 (evt bare kopiere grid-filene).)
### 1.4 Issues
Når du har merget, kan du klone koden på vanlig måte (som i [Del II](LAB-4-II_LABYRINTH.md)) og kikke på den i Eclipse.
* Kjør testene og kjør Brian's Brain og Langton's Ant.
* Se på koden og se hvordan den er forskjellig fra eller liknende til din egen.
* Prøv å lage en bug rapport:
* Trykk *Issues* i menyen på venstre side på prosjektet på retting.ii.uib.no. Du kan gjøre dette på ditt eget prosjekt, eller på en annen students prosjekt (mer spennende, kanskje).
* Velg *New Issue*
* Fyll inn hva du mener er problemet. Enten noe oppdiktet, eller en faktisk feil du har funnet (kanskje noe som er lagt inn med vilje).
* Du kan gjerne også lage en ny *issue* med en "feature request" om å implementere labyrinten i Del II av denne labben (her kan du f.eks. linke til Del II i forklaringen din). Du kan bruke "Labels" for å skikke forskjellige typer issues fra hverandre. Velg *Labels*, *Manage labels*, *Generate a default set of labels*. "Enhancement" vil f.eks. passe for denne type "fint om du implementerer denne tingen"-forespørsel.
* Test også hvordan du kan [lukke en "issue" ved å committe](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html). Enten fiks det faktiske problemet som er rapportert, eller bare gjør en endring (hvis dere har rapportert fiktive problemer). Når du committer i Eclipse (evt. direkte på websiden), legg til en setning nederst i commit-meldingen med f.eks. "Fixes #1." (der "1" er nummeret på bugrapporten). Når du har committet og pushet, skal issuen bli stengt av seg selv.
## Steg 3: Flere muligheter
Hvis du/dere er lei av GitLab og bug-rapporter nå, kan du gå videre til [Del II](LAB-4-II_LABYRINTH.md). Ellers har vi noen flere tips til ting dere kan prøve:
* Hvis du finner mulige forbedringer, faktiske feil eller annet så kan du sende en merge request tilbake til de andre med fix for problemet.
* Hvis dere ser på hverandres kode går det også an å se om det er løsninger som er "bedre" (koden er lettere å forstå f.eks.) enn de andre. Så lenge du har rettigheter til andres prosjekter, går det an å spre kode mellom seg med merge requests; enten at du sender til en annen, eller at du lager merge request på ditt eget prosjekt med en annens prosjekt som "source".
* Det går an å gjøre Del II av denne oppgaven "felles" ved at alle kloner og jobber mot det samme repositoriet. Til slutt kan dere bruke merge request for å få alt over på deres egen bruker, slik at det blir sporet i testesystemet vårt.
* Legg også merke til at endringene dere gjør eller overfører til hverandre blir korrekt sporet med hvem som har gjort hva. Dvs. at ditt navn dukker opp på commits i andre sine prosjekter (slik som navnet på den som har laget oppgaven også dukker opp i historikken). I mer avanserte arbeidsflyter vil man gjerne også bruke kryptografisk signering for å være sikker på hvor koden kommer fra og hvem som har godkjent den.
*
# Lab 4: Labyrint
## Læringsmål
* *Abstraksjon*:
* Kunne forklare abstrakt datatype (ADT)
* *Generisk programmering*:
* Gjøre en samling generisk
* Bruke generiske samlinger
* Enkel testing av generiske klasser
* *Software engineering metoder*:
* Interagere med andre utviklere med pull/merge request, bug reports,
## Part I: Social Software Engineering: Git, Reviews, Bugs
(Gjør Del I av Lab 3 først!)
[Gå til Del I](LAB-4-I_GIT.md)
## Part II: Labyrint
(Gjør Lab 3 og Del I først!)
[Gå til Del II](LAB-4-II_LABYRINTH.md)
# INF101
Dette prosjektet inneholder [Labøvelse 3](LAB-3.md). Du kan også [lese oppgaven online](https://retting.ii.uib.no/inf101.v19.oppgaver/inf101.v19.lab3/blob/master/LAB-3.md) (kan evt. ha små oppdateringer i oppgaveteksten som ikke er med i din private kopi).
Dette prosjektet inneholder [Labøvelse 4](LAB-4.md). Du kan også [lese oppgaven online](https://retting.ii.uib.no/inf101.v19.oppgaver/inf101.v19.lab4/blob/master/LAB-4.md) (kan evt. ha små oppdateringer i oppgaveteksten som ikke er med i din private kopi).
## Tips
#### Tips 1
Det er veldig lett å bli forvirret over alle de forskjellige repositoriet (mitt, ditt, naboens, lab2, lab3, lab4...). Kan være greit å tegne en oversikt, f.eks... I tillegg kan du holde litt oversikt over hva som har skjedd (f.eks. om du har eller ikke har merget lab3 til lab4) ved å se på Overview → Activity og/eller Repository → Commits (begge deler på venstre side av prosjektsiden på retting.ii.uib.no). Der får du se hvem som har gjort hva med koden din. (Og hadde dette vært enkelt og lettvint å holde styr på, så hadde vi selvfølgelig ikke laget oppgave av det... :) )
#### Tips 2
Du får feil i labyrint-pakken når du er ferdig med Del 1 av oppgaven – det er meningen. I tillegg får du sannsynligvis en feil i MyGrid som gjør at du ikke kan kjøre Brian's Brain eller Langton's Ant med en gang. Dette er ting du skal fikse i løpet av Del 2. Problemet er at vi nå har gjort IList/MyList generisk, uten at IGrid/MyGrid er oppdatert tilsvarende (det er din jobb). Da vet ikke Java lenger at listen "cells" inneholder CellState-objekter, den vet bare at de er "Object", og klager når get()-metoden skal hente en CellState ut fra "cells" og returnere den. Du kan fikse det midlertidig ved å si "return (CellState) cells.get(...);" i MyGrid.get() (da forteller du Java at du er sikkert på at objektet er en CellState). Alternativt kan du endre "IList cells" til "IList<CellState> cells" (+ oppdatere konstruktøren din) – eller rett og slett bare gjøre Del 2 Steg 2.
## Korrigerte feil
I Del 2 steg 2 mente vi `MyGrid<CellState>` der hvor det stod `GridiTest<CellState>`. (Du *kan* lage generiske tester, men det er litt mer komplisert og vi skal se på det senere.)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/bin" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="junit5">
<CLASSES>
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="JUnit5.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.0.0/junit-jupiter-api-5.0.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.0.0/apiguardian-api-1.0.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.0.0/opentest4j-1.0.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.0.0/junit-platform-commons-1.0.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
\ No newline at end of file
INF100 Semesteroppgave 3, Høsten 2016
Authors:
* Bjørn André Bredesen, UiB
* Dag Haugland, UiB
\ No newline at end of file
package inf100.h16.sem3;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class LabyrintFil {
public static int terningkast(){
return (int) (1+6*Math.random());
}
public static boolean kanGaaTil(char[][] labyrint, int labyrintBredde, int labyrintHoeyde, int nyX, int nyY){
if(nyX<0||nyY<0||nyX>=labyrintBredde||nyY>=labyrintHoeyde)
return false;
if(labyrint[nyY][nyX] == '*')
return false;
return true;
}
public static char[][] lesLabyrintFraFil(String bane){
File fil = new File(bane);
try{
Scanner in = new Scanner(fil);
// Les inn bredde
if(!in.hasNextInt()){
System.out.println("Feil! Mangler bredde.");
in.close();
return null;
}
int labyrintBredde = in.nextInt();
if(labyrintBredde <= 0){
System.out.println("Feil! Bredde maa vaere minst 1.");
in.close();
return null;
}
in.nextLine();
// Les inn hoeyde
if(!in.hasNextInt()){
System.out.println("Feil! Mangler hoeyde.");
in.close();
return null;
}
int labyrintHoeyde = in.nextInt();
in.nextLine();
if(labyrintHoeyde <= 0){
System.out.println("Feil! Hoeyde maa vaere minst 1.");
in.close();
return null;
}
// Les brettet
System.out.println(labyrintBredde);
System.out.println(labyrintHoeyde);
char[][] labyrint = new char[labyrintHoeyde][labyrintBredde];
for(int y = 0; y < labyrintHoeyde; y++){
if(!in.hasNextLine()){
System.out.println("Feil! Filen har ikke nok linjer.");
in.close();
return null;
}
String linje = in.nextLine();
for(int x = 0; x < labyrintBredde; x++){
if(x >= linje.length()){
System.out.println("Feil! En linje er for kort.");
in.close();
return null;
}
labyrint[y][x] = linje.charAt(x);
}
}
in.close();
return labyrint;
}catch(FileNotFoundException e){
System.out.println("Feil! Filen kunne ikke åpnes.");
return null;
}
}
public static void main(String[] args) {
Scanner tastatur = new Scanner(System.in);
// Labyrint
System.out.println("Oppgi vil som labyrint skal lastes fra:");
String labyrintBane = tastatur.nextLine().trim();
char[][] labyrint = lesLabyrintFraFil(labyrintBane);
if(labyrint == null){
tastatur.close();
return;
}
int labyrintBredde = labyrint[0].length;
int labyrintHoeyde = labyrint.length;
int labyrintGull = 0;
// Finn spillerposisjon
int spillerX = 0;
int spillerY = 0;
int spillerGull = 0;
for(int y = 0; y < labyrintHoeyde; y++){
for(int x = 0; x < labyrintBredde; x++){
if(labyrint[y][x]=='s'){
spillerX = x;
spillerY = y;
labyrint[y][x] = ' ';
}else if(labyrint[y][x]=='g'){
labyrintGull++;
}
}
}
// Gaa gjennom labyrint
while(true){
// Skriv ut labyrint
System.out.println("Spiller-gull: "+spillerGull);
System.out.println("Labyrint:");
for(int y = 0; y < labyrintHoeyde; y++){
for(int x = 0; x < labyrintBredde; x++){
if(x == spillerX && y == spillerY)
System.out.printf("s");
else
System.out.printf("%c",labyrint[y][x]);
}
System.out.printf("\n");
}
// Gaa
System.out.println("Hvor vil du gaa? Skriv nord, soer, vest eller oest for aa gaa i respektiv retning, eller avslutt for aa avslutte.");
String valg = tastatur.nextLine().trim();
int nyX = spillerX;
int nyY = spillerY;
if(valg.equals("nord")){
nyY--;
}else if(valg.equals("soer")){
nyY++;
}else if(valg.equals("vest")){
nyX--;
}else if(valg.equals("oest")){
nyX++;
}else if(valg.equals("avslutt")){
break;
}else{
System.out.printf("Ugyldig valg: %s\n",valg);
continue;
}
if(kanGaaTil(labyrint, labyrintBredde, labyrintHoeyde, nyX, nyY)){
spillerX = nyX;
spillerY = nyY;
}else{
System.out.println("Veien er blokkert!");
continue;
}
// Plukk opp gull
if(labyrint[spillerY][spillerX] == 'g'){
labyrint[spillerY][spillerX] = ' ';
spillerGull++;
System.out.println("Du tok 1 gull!");
if(spillerGull == labyrintGull){
System.out.println("Du tok alt gullet i labyrinten!");
break;
}
}
// Monster-kamp
if(labyrint[spillerY][spillerX] == 'm'){
labyrint[spillerY][spillerX] = ' ';
boolean kampFerdig = false;
boolean spillerTapte = false;
System.out.println("Et monster blokkerer veien din, og utfordrer deg til aa kaste hoeyeste terning.");
while(!kampFerdig){
System.out.println("Du og monsteret kaster terninger.");
int spillerKast = terningkast();
int monsterKast = terningkast();
System.out.println("Ditt kast: "+spillerKast);
System.out.println("Monsterets kast: "+monsterKast);
if(spillerKast > monsterKast){
System.out.println("Du kastet hoeyere enn monsteret, saa monsteret ga opp.");
break;
}else if(spillerKast == monsterKast){
System.out.println("Kastet var uavgjort.");
}else if(spillerKast < monsterKast){
System.out.println("Monsteret kastet hoeyere enn deg.");
if(spillerGull > 0){
System.out.println("Du brukte 1 gull til aa bestikke monsteret til aa ta en omkamp.");
spillerGull--;
labyrintGull--;
}else{
System.out.println("Du hadde ikke gull til aa bestikke monsteret. Monsteret spiste deg.");
spillerTapte = true;
break;
}
}
}
if(spillerTapte){
break;
}
}
}
tastatur.close();
System.out.println("Spiller-gull: "+spillerGull);
}
}
package inf100.h16.sem3;
/**
* INF 100 HOESTEN 2016
* Semesteroppgave 3, Oppgave 3
*
* Laster labyrint fra en fil og lar spiller gaa i labyrinten, plukke opp gull og sloss med monstre.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class LabyrintMonstre {
public static int terningkast(){
return (int) (1+6*Math.random());
}
public static boolean kanGaaTil(char[][] labyrint, int labyrintBredde, int labyrintHoeyde, int nyX, int nyY){
if(nyX<0||nyY<0||nyX>=labyrintBredde||nyY>=labyrintHoeyde)
return false;
if(labyrint[nyY][nyX] == '*')
return false;
return true;
}
public static char[][] lesLabyrintFraFil(String bane){
File fil = new File(bane);
try{
Scanner in = new Scanner(fil);
// Les inn bredde
if(!in.hasNextInt()){
System.out.println("Feil! Mangler bredde.");
in.close();
return null;
}
int labyrintBredde = in.nextInt();
if(labyrintBredde <= 0){
System.out.println("Feil! Bredde maa vaere minst 1.");
in.close();
return null;
}
in.nextLine();
// Les inn hoeyde
if(!in.hasNextInt()){
System.out.println("Feil! Mangler hoeyde.");
in.close();
return null;
}
int labyrintHoeyde = in.nextInt();
in.nextLine();
if(labyrintHoeyde <= 0){
System.out.println("Feil! Hoeyde maa vaere minst 1.");
in.close();
return null;
}
// Les brettet
System.out.println(labyrintBredde);
System.out.println(labyrintHoeyde);
char[][] labyrint = new char[labyrintHoeyde][labyrintBredde];
for(int y = 0; y < labyrintHoeyde; y++){
if(!in.hasNextLine()){
System.out.println("Feil! Filen har ikke nok linjer.");
in.close();
return null;
}
String linje = in.nextLine();
for(int x = 0; x < labyrintBredde; x++){
if(x >= linje.length()){
System.out.println("Feil! En linje er for kort.");
in.close();
return null;
}
labyrint[y][x] = linje.charAt(x);
}
}
in.close();
return labyrint;
}catch(FileNotFoundException e){
System.out.println("Feil! Filen kunne ikke åpnes.");
return null;
}
}
public static void main(String[] args) {
Scanner tastatur = new Scanner(System.in);
// Labyrint
System.out.println("Oppgi filen som labyrinten skal lastes fra:");
String labyrintBane = tastatur.nextLine().trim();
char[][] labyrint = lesLabyrintFraFil(labyrintBane);
if(labyrint == null){
tastatur.close();
return;
}
int labyrintBredde = labyrint[0].length;
int labyrintHoeyde = labyrint.length;
int labyrintGull = 0;
// Finn spillerposisjon
int spillerX = 0;
int spillerY = 0;
int spillerGull = 0;
for(int y = 0; y < labyrintHoeyde; y++){
for(int x = 0; x < labyrintBredde; x++){
if(labyrint[y][x]=='s'){