webForumDet fria alternativet

Kan någon vara gullig och hjälpa mig?

Java

35 svar · 1 963 visningar · startad av PollyJuice

Medlem sedan mars 2006124 inlägg
Frågan#1

Hej!
Jag håller på att utveckla ett memoryspel för ett projekt i skolan, och jag har kört fast.

Jag försöker att skapa en ArrayList där man slumpar fram siffrorna 0-15. Varje siffra läggs i ett index i en array. Själva spelet ser ut som en tvådimensionell array, med 4*4 rutor. Varje ruta har en button med en icon som ser ut som baksidan på ett spelkort, och varje button tilldelas ett värde utifrån arrayen jag nyss nämnde.

Via en form.java ska man sen få fram att när man klickar på en button så ska programmet kolla vilket värde detta index har fått, och om index har t.ex värdet 1 så ska den blå figuren visas, om det har värdet 2 ska den röda figuren visas, osv.

Samma sak när man klickar på en andra ruta, varefter programmet ska utvärdera om bilderna är desamma, och om de är det, så ska visibility sättas till false. Är de däremot olika, ska figurerna bytas ut mot baksidesbilden... hänger ni med?

De första problemen är att NetBeans, som jag kodar i, klagar över ArrayList. Den vill ha ett semikolon någonstans, och jag fattar inte var eller varför. Därefter gnäller den över raden där arraylistans size multipliceras med math.random och lägger resultatet i int index, vilket sen läggs i array.

Titta på koden, snälla. Kan nån tipsa mig om vad jag gör för fel?

 public MemoryForm() {
        ArrayList() al =new ArrayList(16); //skapar en ny arraylist med en kapacitet på 16 platser
        for(int i =0; i<=15; i++) { // räknar upp i från 0-15
            int index = int al.size() * Math.random(); // slumpar fram ett värde mellan 0-15
            tabellen[i] = int al.size() * Math.random(); // slumpar fram ett värde mellan 0-15index; // skapar arrayen tabellen och stoppar in värdet på index (0-15) på plats 0-15
            al.remove(index); // minskar längden på al med 1
        }
        initComponents();
        //for ( alla 16 rutor )
        {
            MemoryImage mi = new MemoryImage( tabellen[i] );
            Spelplan.add( mi );
            mi.button.addActionListener( new ButtonActionListener(mi) );
        }
    }
    MemoryImage clickedFirst;
    MemoryImage clickedSecond;
    
    class ButtonActionListener implements ActionListener{
        MemoryImage memoryImage;
        ButtonActionListener(MemoryImage mi){
            this.memoryImage = mi;
        }
        public void actionPerformed(ActionEvent e) {
            if ( clickedFirst == null ) {
                clickedFirst = memoryImage;
                memoryImage.showImage();
                return;
            }
            if ( clickedSecond == null ){
                clickedSecond = memoryImage;
                return;
            }
            // tredje klicket.
            // lika
            memoryImage.setVisible(false);
            // olika memoryImage.showBaksida();
            
        }
    }
Medlem sedan mars 20007 896 inlägg
#2
        java.util.ArrayList al = new java.util.ArrayList(16);
        int index;
        for(int i =0; i<=15; i++) {
            index = al.size() * Math.random();
            tabellen[i] = al.size() * Math.random();
            al.remove(index);
        }

Du ska inte deklarera al.size() som en int, då metoden size() för ArrayList är deklarerad att returnera en int. Du säger också att kompilatorn "klagar på ArrayList" - men inte hur felmeddelandet lyder. Du har ett parentespar för mycket, åtminstone. Har du också importerat ArrayList från paketet java.util?

Borde vara svaret på dina frågor, men sen tycker jag att slumpgenereringen inte ser så bra ut. Fungerar den som du vill att den ska fungera?

Medlem sedan mars 2006124 inlägg
#3

Provade att ändra som du föreslog, och det verkar ta hand om arraylistproblemet. Nu har jag skrivit såhär:

