Laboration 4. Memory

Spelet Memory kan som bekant spelas av två eller flera spelare. Till spelet hör ett antal kort med samma baksida men med olika bilder på framsidan. Varje bild förekommer på exakt två kort. När spelet börjar läggs alla korten ut på bordet med baksidan uppåt. Spelarna får sedan i tur och ordning vända på två kort. Om de två korten har olika bilder vänds de tillbaka så att baksidan kommer uppåt. Nästa spelare får i så fall fortsätta. Om de två korten däremot har samma bild får spelaren ta korten från bordet och lägga dem i sin egen hög. Samma spelare får sedan fortsätta och vända två nya kort. En viss spelare får fortsätta så länge som han eller hon lyckas hitta kortpar med samma bild. Spelet fortsätter tills alla kort på bordet är borta. Den spelare som då har flest par har vunnit.

Uppgiften är att skriva ett datorprogram som låter användarna spela Memory. Istället för att ha kort på bordet skall korten visas på skärmen. Spelarna väljer kort genom att klicka på korten. I programmet skall det finnas ett fönster med ett antal kort. Korten skall placeras ut i rader. Programmet skall utformas så att antalet rader och kolumner kan bestämmas dynamiskt när man startar programmet.  I fönstret skall det också finnas två knappar som spelarna kan klicka på när de vill starta ett nytt spel respektive avsluta programmet. Programmet skall kunna hantera två spelare. De två spelarnas aktuella poäng, dvs. antalet kortpar spelarna har hittat, skall visas. Programmet skall hålla reda på vilken spelares tur det är och detta skall tydligt markeras i fönstret. Man kan t.ex. använda olika färg för att visa spelarnas poäng. Ett exempel på hur det kan se ut visas i följande figur i vilken Spelare 1 just har valt två kort som visade sig vara olika. I denna figur används gul bakgrundsfärg för att visa vems tur det är.

 

För att förenkla arbetet skall laborationen delats in i flera steg. När ett steg är klart skall man visa upp programmet för en handledare.

 

Steg 1, Hjälpklasser

Klassen Kort

 

I programmet skall man arbeta med kort. Detta görs enklast och tydligast om man har en separat klass Kort där varje objekt av klassen beskriver ett enstaka kort. Din uppgift är nu att konstruera klassen Kort . Den skall ha följande egenskaper:

OBS! Skriv inte några egna metoder med namnen getIcon och setIcon eftersom sådana skulle överskugga de metoder som ärvs från klassen JButton eller JColorfulButton och dessa behövs för att allt skall fungera på rätt sätt.

 

Tips: Den ärvda metoden setIcon kan användas för att ange vilken bild som skall visas på ett synligt kort. Om man anropar denna med parametern null kommer ingen bild att visas. Kortets bakgrundsfärg visas då istället (under förutsättning att egenskapen opaque är sann).
 

När klassen Kort är klar skall den testas med hjälp av det färdiga testprogrammet Korttest.

 

Klassen Verktyg

 

I programmet behöver man  slumpmässigt välja vilka bilder som skall användas och man behöver också placera ut dem på ett slumpmässigt sätt i fönstret. Då kan man ha nytta av en metod som flyttar om elementen i ett fält på ett slumpmässigt sätt. Din uppgift är därför nu att konstruera en klassmetod med namnet slumpOrdning. Metoden skall läggas i en separat klass med namnet Verktyg. Metoden skall ha resultattypen void.  Som enda parameter skall den ha ett fält där elementen är av typen Object (dvs. ett fält som kan innehålla referenser till objekt av vilken klass om helst.). När metoden anropas skall den placera om elementen i fältet på ett slumpmässigt sätt.

 

Tips. Använd ett temporärt fält inne i metoden och plocka ut ett element i taget från det ursprungliga fältet och placera in det på ett slumpmässigt ställe i det temporära fältet. Om platsen redan är upptagen måste du förstås slumpa fram en ny plats. När alla elementen är utplacerade kan du sedan kopiera det temporära fältet till det ursprungliga.

 

