Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Excerpt

Oppgaven handler om en TicTacToe-klasse som holder logikken representasjon, logikk og funksjonalitet for å la to spillere spille 'Tre på rad' (Tic-Tac-Toe) gjennom konsollenvia en JavaFX-applikasjon.

Oppgaven handler om en TicTacToe-klasse, som håndterer nødvendig logikk for å kunne spille 'Tre på rad'. I Del 1 skal du implementere logikken som testes av referert JExercise-kode. I Del 2 av oppgaven skal klassen utvides med støtte for å la spillerne (etter tur) taste inn ønsket trekk spillet Tripp-trapp-tresko og klassen TicTacToeTicTacToe-klassen kapsler inn brettet og har metoder for å utføre trekk og sjekke om spillet er avsluttet, og dekkes av del 1 og 2.  I del 3 skal du implementere metoder i klassen din slik at den kan brukes av en JavaFX-applikasjon som er forhåndslagd. Da vil det bli et fullt fungerende spill som tar tekstlig input. Spillerne taste inn ønsket trekk etter tur helt til en spiller har vunnet eller spillet avsluttes uavgjort. Du står fritt til å implementere dette hvordan du vil, men her følger et forslag. 

Del 1 - Representasjon av brett og spiller

Tilstanden i TicTacToe-objekter er som følger:

  • gridString - en streng som holder styr på hvilke brikker som er lagt på de ulike posisjonene på brettet, enten "X", "O" eller " " (sistnevnt tomme streng er for tomt felt). Denne strengen vil ha lengde 9 der de tre første tegnene svarer til den første raden, de tre neste til den andre raden og de tre siste til den tredje raden i brettet. Mao vil strengen være lik "         " (tom streng med lengde 9) rett etter spillet har startet, være lik "  X      " like etter at spiller "X" har plassert en brikke oppe i høyre hjørne (x=2, y=0) og deretter lik "  X    O " like etter at spiller "O" har plassert en brikke i midten nede (feltet må forøvrig være public slik at JExercise-testen får tilgang til dette).

TicTacToe-klassen må ha metodene, getStringIndexForCoordinates, makePlacement, hasWon og changePlayer, med følgende oppførsel:

todelt: Den ene er brettet, dvs. hvilke ruter som er tomme, eller har x og o i seg, og den andre er hvilken spiller sin tur det er.

Du står fritt til å velge hvordan tilstanden realiseres med felt i klassen, men et alternativ er å bruke en tegnsekvens på 3x3 = 9 tegn (altså datatypen char) lagret i et felt av typen String eller StringBuilder og bruke tegnene 'x', 'o' (brikkene) og ' ' (tom rute) for å representere rutene. Spilleren som har turen kan representeres med brikken som han/hun legger, altså en char som er 'x' eller 'o'. Nedenfor ser du eksempler på String'er og tilsvarende brett.

Start-tilstand: "         " (ni mellomrom)

Code Block
   |   |   
-----------
   |   |   
-----------
   |   |   

Spiller 'x' har plassert en brikke øverst i midten: " x       "

Code Block
   | x |   
-----------
   |   |   
-----------
   |   |   

Spiller 'o' har plassert en brikke i slutten av andre rad: " x   o   "

Code Block
   | x |   
-----------
   |   | o 
-----------
   |   |   

Lenger ut i spillet: " x  xo xo"

Code Block
   | x |   
-----------
   | x | o 
-----------
   | x | o 

TicTacToe-klassen må ha følgende metoder:

  • char getCellint getStringIndexForCoordinates(int x, int y) - hjelpemetode som returnerer returnerer verdien til ruten på posisjon x, y.
  • boolean makePlacementsetCell(String playerchar c, int x, int y) - beregner renta og legger det til konto-beløpet
  • String hasWon() 
  • String changePlayer(String player) 

 

Tilstanden i Rectangle-objekter er ikke spesifisert eksplisitt, men må velges slik at metodene nedenfor kan implementerers. Merk at alle metodene jobber med heltallsstørrelser.

Rectangle-klassen har metoder for å spørre om tilstanden og endre tilstanden. Spørremetodene dekker høyde og bredde og koordinatene til øverste venstre og nederste høyre hjørne og om rektanglet inneholder spesifikke punkt(er). Endringsmetodene dekker utviding ved å legge til punkter.

Logikken til metodene må tilfredsstille følgende krav:

  • et Rectangle-objekt er tomt i starten
  • et tomt Rectangle-objekt skal returnere 0 for alle get-metodene (minX, minY, maxX, maxY), true for isEmpty og false for contains-metodene.
  • et punkt har bredde og høyde lik 1, så dersom en legger punktet x,y til et tomt Rectangle-objekt, så skal getMinX og getMaxX returnere x, getMinY og getMaxY skal returnere y og getWidth og getHeight skal returnere 1.
  • når en utvider et Rectangle-objekt med en av add-metodene, så skal ikke rektanglet bli større enn nødvendig.