public MemoryForm() {
java.util.ArrayList al = new java.util.ArrayList(16); //skapar en ny arraylist med en kapacitet på 16 platser
double[] tabellen = new double[16];
double index;
for(int i =0; i<=15; i++) { // räknar upp i från 0-15
index = al.size() * Math.random(); // slumpar fram ett värde mellan 0-15
tabellen = al.size() * Math.random(); // slumpar fram ett värde mellan 0-15index; // skapar arrayen tabellen och stoppar in värdet på index (0-15) på plats 0-15
al.remove(index); // minskar längden på al med 1
}
initComponents();
//for ( alla 16 rutor )
{
MemoryImage mi = new MemoryImage( tabellen );
Spelplan.add( mi );
mi.button.addActionListener( new ButtonActionListener(mi) );

}
}

Jag fick lägga till det som står i blått för att den inte kunde hitta vare sig index eller tabellen annars, samt att den klagade över possible loss of precision, då varken tabellen eller index var double. Nu får jag istället felmeddelandena att den inte hittar vare sig i, button, eller constructor MemoryImage(double).

Medlem sedan mars 20007 896 inlägg
#4

Det är för att din MemoryImage antagligen tar en int som parameter i konstruktorn.

"Possible loss on precision" är för att Math.random() returnerar en double, som du försöker sätta in i en int. Ta en titt på Math.round() t.ex. för att lösa det, så fort du deklarerar 'tabellen' och 'index' som heltal (int) igen så kommer kompilatorn inte att klaga på instansieringen av MemoryImage.

Medlem sedan mars 20007 896 inlägg
#5

För att förenkla din slumptalsgenerering, tycker jag att du ska ta en titt på java.util.Collections.shuffle(List list). Då kan du skapa en ArrayList, fylla den med talen 1-16 och sedan blanda (shuffle) listan. Snyggare lösning, enligt mig. Nu kanske jag hjälpte dig lite för mycket - om det är en skoluppgift... ;)

Medlem sedan mars 2006124 inlägg
#6

int[] tabellen = new int[16];
int index;
for(int i =0; i<=15; i++) { // räknar upp i från 0-15
index = Math.round (al.size() * Math.random()); // slumpar fram ett värde mellan 0-15
tabellen *= index; // stoppar in värdet på index (0-15) på plats 0-15 i tabellen
al.remove(index); // minskar längden på al med 1
}

found long, required int? Var kom long ifrån??? :q*

Medlem sedan mars 2006124 inlägg
#7

SPiN skrev:

För att förenkla din slumptalsgenerering, tycker jag att du ska ta en titt på java.util.Collections.shuffle(List list). Då kan du skapa en ArrayList, fylla den med talen 1-16 och sedan blanda (shuffle) listan. Snyggare lösning, enligt mig. Nu kanske jag hjälpte dig lite för mycket - om det är en skoluppgift... ;)

Nja, vitsen är ju att samma tal inte ska kunna uppstå två gånger. Jag hade från början löst det med en evighetslång kod där man jämförde resultatet av en slumpning med alla tidigare resultat, och om någon var lika, måste man upprepa slumpningen. Den koden funkade visserligen, men den tog upp ungefär en A4, och min lärare kunde inte hålla sig för skratt. Han föreslog att jag skulle använda mig av ArrayList istället, och genom att använda al.remove(index) så minskar storleken på al varje gång man kör igenom for-satsen, vilket gör att samma tal inte kan uppstå två gånger - jag vill ju inte att man ska råka få tre röda figurer och 5 blå i memoryspelet, det ska bara var två av varje.
Vilket kanske låter som en motsägelse till att arrayen ska slumpa fram 16 olika tal till 8 färger, men jag har tänkt att varje färg har två nummer, så att man vid klickandet av en knapp tänker som så att om värdet är 1 eller 9, ska den blå figuren visas, är det 2 eller 10 ska den röda visas, osv.

Medlem sedan mars 20007 896 inlägg
#8