När klassen Verktyg med sin klassmetod slumpOrdning är klar skall den testas med hjälp av det färdiga testprogrammet Slumptest.

 

 

Steg 2, Utplacering av grafiska komponenter

 

I detta steg skall du börja skriva programmet Memory. Du skall placera ut de grafiska komponenterna i fönstret så att det kommer att se ut som i figuren ovan. Fönstrets storlek skall vara beroende på hur många rader och kolumner man vill använda. När programmet startar skall det med hjälp av dialogrutor fråga användaren hur många rader respektive kolumner som önskas. Använd klassen Kort från steg 1 för att beskriva korten.  (Det är ett krav.) Om användaren anger sådana storlekar att antalet nerladdade bilder inte räcker till skall programmet ge ett felmeddelande.

 

Bilder

 

Varje kort skall ha en bild. Bilderna kan hämtas från nätet, där det finns flera webbplatser man kan leta på. För att göra programmet lite roligare kan man hämta hem rörliga (animerade) bilder. Välj bilder som är lagom stora så att de ryms på ett kort i spelet. Skapa en ny mapp (bibliotek) med namnet bildmapp på din dator och placera alla bilder du laddar ner i denna mapp. Obs! Lägg inga andra filer i mappen. Hämta hem fler bilder än vad som på en gång ryms på spelplanen. Då behöver inte samma bilder användas varje gång man spelar. Du måste åtminstone hämta hem så många bilder att det räcker till en spelplan med sex rader och sex kolumner.

 

För att läsa in de nedladdade bilderna till programmet kan man använda standardklassen File. Man börjar med att skapa ett File-objekt som beskriver mappen med bilder:

 

  File bildmapp = new File("bildmapp");

 

Därefter kan man skapa ett fält med File-objekt där varje objekt beskriver en bildfil:


 
File[] bilder = bildmapp.listFiles();

 

För vart och ett av elementen i fältet bilder kan man sedan anropa metoden getPath för att få reda på namnet på motsvarande bildfil. Filnamnen används när man skapar de ImageIcon-objekt som korten skall ha. Löp igenom alla element i fältet bilder och skapa ett Kort-objekt för varje fil. Använd ett fält k för att hålla reda på korten. Allt detta utförs lämpligen i konstruktorn för klassen Memory.

 

Utplacering av kort

 

Placera inte ut korten i konstruktorn, utan skriv en separat metod nyttSpel som kan anropas när programmet startar samt varje gång användaren klickar på knappen Nytt. I denna metod skall ett antal kort slumpmässigt placeras ut på spelplanen. Antag att spelplanen skall innehålla n kort. Skapa då ett nytt fält med plats för n Kort och plocka slumpmässigt ut n/2  kort från fältet k (från förra avsnittet) och placera dem i de första n/2 positionerna i det nya fältet. (Anropa metoden slumpOrdning från steg 1 för fältet k och plocka därefter ut de n/2 första elementen.) Skapa sedan kopior av dessa kort och placera kopiorna i de sista n/2 positionerna i det nya fältet. Flytta slutligen om korten i det nya fältet på ett slumpmässigt sätt (anropa metoden slumpOrdning igen) och placera korten på spelplanen.

 

Lyssnare

 

Lägg till lyssnare för de båda knapparna Nytt och Sluta. Koppla också lyssnare till alla korten på spelplanen. I detta steg skall lyssnaren för korten göras mycket enkel: När användaren klickar på ett kort skall kortet bli synligt så att dess bild visas. Du kan då testköra programmet och se om korten placeras ut på rätt sätt.

Tips: För att bilden på ett kort skall bli synlig omedelbart när man klickar på kortet, kan man i lyssnaren först göra kortet inaktivt och sedan aktivt (enabled) igen.

 

 

Steg 3, Dynamik

 

