Laboration 2
Mål
- Att förstå hur man med hjälp av
interface
kan specificera gränssnittet (beroendet) mellan två programdelar och hålla
det litet.
- Att förstå mönstret Model-View-Control och att tillämpa mönstret
i en uppgift med Model för sig och View+Control tillsammans i en klass.
- Att kunna hantera många knappar med lyssnare på ett
smidigt sätt samt att bygga upp ett enkelt grafiskt gränssnitt.
- Att programmera logiken i ett enkelt spel på ett snyggt och tydligt
sätt.
- Att förstå begreppet Mock object och göra ett sådant.
Uppgifter
Model
Välj ett enkelt spel som spelas på en kvadratisk rutindelad spelplan
genom att man väljer en ruta i taget.
Exempel på såna spel: Femtonspelet, 3x3-luffarschack (TicTacToe),
Memory, Othello. Skriv en klass som implementerar en spelmodell enligt
följande interface:
public interface Boardgame {
public boolean move(int i, int j); //returnerar true om draget gick bra, annars false
public String getStatus(int i, int j);
public String getMessage();
}
Varje drag i spelet utförs genom att man väljer en ruta. Spelets
ställning uppdateras då inuti klassen och kan avläsas position för
position genom metoden getStatus(i,j) . Anrop av
getMessage() ger ett aktuellt meddelande som säger om
draget gick bra eller ej. Spelklassen ska vara helt fri från grafik
och utgör modelldelen i Model-ViewControl. Spelklassen kan användas
tillsammans med en textbaserad ViewControl-del eller en grafisk.
Om ni väljer ett tvåpersonersspel så måste modellen hålla reda
på vems tur det är och meddela detta genom getMessage() .
Vartannat lyckat drag tolkas som spelare1 och vartannat är spelare2.
Spelmodellens uppgift är att tillhandahålla metoder
som behövs för att man ska kunna spela spelet. Spelet spelas genom
många anrop av metoderna.
De detaljerade anvisningar för modellen som följer kommer att att
avse Femtonspelet. TicTacToe har samma svårighetsgrad,
Memory är lite jobbigare och Othello är rätt mycket jobbigare.
TicTacToe ska implementeras med en utplaceringsfas och en
"flyttfas". Spelet ska alltså inte ta slut när 3 + 3 pjäser är utplacerade utan
fortsätta genom att en användare i taget flyttar en pjäs.
Uppgift 1 – Implementera ett Femtonspel
Läs åtminstone t.o.m. uppgift 2 noga (testen av modellen)
innan ni börjar!
Känner du inte till Femtonspelet? Läs då på wikipedia:
http://sv.wikipedia.org/wiki/Femtonspel .
Kursledarens femtonspel kan provköras här:
Kör Femtonspelet
Skriv en klass
// OBS! Det behövs inga import-satser i FifteenModel.
// FifteenModel innehåller ingen grafik !!!
class FifteenModel implements Boardgame {
// Implementera Boardgame-metoderna
// Deklarera variabler och övriga metoder som ni anser behövs
// som behövs för ett femtonspel
}
Låt Boardgame-metoderna vara public . Alla andra variabler
och metoder får vara private . Exempel på variabler som
kan behövas är
private String currentMessage = "No message yet";
private String[][] status = new String[4][4]; // spelplanen
private int iemp, jemp; // index till den tomma rutan
Spelaren väljer en ruta som ligger intill den tomma. Då flyttas
den valda rutan till den tomma platsen.
- När Femtonspelet startar ska sifforna vara i slumpmässiga positioner.
Kan ordnas genom att man placerar ut dem i ordning och sen gör slumpmässiga
anrop av move(i,j) . Om man slumpar placeringen direkt
finns risk att spelet inte går att lösa.
- Det krävs inte att meddelande om att spelet är löst ges.
Kom ihåg: Inga knappar, färger, fönster eller annan
grafik i modellklassen. Studera testprogrammet och körningen av det noga!
Uppgift 2 – Testa FifteenModel
Provkör ert spel med följande testprogram som inte ska ändras alls.
Testprogrammet finns också att hämta här:
Text15.java.
import java.util.*;
class Text15 {
public static void main(String[] u) {
Scanner scan = new Scanner(System.in);
Boardgame thegame = new FifteenModel(); // new
System.out.println("\nVälkommen till femtonspelet\n");
while (true) {
// Skriv ut aktuell ställning
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++)
System.out.print(" " + thegame.getStatus(i,j)); // getStatus
System.out.println();
}
System.out.println();
System.out.print("Ditt drag: ");
int i = scan.nextInt(); // hämta heltal från terminalfönstret
int j = scan.nextInt();
thegame.move(i,j); // move
System.out.println(thegame.getMessage()); // getMessage
}
}
}
Studera testprogrammet noga och titta särskilt på att kommunikationen
med modellklassen sker endast genom metoderna i interfacet.
Modellen skapas på den första kommenterade
raden. Gränssnittets metoder anropas för att visa spelets ställning,
att utföra drag och att se på aktuellt meddelande.
I Text15 visas också hur man i Java får inmatning från
ett terminalfönster med hjälpklassen Scanner .
Klicka här för att få se en körning av Test15:
Text15-demo.
Det är rätt jobbigt att spela femtonspelet i ett terminalfönster.
Det blir mycket trevligare i den grafiska varianten.
Uppgift 3 – View-Control
Skriv en grafisk klass som visar och spelar ett nxn-"rutspel"
(n ska vara parameter) av typen Boardgame .
Klassen ska ha nxn knappar som representerar
rutorna. Ett meddelandefält ska också finnas där resultatet av
anrop av getMessage() visas.
Spelet spelas enligt interfacet Boardgame ,
endast metoderna i Boardgame får användas.
Själva spelet går till så att användaren klickar på en ruta och i och j
avläses. Därefter anropas metoderna i modellen: Först move(i,j)
och sedan getMessage() och sen eventuellt
getStatus(i,j) för uppdatering av alla knapparna.
Här är ett förslag på start av ViewControl
// lämpliga import-satser här
class ViewControl extends JFrame implements ActionListener {
private Boardgame game;
private int size;
private Square[][] board; // Square är subklass till JButton
private JLabel mess = new JLabel();
ViewControl (Boardgame gm, int n){ // OK med fler parametrar om ni vill!
...
}
Förslag
- En subklass till
JButton som lagrar indexen i
och j rekommenderas.
- Testa klassen innan den är helt klar genom att låta knapptryckningarna
skriva ut texter av typen
"Tryck på knapp 3 1"
i terminalfönstret.
Man kan vänta med att införa Boardgame tills den testen är klar,
eller så sätter man Boardgame -objektet till null
till att börja med.
- Låt alla rutor i spelet ha samma färg eller välj två färger och gör
det schackrutigt. Texten på rutorna ska förstås kunna varieras.
Uppgift 4 – Sätt ihop
Sätt ihop en FifteenModel och en View-Control till ett spelbart spel.
Uppgift 5 – Ett Mock Object för ytterligare ett spel
Implementera Boardgame för ytterligare ett spel men
utan spelets funktionalitet, som ett Mock Object.
Ingen logik alls behövs och metoderna kan göra nästan ingenting.
De kan returnera samma svar hela tiden, bara svaren är av rätt typ.
Sätt ihop med ViewControl!
Att redovisa för grunduppgift
- En spelmodellsklass som kommunicerar enligt gränssnittet
Boardgame . Ingen grafik får finnas i den klassen.
- Körning av ett textbaserat program eller
main –metod i
spelmodellklassen som testar spelet. Det går bra att köra det givna
programmet Text15 ovan.
- En generell ViewControl-klass med en rutindelad kvadratisk (nxn)
spelplan som spelar ett spel enligt interfacet
Boardgame .
n är parameter när spelplanen skapas.
- Ett program som sätter ihop Model enligt 1 och ViewControl till ett
spelbart grafiskt spel.
- En mini-implementation i form av ett "Mock Object" av en annan
spelmodell än den ni valt i 1 och en demo med ViewControl av detta spel.
- UML-klassdiagram för allt. Tag med de publika metoderna för varje
klass men inga variabler. Metodernas parametrar behöver inte vara med.
När handledaren är nöjd, be om hans/hennes underskrift på ditt kvittensblad!
Kvittensbladet finns för utskrift på kurshemsidan under Laborationer.
Extrauppgift för högre betyg
Här finns två alternativ, välj ETT av dem:
- Välj ett annat rutspel (t.ex. TicTacToe) än det i grunduppgiften,
implementera det som ett fullständigt
Boardgame , gör ett spelbart
spel med hjälp av ViewControl-klassen. Textbaserad test rekommenderas
men behöver inte redovisas. Det är bra teknik att testa programdelar
var för sig. Samma ViewControl används alltså även till detta
spel. TicTacToe ska implementeras med en utplaceringsfas och en
"flyttfas". Spelet ska alltså inte ta slut när 3 + 3 pjäser är utplacerade utan
fortsätta genom att en användare i taget flyttar en pjäs.
- Om ni väljer Memory eller Othello eller något annat spel med
samma svårighetsgrad i grunduppgiften så gäller det som extrauppgift också.
Fråga gärna kursledaren om ni är osäkra på hur svårt det måste vara!
Det är tillåtet att ändra gränssnittet så att det passar ert valda spel
bättre än det som beskrivs i uppgiften ovan. All kommunikation mellan
modell och view-control måste ske genom ett fåtal väl genomtänkta gränssnittsmetoder.
Det är också tillåtet att ge ViewControl ett utseende som passar det spel
ni har valt.
Vid redovisningen måste ni förstå idén med en enda ViewControl-klass för alla
tillämpningar och kunna redogöra för den.
|