Just det... Det finns två stycken Math.round(), den som tar en double som parameter returnerar ett flyttal... Du kan cast:a din double till en int, rakt av. Sorry att jag fick dig att snurra in dig i metoder som inte fungerar. :)

index = (int) (al.size() * Math.random());
Medlem sedan mars 2006124 inlägg
#9
index = (int)Math.round (al.size() * Math.random());

verkar funka, den blir iallafall godkänd av NetBeans...
Nästa problem blir istället de två första raderna i

MemoryImage clickedFirst;
    MemoryImage clickedSecond;
    
    class ButtonActionListener implements ActionListener{
        MemoryImage memoryImage;
        ButtonActionListener(MemoryImage mi){
            this.memoryImage = mi;
        }
        public void actionPerformed(ActionEvent e) {
            if ( clickedFirst == null ) {
                clickedFirst = memoryImage;
                memoryImage.showImage();
                return;
            }
            if ( clickedSecond == null ){
                clickedSecond = memoryImage;
                return;
            }
            // tredje klicket.
            // lika
            memoryImage.setVisible(false);
            // olika memoryImage.showBaksida();
            
        }
    }

där den vill ha en class eller en interface. Jag misstänker att något är fel med den form jag använder för att skapa ändra utseende på den knapp man trycker på, MemoryImage.java. Den har låst sig av gud vet vilken anledning. Koden ser ut såhär:

public class MemoryImage extends javax.swing.JPanel {
    public int imageNumber;
    public static final String[] imageNames = {"bla.gif", "gul.gif", "rod.gif", "gron.gif", "vit.gif", "svart.gif", "rosa.gif", "lila.gif"}; 
 
    /**
     * Creates new form MemoryImage
     */
    public MemoryImage(int imageNumber) {
        this.imageNumber = imageNumber;
        initComponents();
         
        URL bildUrl = getClass().getResource("memory/images/"+ "bildnamnet" );
        button.setIcon( new ImageIcon( bildUrl ));
        
        URL baksideURL = getClass().getResource("memory/images/"+ "baksida.gif" );
        button.setIcon( new ImageIcon( bildUrl ));
    }
    public void showBaksida(){
    button.setIcon( new ImageIcon( baksideUrl ));
    }
    public void showImage(){
    button.setIcon( new ImageIcon( bildUrl ));
    }
    }
Medlem sedan mars 20007 896 inlägg
#10

PollyJuice skrev:

Nja, vitsen är ju att samma tal inte ska kunna uppstå två gånger. Jag hade från början löst det med en evighetslång kod där man jämförde resultatet av en slumpning med alla tidigare resultat, och om någon var lika, måste man upprepa slumpningen. Den koden funkade visserligen, men den tog upp ungefär en A4, och min lärare kunde inte hålla sig för skratt. Han föreslog att jag skulle använda mig av ArrayList istället, och genom att använda al.remove(index) så minskar storleken på al varje gång man kör igenom for-satsen, vilket gör att samma tal inte kan uppstå två gånger - jag vill ju inte att man ska råka få tre röda figurer och 5 blå i memoryspelet, det ska bara var två av varje.
Vilket kanske låter som en motsägelse till att arrayen ska slumpa fram 16 olika tal till 8 färger, men jag har tänkt att varje färg har två nummer, så att man vid klickandet av en knapp tänker som så att om värdet är 1 eller 9, ska den blå figuren visas, är det 2 eller 10 ska den röda visas, osv.

Det är bara det att din kodsnutt där inte kommer att fungera. Du borde få ett IndexOutOfBoundsException, då din ArrayList inte kommer att ha 16 tomma platser. När du instantierar en ArrayList som du gör, sätter du bara kapaciteten på listan till 16 element. Den är fortfarande tom i verkligheten. Koden kommer alltså att kompileras, men inte att exekveras.

Du behöver inte heller ha kvar Math.round() i koden - den är där helt i onödan. Det räcker med det jag skrev i mitt förra inlägg.

Angående ditt nya problem, känns det som att klassen MemoryImage inte är tillgänglig. Det verkar inte som att du importerar den eller att den inte finns i samma paket.