I detta steg skall du fullborda programmet genom att utöka lyssnaren och lägga till en timer. Det skall fungera på följande sätt:

 

När en spelare har klickat på det första kortet skall dess bild visas. När en spelare har klickat på det andra kortet skall bilden på detta visas och båda korten skall vara synliga i 1.5 sekunder. (Tips: Använd klassen javax.swing.Timer.) Under denna tid skall övriga händelser i programmet spärras så att inget händer om spelarna klickar någonstans. (Tips: Använd en variabel av typen boolean, för att hålla reda på när timern är igång.) När tiden löpt ut skall de två korten, om de var olika, åter bli blåa och programmet skall markera att det är den andra spelarens tur. Om korten var lika skall de tas bort genom att rutorna görs vita. Samma spelare skall sedan få fortsätta och välja två nya kort. När alla korten har tagits bort skall programmet visa en dialogruta där det frågar om man vill starta ett nytt spel eller inte. Det skall också gå att avbryta ett spel och starta på nytt genom att klicka på knappen Nytt.

 

 

Steg 4, Frivilliga tillägg

 

Här ges exempel på några frivilliga tillägg som man kan göra för att programmet skall bli lite intressantare och för att man skall få mer övning i att programmera.

 

1. Olika antal spelare

 

Utforma programmet så att man kan ändra antalet spelare. Man skall kunna vara fler än två spelare. Det skall också vara möjligt att köra programmet med endast en spelare. Eftersom det då är meningslöst att räkna hur många par man hittat, skall man istället visa hur många gissningar man gjort. Man kan då köra flera gånger i följd och jämföra hur många försök som behövdes för att hitta alla paren.

 

2. Storlek, tid och ljud

 

Utforma programmet så att man kan ändra antalet rader och kolumner. Man skall också kunna ändra den tid som programmet väntar efter det att en spelare har  klickat på det andra kortet. (Tiden skall alltså inte alltid behöva vara 2 sekunder.) Gör det också möjligt att använda ljud och man så önskar. Om en spelare har hittat två kort som är lika skall det vara ett viss (positivt) ljud annars ett annat (negativt). Det går att hitta lämpliga ljudfiler genom att leta efter filer med suffixet .wav.

 

3. Kom ihåg inställningar

 

Lägg till en knapp (eller ett menyalternativ) med namnet "Spara". När användaren klickar på denna skall de aktuella inställningarna (antal spelare om du gjort tillägg nummer 1 och antal rader och kolumner, tidsintervall samt ljud på/av om du gjort tillägg nummer 2) sparas i en textfil med ett visst namn, t.ex. inst.dat. Varje gång man startar programmet skall det undersöka om filen med inställningar finns. Om så är fallet skall programmet läsa informationen i filen och initiera programmet på det sätt som det anges där.

 

4. Använd menyer

 

Programmet kan göras lite elegantare om man använder menyer. (Knapparna i grundversionen behövs då inte och kan tas bort om man så önskar) Lägg till två menyer "Spel" och "Inställningar". Menyn "Spel" skall (åtminstone) innehålla alternativen "Nytt spel" och "Avsluta". Menyn "Inställningar" skall  (åtminstone) innehålla alternativet "Antal spelare" (om du gjort tillägg nummer 1) och  alternativen "Storlek",  "Tid" och "Ljud" om du gjort tillägg nummer 2.  Om du gjort tillägg nummer 3 skall det också finnas ett alternativ "Spara".

 

5. Eget förslag

 

Du kanske har några egna idéer om hur programmet kan göras roligare.  Diskutera dem med din handledare innan du börjar.

Ett exempel kan vara att visa namnen på spelarna istället för att numrera dem.

 

Exempel

 

Ett exempel på hur det kan se ut när man kör en utökad version av programmet visas i nedanstående figur.

 

 

 

 

Dokumentation

När allt är klart skall laborationen lämnas in. Programmet skall vara snyggt redigerat och innehålla kommentarer som anger vad som görs i de olika avsnitten i koden.