Laboration 3. 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

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.


 

Steg 1, Hjälpklasser

Klassen Card

 

I programmet skall man arbeta med kort. Detta görs enklast och tydligast om man har en separat klass Card där varje objekt av klassen beskriver ett enstaka kort. Din uppgift är nu att konstruera klassen Card . 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 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 Card är klar skall den testas med hjälp av det färdiga testprogrammet Cardtest.

 

 

Klassen Tools

 

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 en array på ett slumpmässigt sätt. Din uppgift är därför nu att konstruera en klassmetod med namnet randomOrder. Metoden skall läggas i en separat klass med namnet Tools. Metoden skall ha resultattypen void.  Som enda parameter skall den ha en array där elementen är av typen Object (dvs. en array som kan innehålla referenser till objekt av vilken klass om helst.). När metoden anropas skall den placera om elementen i arrayen på ett slumpmässigt sätt.

 

Tips. Använd en temporär array inne i metoden och plocka ut ett element i taget från den ursprungliga arrayen och placera in det på ett slumpmässigt ställe i den temporära arrayen. 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 den temporära arrayen till den ursprungliga.

 

När klassen Tools med sin klassmetod randomOrder är klar skall den testas med hjälp av det färdiga testprogrammet Randomtest.

 

 

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 Card 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 (folder) med namnet mypictures 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 (som beskrivs i avsnitt 16.6 i kursboken). Man börjar med att skapa ett File-objekt som beskriver mappen med bilder:

 

  File folder= new File("mypictures");

 

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


 
File[] pictures = folder.listFiles();

 

För vart och ett av elementen i arrayen pictures 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 arrayen pictures och skapa ett Card-objekt för varje fil. Använd en  array allCards 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 newGame 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å en ny array med plats för n Card-objekt och plocka slumpmässigt ut n/2  kort från arrayen allCards  (från förra avsnittet) och placera dem i de första n/2 positionerna i den nya arrayen. (Anropa metoden randomOrder från steg 1 för arrayen 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 den nya arrayen. Flytta slutligen om korten i den nya arrayen på ett slumpmässigt sätt (anropa metoden randomOrder 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 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, Tillägg

 

Här ges exempel på några tillägg som man kan göra för att programmet skall bli lite intressantare. Det är obligatoriskt att göra tillägg nummer 1 eller 2 samt tillägg nummer 3 eller 4. (Det rekommenderas förstås att du gör alla tilläggen.)

 

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). Hur man spelar upp ljud i ett Javaprogram beskrivs i kursboken i avsnitt 15.5. 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. options.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. Frivilligt 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

Dokumentationen skall  innehålla programtexten. Programmet skall vara snyggt redigerat och innehålla kommentarer som anger vad som görs i de olika avsnitten i koden. Dokumentationen skall lämnas in via Fire.