Medlem sedan mars 2006124 inlägg
#11

Jag trodde att det funkade så att index ges det värde man får fram av att multiplicera kapaciteten på arraylist med math.random? Måste jag alltså ha ett innehåll i arraylist för att det ska funka?

Har bytt till den kod du föreslog utan round, det funkar alldeles utmärkt, tack. :)

Läste att filer kan låsa upp sig vid reboot. Ska testa det och försöka importera lämplig klass till den upplåsta filen.

Medlem sedan mars 20007 896 inlägg
#12

al.size() kommer alltid att vara 0, så länge det inte finns några element i listan.

Medlem sedan mars 2006124 inlägg
#13

Ahaaaaaa... *känner mig som en bimbo* :r

Medlem sedan mars 2006124 inlägg
#14

Har jag fattat rätt då om jag inbillar mig att följande kod

  for(int j=0; j<=15; j++){ //räknar upp j från 0-15
           al.add(j); //lägger in värdena 0-15 i arraylist
       }
       for(int i =0; i<=15; i++) { // räknar upp i från 0-15
            index = (int) (al.size() * Math.random()); // slumpar fram ett värde mellan 0-15
            tabellen[i] = index; // stoppar in värdet på index (0-15) på plats 0-15 i tabellen
            al.remove(index); // minskar längden på al med 1
        }

kommer att funka så att arraylist först fylls på med element, och därefter töms på dem igen alltefetersom storleken krymper? Eller kommer jag att få ett Indexoutofbounds för att storleken krymper utan att innehållet minskas?

Behöver jag lägga till ett al.remove(j) före jag tar bort ett index?

Medlem sedan mars 20007 896 inlägg
#15

Din slumpgenerering kommer fortfarande inte att fungera, dock. Du kommer att få duplikerad information i din array. Tänk så här: Första gången loopen körs sätts index till ett tal mellan 0 och 15. Andra gången loopen körs sätts index till ett tal mellan 0 och 14. Etc. Du har alltså ingen koll på om talet redan har blivit slumpat. Dessutom är risken att 0 förekommer flera gånger överhängade, då det är det lägsta talet. 0 har i varje loop möjligheten att bli slumpat, medan 15 enbart har möjlighet att slumpas en gång - nämligen i första loopen.

Som jag sade i ett tidigare inlägg, http://www.webforum.nu/showthread.php?p=1415708#post1415708 , så tycker jag att du skapar en ArrayList, fyller den med talen 1-16 och sedan blandar m.h.a. Collections.shuffle() - så är du garanterad att inga dubletter förekommer i arrayen.

Och du behöver absolut inte känna dig som en bimbo. :)

Medlem sedan sep. 2001961 inlägg
#16

Vad du borde göra är att skapa en enum med det 8 olika bilderna (eller en representation av dessa) och sedan skapa en arraylist med två av varje sort. Sedan använder du shuffle-metoden för att blanda.

Du gör problemet onödigt stort. Strunta i alla konstiga arrayer som ska hålla i värden. Gör spelet så verklighetstroget som möjligt. Om du har olika kort, skapa en klass som är kortet. Om du ska jämföra om två kort är samma, gör det genom att implementera en equals-metod i din MemoryCard-klass.

Bara så du vet målsättningen så går det att göra detta på 3 klasser, 109 rader kod... ;)

Medlem sedan mars 2006124 inlägg
#17

OK, jag gillar iden med enum och klasser. Jag läste på lite och tror att jag har fattat hur den biten går till. Jag är däremot inte helt säker på att jag gör rätt när jag försöker använda mig av toArray för att flytta den shufflade arraylistan till en nyskapad array. Stämmer det här?

java.util.ArrayList farger = new java.util.ArrayList(16);

enum Kort{bla, rod, gron, gul, vit, svart, lila, rosa}

Class MemoryKort{
public String namn;
public Kort farg;
}

Class MemoryBaksida{
public String namn;
public Baksida farg;
}

