Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Excerpt

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

Del 1 (50%)

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.

...

  • 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)

Obs! For slagskip-spillet skal man ikke implementere angre og gjenta. Se egen artikkel for slagskip.

Del 2 (50%)

I denne delen skal du definere et grensesnitt (altså et interface) knyttet til innlesing av nye eller 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 en lett kan bytte til andre lagringsformat. Du skal lage minst én implementasjon som brukes av spillet dittstøtter ditt definerte filformat. Du må selvsagt også implementere en kommando for det, så brukeren kan starte et nytt spill evt. 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 .

Del 3

La spillet ditt implementere det allerede definerte grensesnittet ConsoleGame. ConsoleGame-grensesnittet definerer metoder for å initialisere, starte og styre spill. ConsoleGame-interfacet ser slik ut:

Code Block
public interface ConsoleGame {
	public void init();
	public void run();
	public Integer doLine(String input);
}
  • init()-metoden fjerner all informasjon om et evt. spill som er igang og gjør det klar til å starte et nytt. Denne må kalles før run()-metoden.
  • run()-metoden starter et nytt spill, i den forstand at det er klar til å ta imot kommandoer fra brukeren.
  • 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 skrives til System.out.

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 GameDriver-klassen:

Code Block
public static void main(String[] args) {
	ConsoleGame consoleGame = new DittSpill(); // evt. en annen konstruktør
	GameDriver gameDriver = new GameDriver(consoleGame);
	gameDriver.run();
} 

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.

JavaFX-apper for spillene (morsomt, men ikke obligatorisk)

Som for første trinn av spillene, som det er lenket til over, så har vi laget JavaFX-apper for spillene. I tillegg til grafisk visning av rutenettet, er det nå støtte for å

  • lese inn spill-tilstand fra fil, nettadresse (URL) eller fra innholdet i et tekstfelt
  • lagring av spill-tilstand til et tekstfelt (mest for debugging)
  • angre (undo) og gjenta (redo)
Image Added

Eksempel på JavaFX-app (Sokoban).

Øverst til venstre kan en velge en fil eller skrive inn en nettadresse som en laster spill-tilstanden fra. En kan også lagre nåværende tilstand til fil.

I midten til venstre kan en skrive inn spill-tilstanden i et tekstfelt, evt. lime inn noen en har klippet ut fra en annen applikasjon og starte spillet med denne tilstanden. En kan også kopiere spill-tilstanden som er i spill inn i tekstfeltet (mest for debugging) og evt. kopiere den over i en annen applikasjon.

Til høyre er det knapper for angring (undo) og gjenta siste angrede handling (redo).

For at din spill-implementasjon skal kunne kobles til vår JavaFX-app, så må spillklassen din implementere et tilhørende grensesnitt. Dette er en utvidet (og kanskje modifisert) utgave av grensesnittet fra trinn 1, ved at de utvider/bygger på to grensesnitt:

  • IPersistable (lagrebar) har metoder for lesing/skriving av tilstand fra/til hhv. InputStream og OutputStream. Metodene brukes av appen til lesing fra fil, nettadresse og tekstfelt og skriving til fil og tekstfelt.
  • IUndoable (angrebar) har metoder for angring (spole et hakk tilbake) og gjentaking av siste angrede handling (spole et hakk frem). Metodene er knyttet til tilsvarende knapper.

Spillklassen din må altså implementere både de spill-spesifikk metodene og de to metode-parene fra IPersistable og IUndoable.

For hvert spill har vi laget en "nedlastningspakke" som gjør det lett å importere de nødvendige filene med Digital Compendium-tillegget. Disse finner du under, én for hver app. Når emfs-pakken er importert så må du

  1. implementere det nødvendige grensesnittet og
  2. legge navnet på din spill-klasse inn i fxml-fila for app-en (se instruksjoner i fila).

Så kan du starte app-en ved å høyreklikke på java-fila med samme navn som fxml-fila og (som vanlig) velge Run As->Java Application.

Nedlastingspakker

