You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 12 Next »

I denne oppgaven vil vi gå ut ifra allerede implementerte spill. Vi vil legge til nye kommandoer og anvende grensesnitt-mekanismen. Vi vil bygge på oppgavene TicTacToeSokoban og Sudoku

Del 1 (40%)

Her skal du implementere kommandoer for å angre (eng: undo) handlinger (legg, trekk, ...) og gjenta (eng: redo) handlinger som er angret. Hvis brukeren angrer en handling, så skal spillet settes tilbake til den forrige tilstanden, dvs. tilstanden før handlingen. Dersom brukeren gjentar en handling (altså angrer angringen) vil handlingen som brukeren angret bli utført på nytt.

Angre- og gjenta-logikken kan implementeres med to Stack-objekter som inneholder "handling"-objekter, dvs. objekter som inneholder informasjon om en brukerhandling. Når en handling er utført så legges den på angre-stack'en. Ved angring tas det øverste elementet av angre-stack'en, handlingen som dette objektet representerer reverseres og legges på gjenta-stack'en. Ved gjenta, så tas det øverste elementet av gjenta-stack'en, handlingen som dette objektet representerer utføres og legges (tilbake) på angre-stack'en. For å implementere angre og gjenta må en altså:

  • finne en måte å representere brukerhandlinger, dvs. lage en klasse som kan lagre informasjon om handlinger
  • implementere logikk for å reversere og gjenta handlingen som slike objekter representerer
  • administrere angre- og gjenta-stack'er som forklart over (eller tilsvarende logikk)

Del 2 (50%)

I denne delen skal du implementere lagring av spill og innlesing av tidligere lagrede spill, slik at en kan fortsette der en slapp, f.eks. med et vanskelig Sokoban-brett. Du må altså definere et egnet filformat, og støtte dette formatet både ved skriving til fil og lesing fra fil. Merk at det kun er nødvendig å lagre nå-tilstanden til spillet, en trenger ikke lagre tilstand knyttet til angring (undo). Det naturlige vil være å ha et tekstlig (i motsetning til binært) format, med én linje pr. rad i spillet og én eller flere tegn pr. rute i raden. Sokoban har forøvrig et definert standardformat (se http://sokobano.de/wiki/index.php?title=Level_format), som det kan være lurt å støtte for å forenkle bruk av eksisterende brett.

For å gjøre det enklere å bytte til et annet lagringsformat, så skal du definere et grensesnitt (altså et interface) knyttet til lagring og innlesing og lage minst én implementasjon som støtter ditt definerte filformat. Du må selvsagt også implementere en kommando for det, så brukeren både kan lagre og gjenoppta et tidligere lagret spill. Du skal også forklare hvordan du med en annen implementasjon kan støtte et annet lagringsformat og hvordan dette i så fall kan gjøres uten store endringer i hovedprogrammet. Som en ekstra utfordring kan du velge hvilket filformat som brukes basert på endelsen til fila som spillet lagres i.

Før du går i gang med denne delen kan det være lurt å ta en titt på wikisiden for Lesing fra og skriving til fil.

Del 3 (10%)

La spillet ditt implementere det allerede definerte grensesnittet ConsoleGame. ConsoleGame-grensesnittet definerer metoder for å initialisere, starte og styre spill. ConsoleGame-interfacet er vist under til venstre:

public interface ConsoleGame {
	public void init(String level);
	public void run(ConsoleOutput output);
	public Integer doLine(String input);
}
public interface ConsoleOutput {
	public void message(String message);
	public void error(String message);
}

Oppførselen til metodene er som følger:

  • init(String)-metoden fjerner all informasjon om et evt. spill som er igang og initialiserer det med informasjon fra String-argumentet. Du avgjør selv hvordan argumentet tolkes, men bør støtte filnavn. Denne må kalles før run()-metoden.
  • run(ConsoleOutput)-metoden starter et nytt spill, i den forstand at det er klar til å ta imot kommandoer fra brukeren. Kommandoene vil komme gjennom kall til doLine-metoden. All output fra programmet til brukeren skal formidles med kall til ConsoleOutput-argumentet sine message- og error-metoder, så dette objektet må lagres unna til siden.
  • Integer doLine(String)-metoden utfører en kommandolinje, som om den ble skrevet inn av brukeren. Returnverdien angir om spillet er ferdig og hva resultatet ble. Dersom returverdien er null, så er spillet fortsatt igang, dersom verdien er positiv så vant spilleren (evt. spiller 1), dersom verdien er negativ så tapte spilleren (evt. spiller 1) og dersom den er 0 så er resultatet udefinert evt. uavgjort. I løpet av kallet til doLine, så skal informasjon om (den nye) tilstanden til spillet formidles til ConsoleOutput-objektet sin message-metode.

Det er viktig å merke seg at all styring av spillet må skje gjennom doLine-metoden, inkludert å lese inn nye evt. tidligere spill fra fil, siden det ikke finnes noen spesifikk metode som gjør dette. Dette betyr at du må lage kommando-syntaks for dette, som fungerer ved siden av de andre kommandoene for å styre spillet. F.eks. kan en tenke seg følgende kommandoer for lagring og lesing av tilstanden til spillet:

  • > filnavn: lagrer tilstanden til spillet i filen ved navn filnavn
  • < filnavn: leser inn og (re)starter spillet lagret i filen ved navn filnavn
  • ... andre kommandoer for å styre spillet, f.eks. w for opp, s for ned, a for venstre, d for høyre eller koordinatpar x,y for å legge brikke i rutenett osv.

Det blir gitt ut en klasse (som ikke er klar ennå) som "driver" et spill som implementerer ConsoleGame-grensesnittet, som du kan bruke til å teste om implementasjonen din fungerer etter hensikten. Dersom denne klassen heter GameDriver og din spill-klasse heter MittSpill, så skal følgende main-metode kunne brukes for å kjøre ditt spill ved hjelp av ConsoleGameDriver-klassen:

public static void main(String[] args) {
	ConsoleGameDriver.main(DittSpill.class.getName(), <initielt brett eller null>);
} 

Hensikten her er å vise at en kan lage en generell driver for mange typer spill, hvis disse spillene implementerer et felles grensesnitt med relevante metoder. Vi har satt %-verdien lavt, ikke fordi del-oppgaven er raskt gjort, men fordi den kanskje er litt vanskelig...

 

 

SidetypeDekningsgradOmfangFerdig
Oppgave10010060

 

 

  • No labels