farger.add(bla, bla, rod, rod, gron, gron, gul, gul, vit, vit, svart, svart, lila, lila, rosa, rosa);
java.util.Collections.shuffle(List farger);

//vid det laget har jag en arraylist med 16 element = 2 exemplar vardera av 8 färger, i slumpad ordning

String[] tabellen = new String[16];
       farger.toArray[] tabellen;

//skapar arrayen tabellen och arraylistans element läggs i denna

Sen undrar jag hur jag ska visa korten i arrayen för användaren. Kan jag använda den kod jag hade tidigare

initComponents();
        {
            MemoryImage mi = new MemoryImage( tabellen[i] );
            Spelplan.add( mi );
            mi.button.addActionListener( new ButtonActionListener(mi) );
        }
    }
    MemoryImage clickedFirst;
    MemoryImage clickedSecond;
    
    class ButtonActionListener implements ActionListener{
        MemoryImage memoryImage;
        ButtonActionListener(MemoryImage mi){
            this.memoryImage = mi;
        }
        public void actionPerformed(ActionEvent e) {
            if ( clickedFirst == null ) {
                clickedFirst = memoryImage;
                memoryImage.showImage();
                return;
            }
            if ( clickedSecond == null ){
                clickedSecond = memoryImage;
                return;
            }
            // tredje klicket.
            // lika
            memoryImage.setVisible(false);
            // olika memoryImage.showBaksida();
            
        }
    }

och så i MemoryImage.java skriva

public class MemoryImage extends javax.swing.JPanel {
    public int imageNumber;
    public static final String[] Kort = {"bla.gif", "gul.gif", "rod.gif", "gron.gif", "vit.gif", "svart.gif", "rosa.gif", "lila.gif"}
public static final String[] Baksida = baksida.gif; 
 
    /**
     * Creates new form MemoryImage
     */
    public MemoryImage(int imageNumber) {
        this.imageNumber = imageNumber;
        initComponents();
         
        URL bildUrl = getClass().getResource("memory/images/"+ "bildnamnet" );
        button.setIcon( new ImageIcon( bildUrl ));
        
        URL baksideURL = getClass().getResource("memory/images/"+ "baksida.gif" );
        button.setIcon( new ImageIcon( bildUrl ));
    }
    public void showBaksida(){
    button.setIcon( new ImageIcon( baksideUrl ));
    }
    public void showImage(){
    button.setIcon( new ImageIcon( bildUrl ));
    }
    }
Medlem sedan mars 2006124 inlägg
#18

Eller kanske såhär, med all kod i en enda fil?

package memory;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.*;
import java.math.*;
import java.awt.*;
import javax.swing.ImageIcon;
import java.net.URL;

public class MemoryForm extends javax.swing.JFrame {
    /** Creates new form MemoryForm */
    
    public MemoryForm() {
java.util.ArrayList farger = new java.util.ArrayList(16);

enum Kort{bla, rod, gron, gul, vit, svart, lila, rosa}

public class MemoryKort extends javax.swing.JPanel {
public Kort farg;
}

public class MemoryBaksida{
public Baksida farg;
}

farger.add(bla, bla, rod, rod, gron, gron, gul, gul, vit, vit, svart, svart, lila, lila, rosa, rosa);
java.util.Collections.shuffle(List farger);

//vid det laget har jag en arraylist med 16 element = 2 exemplar vardera av 8 färger, i slumpad ordning

String[] tabellen = new String[16];
       farger.toArray[] tabellen;

//skapar arrayen tabellen och arraylistans element läggs i denna

public class MemoryImage {
        public MemoryImage(string kortfarg) {
        this.kortfarg = kortfarg;
        initComponents();
         
        URL bildUrl = getClass().getResource("memory/images/"+ Memorykort.Kort.farg);
        button.setIcon( new ImageIcon( bildUrl ));
        
        URL baksideURL = getClass().getResource("memory/images/baksida.gif" );
        button.setIcon( new ImageIcon( bildUrl ));
    }
    public void showBaksida(){
    button.setIcon( new ImageIcon( baksideUrl ));
    }
    public void showImage(){
    button.setIcon( new ImageIcon( bildUrl ));
    }
    }
{
            MemoryImage mi = new MemoryImage( tabellen[i] );
            Spelplan.add( mi );
            mi.button.addActionListener( new ButtonActionListener(mi) );
        }
    }
    MemoryImage clickedFirst;
    MemoryImage clickedSecond;
MemoryImage clickedThird;
    