Fellespakke (brukes av alle)
Code Block
emfs
/games/ #java #package
    FxmlApp.java                 @ git@github.com:hallvard/javafx/games/src/games/FxmlApp.java;
    FxmlBuilderFactory.java     @ git@github.com:hallvard/javafx/games/src/games/FxmlBuilderFactory.java;
    FxmlGame.java                @ git@github.com:hallvard/javafx/games/src/games/FxmlGame.java;
    IPersistable.java            @ git@github.com:hallvard/javafx/games/src/games/IPersistable.java;
    IUndoable.java                @ git@github.com:hallvard/javafx/games/src/games/IUndoable.java;
    IUpdateable.java            @ git@github.com:hallvard/javafx/games/src/games/IUpdateable.java;
    PersistableController.java    @ git@github.com:hallvard/javafx/games/src/games/PersistableController.java;
    UndoableController.java        @ git@github.com:hallvard/javafx/games/src/games/UndoableController.java;
    Persistable.fxml            @ git@github.com:hallvard/javafx/games/src/games/Persistable.fxml;
    Undoable.fxml                @ git@github.com:hallvard/javafx/games/src/games/Undoable.fxml;

    imagegrid/ #java #package
        ImageGrid.java        @ git@github.com:hallvard/javafx/games/src/games/imagegrid/ImageGrid.java;
        ImageGridGame.java        @ git@github.com:hallvard/javafx/games/src/games/imagegrid/ImageGridGame.java;
Sokoban
Code Block
emfs
/games/ #java #package
	sokoban/ #java #package
        sokoban2/ #java #package
            ISokoban.java    @ git@github.com:hallvard/javafx/games/src/games/sokoban/sokoban2/ISokoban.java;
            SokobanFX.java    @ git@github.com:hallvard/javafx/games/src/games/sokoban/sokoban2/SokobanFX.java;
            SokobanFX.fxml    @ git@github.com:hallvard/javafx/games/src/games/sokoban/sokoban2/SokobanFX.fxml;
            ;
        sample.sok    @ git@github.com:hallvard/javafx/games/src/games/sokoban/sample.sok;
        box_on_target16x16.png    @ git@github.com:hallvard/javafx/games/src/games/sokoban/box_on_target16x16.png;
        box16x16.png            @ git@github.com:hallvard/javafx/games/src/games/sokoban/box16x16.png;
        empty16x16.png            @ git@github.com:hallvard/javafx/games/src/games/sokoban/empty16x16.png;
        player_on_target16x16.png    @ git@github.com:hallvard/javafx/games/src/games/sokoban/player_on_target16x16.png;
        player16x16.png            @ git@github.com:hallvard/javafx/games/src/games/sokoban/player16x16.png;
        target16x16.png            @ git@github.com:hallvard/javafx/games/src/games/sokoban/target16x16.png;
        wall16x16.png            @ git@github.com:hallvard/javafx/games/src/games/sokoban/wall16x16.png;

Sudoku
Code Block
emfs
/games/ #java #package
	sudoku/ #java #package
		sudoku2/ #java #package
            ISudoku.java    @ git@github.com:hallvard/javafx/games/src/games/sudoku/sudoku2/ISudoku.java;
            SudokuFX.java    @ git@github.com:hallvard/javafx/games/src/games/sudoku/sudoku2/SudokuFX.java;
            SudokuFX.fxml    @ git@github.com:hallvard/javafx/games/src/games/sudoku/sudoku2/SudokuFX.fxml;
TicTacToe
Code Block
emfs
/games/ #java #package
	tictactoe/ #java #package
		tictactoe2/ #java #package
            ITicTacToe.java    @ git@github.com:hallvard/javafx/games/src/games/tictactoe/tictactoe2/ITicTacToe.java;
            TicTacToeFX.java    @ git@github.com:hallvard/javafx/games/src/games/tictactoe/tictactoe2/TicTacToeFX.java;
            TicTacToeFX.fxml    @ git@github.com:hallvard/javafx/games/src/games/tictactoe/tictactoe2/TicTacToeFX.fxml;

Slagskip

Se egen artikkelHensikten her er å vise at en kan lage en generell driver for mange typer spill, hvis disse spillene implementerer et felles grensesnitt med relevante metoder.

 

Include Page
Bunntekst for oppgaver
Bunntekst for oppgaver

...