Spørremetoder:

  • int getMinX() og int getMinY() - returnerer henholdsvis x- og y-koordinatene til punktet med lavest x,y-verdier som er inneholdt i dette rektanglet. Dersom dette rektanglet er tomt, så skal 0 returneres.
  • int getMaxX() og int getMaxY() - returnerer henholdsvis x- og y-koordinatene til punktet med høyest x,y-verdier som er inneholdt i dette rektanglet. Dersom dette rektanglet er tomt, så skal 0 returneres.
  • int getWidth() og int getHeight() - returnerer henholdsvis bredden og høyden til rektanglet. Begge skal returnere 0, dersom dette rektanglet er tomt.
  • boolean isEmpty() - returnerer true om rektanglet er tomt, dvs. om bredden og/eller høyden er 0.
  • boolean contains(int x, int y) - returnerer true om punktet x,y er inneholdt i dette rektanglet, og false ellers.
  • boolean contains(Rectangle rect) - returnerer true om hele rect, dvs. alle punktene i rect er inneholdt i dette rektanglet, og false ellers. Dersom rect er tomt, så skal false returneres.

Endringsmetoder:

  • boolean add(int x, int y) - utvider (om nødvendig) dette rektanglet slik at det (akkurat) inneholder punktet x,y. Etter kallet skal altså contains(x, y) altså returnere true. Returnerer true om dette rektanglet faktisk ble endret, ellers false.
  • boolean add(Rectangle rect) - utvider (om nødvendig) dette rektanglet slik at det (akkurat) inneholder hele rect-argumentet. Returnerer true om dette rektanglet faktisk ble endret, ellers false. Dersom rect er tomt, så skal dette rektanglet ikke endres.

Andre metoder:

  • Rectangle union(Rectangle rect) - returnerer et nytt Rectangle-objekt som tilsvarer kombisjonen av dette rektanglet og rect-argumentet. Alle punktene som finnes i ett av rektanglene skal altså være inneholdt i rektanglet som returneres.

Del 1 - Indre logikk (50%)

Tegn et objekttilstandsdiagram for en tenkt bruk av Rectangle-klassen. Velg en sekvens av kall som bruker alle fire endringsmetoder.

JExercise-testkode for denne oppgaven finner du her: objectstructures/TicTacToeTest.java.

 

Del 2 - Fullt fungerende spill (50%)

Skriv Java-kode for Rectangle-klassen med oppførsel som er beskrevet over.

Lag en passende toString()-metode og et hovedprogram, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme sekvens av kall).

 

  • - setter ruten i posisjon x, y til c. Metoden må sjekke om ruten er ledig før brettet oppdateres (okkuperte ruter kan ikke overskrives) og returnerer true hvis en ny brikke har blitt lagt på, false ellers.
  • boolean isOccupied(int x, int y) - returnerer true hvis ruten på posisjon x, y har en brikke og false ellers.
  • char getCurrentPlayer() - returnerer spilleren/brikken som har turen
  • String toString() - returnerer en String-representasjon av brettet, som gjerne kan likne på rutenett-eksemplene over, uten at dette er et krav som testes.

Det kan være en fordel å implementere en metode som mapper fra x- og y-koordinater til riktig indeks i String eller StringBuilder-objektet, men dette kreves ikke (i.e. det er fint mulig å implementere det på andre måter):

Del 2 - Logikk for spillets gang

TicTacToe-klassen utvides med metodene, isFinished(), isWinner(char), hasWinner() og play(), med følgende oppførsel:

  • void play(int x, int y) -setter ruten på posisjon x, y på brettet til tegnet til spilleren som utfører trekket (angis av player-feltet) og oppdaterer hvilken spiller som skal utføre det neste trekket.
  • boolean isWinner(char c) - returnerer true om spiller med brikke c har vunnet, false ellers.
  • boolean hasWinner() - returnerer true om spiller har en vinner, false ellers.
  • boolean isFinished() - returnerer true om spillet har en vinner eller brettet er blitt fylt og false ellers. En spiller har vunnet når den har lagt tre brikker på rad, enten horisontalt, vertikalt eller diagonalt.

Del 3 - Fullt fungerende spill, med interaksjon og JavaFX

Det er laget en JavaFX-applikasjon som i praksis gjør to ting: den tar inn tekstlig input fra brukeren og endrer tilstanden i TicTacToe-objektet basert på dette, og den viser spillets toString()-metode i applikasjonsvinduet. For at applikasjonen skal være kjørbar med TicTacToe, må følgende gjøres:

  • GameController, deklarer spillet ditt og initialiser det slik kommentarene i koden forklarer. 
  • TicTacToe, lag en metode void getInput(String in), som tar inn bruker-input (som kommer fra applikasjonen), og endrer tilstanden på spillet tilsvarende. Her kommer det altså inn posisjonen for neste trekk, som så skal bli utført. Formatet på strengen er valgfri, så "21", "2 1", eller "x2y1" vil fungere. Bestem deg for et format, og skriv kode for dette i metoden.
  • Når spillet er ferdig, skal spillerne få vite dette. GameController bruker TicTacToe sin toString()-metode for å vise spillets tilstand. Oppdater denne metoden slik at den returnerer en String som sier at spillet er over og hvem som vant (eller uavgjort) når dette skjer.

Du kan nå kjøre applikasjonen (Game.fxml > Run As > FXML Application) og teste spillet ditt.

Demonstrer spillet ditt for stud.assen din for å få poeng på del 3. Ekstra poeng gis hvis du klarer å slå han / henne (wink)

Met hjelp til kjøring av JavaFX og generelt om øvinger finner du i Hjelp til øvinger.

Include Page
Bunntekst for oppgaver
Bunntekst for oppgaver

  Include PageBunntekst for JExercise-oppgaverBunntekst for JExercise-oppgaver