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 ett rutnät. Programmet skall utformas så att antalet rader och kolumner kan väljas 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 i grundutförandet ha två spelare. De två spelarnas aktuella poäng, d.v.s. 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.

Memory, exempel utan tillägg

Memory, exempel utan tillägg

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. Er 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, d.v.s. 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 (se nedan) inte räcker till skall programmet ge ett felmeddelande.

Bilder

Varje kort skall ha en bild. Bilderna kan hämtas från nätet. Välj bilder som är lagom stora så att de ryms på ett kort i spelet. Lägg bildfilerna i en mapp med namnet CardImages. Denna mapp ska ligga i programmets arbetsmapp (aktuell mapp när programmet exekveras). Det måste åtminstone finnas så många bilder att det räcker till en spelplan med sex rader och sex kolumner.

För att läsa in 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("CardImages");

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 ImageIcon-objekt för varje fil. 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 för nytt parti. I denna metod skall ett antal kort slumpmässigt placeras ut på spelplanen. Antag att spelplanen skall innehålla n kort. Då behövs n/2 bilder. Skapa en kopia av arrayen som innehåller alla era ikoner. Anropa randomOrder i Tools-klassen. Låt de n/2 första ikonerna i den resulterande arrayen utgöra de bilder som används för korten. För var och en av dessa bilder skapa två kort och lägg alla n kort i en array. Anropa randomOrder för att lägga korten i slumpvis ordning. Placera ut korten på spelplanen enligt ordningen i den resulterande arrayen.

Lyssnare

Lägg till lyssnare till knapparna för nytt parti och avsluta. 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 nytt parti genom att klicka på resp. knapp.

Steg 4, Tillägg

Implementera minst ett av följande två tillägg:

  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. Ljudeffekter och valbar storlek och tid Utforma programmet så att man kan ändra antalet rader och kolumner inför nästa parti. 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 1,5 sekunder.) Lägg också till möjligheten att slå på ljudeffekter. 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 .waw. Ljudfilerna ska vara "wav"-filer och heta "yes.wav" och "no.wav" och ligga i programmets arbetsmapp.

Implementera också minst ett av följande två tillägg:

  1. Kom ihåg inställningar Lägg till en knapp (eller ett menyalternativ, se nedan) med namnet "Spara". När användaren klickar på denna skall de aktuella inställningarna (antal spelare om du gjort tillägg nummer 1 ovan och antal rader och kolumner, tidsintervall samt ljud på/av om du gjort tillägg nummer 2 ovan) sparas i en textfil med ett bestämt namn. 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.

  2. 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 "Game" och "Settings". Menyn "Game" skall innehålla alternativen "New Game" och "Quit". Menyn "Settings" skall innehålla alternativet "Number of Players" (om du gjort tillägg nummer 1 ovan) och alternativen "Size", "Time" och "Sound" om du gjort tillägg nummer 2 ovan.

Memory på en variant av programmet med tillägg

Memory på en variant av programmet med tillägg

Vad ni ska lämna in

Skicka in er källkodsfiler (d.v.s. .java-filer) och inget annat. Alla filer ska skickas lösa, d.vs. ej inuti .zip eller dylikt).

Placera inte era java-filer i något paket, d.v.s. de ska inte innehålla någon rad package .... Det förenklar för oss när vi ska testköra era program.

Tänk på att följa de allmänna riktlinjerna för programmeringsstil som anges på sidan Laborationer.