    class ButtonActionListener implements ActionListener{
        MemoryImage memoryImage;
        ButtonActionListener(MemoryImage mi){
            this.memoryImage = mi;
        }
        public void actionPerformed(ActionEvent e) {
            if ( clickedFirst == null ) {
                clickedFirst = memoryImage;
                memoryImage.showImage();
                return;
            }
            if ( clickedSecond == null ){
                clickedSecond = memoryImage;
	memoryImage.showImage();
                return;
            }
           if(clickedThird==null){
            if(clicked.First.farg==clickedSecond.farg){
           memoryImage.setVisible(false);
}
          if(!clicked.First.farg==clickedSecond.farg){
memoryImage.showBaksida();
            
        }
}
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MemoryForm().setVisible(true);

            }
        });
    }
Medlem sedan mars 2006124 inlägg
#19

Om jag har en enda fil, som i posten ovan, får jag följande felmeddelanden:

  • enum Kort{bla, rod, gron, gul, vit, svart, lila, rosa} - - -> enum types must not be local
  • public class MemoryKort extends javax.swing.JPanel { - - -> illegal start of expression, ';' expected
  • public class MemoryBaksida{ - - - illegal start of expression, ';' expected
  • java.util.Collections.shuffle(List farger); - - -> ')' expected
  • public class MemoryImage { - - -> illegal start of expression, ';' expected

Några tips, någon? :q

Medlem sedan mars 20007 896 inlägg
#20

1: Du måste deklarera dina enum's i klassen, inte i en metod/konstruktor.
2-3: Du är fortfarande inne i din konstruktor. Du måste avsluta konstruktorn - så får du en s.k. inre klass av MemoryKort och MemoryBaksida.
3: Du har ingen klass eller enum som är döpt Baksida - vad jag kan se.
4: Du måste lägga till värdena till din ArrayList 'farger' var för sig, inte rada upp dom som du har gjort - samt att denna kod måste vara placerad i en metod, likaså måste anropet till Collections.sort() vara placerad i en metod. Du skriver också:

Collections.sort([b]List[/b] farger);

Ta bort List där, 'farger' är redan av typen List då det är en ArrayList.
5:

String[] tabellen = new String[16];
       farger.toArray[] tabellen;

Det ser lite suspekt ut - samt att koden inte är placerad i någon metod. Du behöver inte exportera din ArrayList till en array - du har all funktionalitet med ArrayList som array också har - plus en massa till.

Överlag är din kod ganska rörig, jag tycker att du ska omstrukturera den lite.
Lime tyckte att du behövde tre klasser - jag tycker att du klarar dig med två (och 89 rader kod ;)).
- Klassen Memory - som hanterar spelplanen
- Klassen MemoryButton - som hanterar knapparna samt spelarens val

När jag gjorde spelet lät jag Memory ärva av JFrame och placera ut alla MemoryButton's. MemoryButton lät jag ärva från JButton (enkelt att hantera knapptryckningar då) samt implementera ActionListener (enkelt att veta vilken knapp som blev tryckt).

I Memory skapar du alla MemoryButtons, lägger in dom i en ArrayList, shufflar dom och placerar sedan ut dom i en JPanel som använder förslagsvis GridLayout som layout manager - så hamnar knapparna som i en knappsats (4 x 4 i ditt fall, om du har 16 knappar).

274 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
124 ms — deklarationer (db)
0 ms — hämta statistik (cache)
146 ms — hämta tråd, inlägg och bilagor (db)
125 ms — ändringar (db)