Den Inhalten aus einer ArrayList Bilder zuweisen (Kartenspiel)

Linjutsu

Mitglied
Ich möchte ein Uno Ähnliches Spiel programmieren und möchte dafür meinen Objekten in der ArrayList Bilder zuweisen. Dafür habe ich mehrere Klassen vorbereitet und auch schon den Kartenstapel mit allen Karten erstellt. Jetzt möchte ich diesen Karten noch die richtigen Bilder zuweisen, um diese dann in einem Label auszugeben. Ich wollte dazu eine Methode erstellen, die die Karte in meiner ArrayList (Kartendeck) darauf prüft, welche Farbe und welches Symbol abgebildet ist. Ich weiss jedoch nicht, wie ich das angehen sollte :/

Dafür habe ich folgendes vorbereitet:
Java:
class Bilder {
  public String logo = "Uno Bilder/UNO_Logo.png";
  public String karten_rot[] = {"Uno Bilder/rot 0.png", "Uno Bilder/rot 1.png", "Uno Bilder/rot 2.png","Uno Bilder/rot 3.png", "Uno Bilder/rot 4.png", "Uno Bilder/rot 5.png", "Uno Bilder/rot 6.png", "Uno Bilder/rot 7.png", "Uno Bilder/rot 8.png", "Uno Bilder/rot 9.png", "Uno Bilder/rot aussetzen.png", "Uno Bilder/rot retoure.png", "Uno Bilder/rot +2.png"};
  public String karten_blau[] = {"Uno Bilder/blau 0.png", "Uno Bilder/blau 1.png", "Uno Bilder/blau 2.png", "Uno Bilder/blau 3.png", "Uno Bilder/blau 4.png", "Uno Bilder/blau 5.png", "Uno Bilder/blau 6.png", "Uno Bilder/blau 7.png", "Uno Bilder/blau 8.png", "Uno Bilder/blau 9.png", "Uno Bilder/blau aussetzen.png", "Uno Bilder/blau retoure.png", "Uno Bilder/blau +2.png"};
  public String karten_gruen[] = {"Uno Bilder/gruen 0.png", "Uno Bilder/gruen 1.png", "Uno Bilder/gruen 2.png", "Uno Bilder/gruen 3.png", "Uno Bilder/gruen 4.png", "Uno Bilder/gruen 5.png", "Uno Bilder/gruen 6.png", "Uno Bilder/gruen 7.png", "Uno Bilder/gruen 8.png", "Uno Bilder/gruen 9.png", "Uno Bilder/gruen aussetzen.png", "Uno Bilder/gruen retoure.png", "Uno Bilder/gruen +2.png",};
  public String karten_gelb[] = {"Uno Bilder/gelb 0.png", "Uno Bilder/gelb 1.png", "Uno Bilder/gelb 2.png", "Uno Bilder/gelb 3.png", "Uno Bilder/gelb 4.png", "Uno Bilder/gelb 5.png", "Uno Bilder/gelb 6.png", "Uno Bilder/gelb 7.png", "Uno Bilder/gelb 8.png", "Uno Bilder/gelb 9.png", "Uno Bilder/gelb aussetzen.png", "Uno Bilder/gelb retoure.png", "Uno Bilder/gelb +2.png",};
  public String wunschkarten[] = {"Uno Bilder/wunsch.png", "Uno Bilder/wunsch +4.png",};
  }

Java:
class Karte{
  public String farbe;
  public Karte(String farbe) { 
    this.farbe=farbe;
    }
    public String ausgabe() {
    return "" + farbe;
    }
  }

Java:
class Zahlkarte extends Karte {
  public int zahl; 
  public Zahlkarte(String farbe, int zahl){
    super(farbe);
    this.zahl=zahl;
    } 
  public String ausgabe() {
    return super.ausgabe() + ", " + zahl;
    }   
  }

Java:
class Aktionskarte extends Karte {
  public String aktion;
  public Aktionskarte(String farbe, String aktion){
    super(farbe);
    this.aktion=aktion;
    }
  public String ausgabe() {
    if (aktion == "Farbenwahl" || aktion == "Farbenwahl-Zieh-Vier") {
      return aktion + "";
    }     
    else {
      return super.ausgabe()+ ", " + aktion;
    } // end of if-else   
    }
  }

Hauptprogramm:
Java:
public int zahlen[] = {0,1,2,3,4,5,6,7,8,9};
  public String farben[] = {"blau", "rot", "gruen", "gelb"};
  public String aktionen[] = {"Zieh-Zwei", "Retoure", "Aussetzen", "Farbenwahl", "Farbenwahl-Zieh-Vier"};
  
  ArrayList<Karte> kartenstapel = new ArrayList<Karte>();
  int stapelanzahl = 0;

public void stapel_erstellen() {
    //Zahlkarte
    for (int i=0;i<farben.length;i++) {
      for (int j=0;j<zahlen.length;j++ ) {
        Zahlkarte zkarte = new Zahlkarte(farben[i], zahlen[j]);
        kartenstapel.add(zkarte);
        stapelanzahl++; 
      }   
    } // end of for
    for (int i = 0;i<farben.length ;i++ ) {
      for (int j=0;j<aktionen.length ; j++) {
        if (aktionen[i].equals("Farbenwahl") || aktionen[i].equals("Farbenwahl-Zieh-Vier")) {
          Aktionskarte akarte = new Aktionskarte("", aktionen[j]);
          kartenstapel.add(akarte);
          stapelanzahl++;
        } 
        else if (aktionen[i].equals("Zieh-Zwei") || aktionen[i].equals("Retoure") || aktionen[i].equals("Aussetzen")){
          Aktionskarte akarte = new Aktionskarte(farben[i], aktionen[j]);
          kartenstapel.add(akarte);
          stapelanzahl++;
        } // end of if-else
      } // end of for     
    } 
    Collections.shuffle(kartenstapel);
  }

Und jetzt hätte ich gerne noch eine Methode, die den Karten im Hauptprogramm die jeweiligen Bilder zuweist. Weiß zufällig jemand, wie er mir weiter helfen könnte?
 
Und jetzt hätte ich gerne noch eine Methode, die den Karten im Hauptprogramm die jeweiligen Bilder zuweist. Weiß zufällig jemand, wie er mir weiter helfen könnte?
Deine Klasse Bilder könntest Du etwas umbauen.
Java:
public class TestCard {
    public static void main(String[] args) {
        for (int color = 0; color <= Bilder.getMaxColor(); color++) {
            for (int value = 0; value <= Bilder.getMaxValue(); value++)
                System.out.println(Bilder.getCardFileName(value, color) + " ");
            System.out.println("---------------");
        }
    }
}
Java:
public class Bilder {
    private final static String path = "Uno Bilder/";
    private final static String[] colors = { "rot", "blau", "gruen", "gelb", "wunsch" };
    private final static String[] action = { "aussetzen", "retoure", "+" };
    private final static String type = "png";

    public final static int RED = 0;
    public final static int BLUE = 1;
    public final static int GREEN = 2;
    public final static int YELLOW = 3;
    public final static int ALL_COLORS = 4;

    public final static int SKIP = 10; // AUSSETZEN
    public final static int BACK = 11; // RETOURE
    public final static int TAKE = 12; // NEHMEN

    private static void checkParameters(int value, int color) {
        if (color < 0 || color >= colors.length)
            throw new IllegalArgumentException(
                    "Invalid Color number use " + Bilder.class.getSimpleName() + " color constants!");
        if (value < 0 || value > getMaxValue())
            throw new IllegalArgumentException("Invalid value. Allowed range from 0-" + getMaxValue() + "!");
    }

    public static int getMaxColor() {
        return colors.length-1;
    }

    public static int getMaxValue() {
        return TAKE;
    }

    public static String getCardName(int value, int color) throws IllegalArgumentException {
        checkParameters(value, color);
        String name = colors[color] + " ";
        if (value < SKIP)
            return name + value;
        name += action[value - SKIP];
        if (value == TAKE)
            return color == ALL_COLORS ? name + "4" : name + "2";
        return name;
    }

    public static String getCardFileName(int value, int color) throws IllegalArgumentException {
        return path + getCardName(value, color) + "." + type;
    }
}
 
Vielen Dank für deine Antwort, aber wäre es nicht auch möglich, eine einfachere Überprüfung Methode zu erstellen? Ich brauche das nämlich für mein Schuld Projekt und diese Lösung wäre da etwas zu komplex... Nicht falsch verstehen, Ich bin dir sehr dankbar und danke dir auch für deine Mühe, doch Ich verstehe selbst nicht einmal genau diese Lösung und da wäre es falsch von mir, dies in mein Schul Projekt einzubauen. Ich

Aber ich hätte auch noch eine Frage: Ich habe es nicht hinbekommen, anhand dieser Methode die Bilder in meinem jLabel auszugeben. Liegt es daran, da die Methode nicht dafür konzipiert wurde?
 
JLabel ist auch dazu gedacht Bilder anzuzeigen:
Java:
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class Main {

    public static void main(final String[] args) throws IOException {

        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setLocation(200, 200);

        final JFileChooser fc = new JFileChooser();
        if (fc.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
            final BufferedImage img = ImageIO.read(fc.getSelectedFile());// it must be an image file, otherwise you'll get an exception
            final JLabel label = new JLabel();
            label.setIcon(new ImageIcon(img));
            frame.getContentPane().add(label);
        }

        frame.setVisible(true);
    }

}
1667206209464.png
 
Ich wollte dazu eine Methode erstellen, die die Karte in meiner ArrayList (Kartendeck) darauf prüft, welche Farbe und welches Symbol abgebildet ist.
Die Arraylist enthält nur Objekte vom Typ Karte. Damit kannst du zwar die Farbe ausgeben aber es gibt keine Methode für ein "Symbol".
Leider haben auch weder Zahlkarte noch Aktionskarte ein "Symbol". Du musst noch mal beschreiben was du eigentlich tun willst, bzw. den Karten erst einmal ein "Symbol" zuweisen.
Java:
        final ArrayList<Karte> kartenstapel = new ArrayList<>();
        kartenstapel.add(new Karte("rot"));
        kartenstapel.add(new Karte("blau"));
        kartenstapel.add(new Karte("rot"));

        System.out.println(kartenstapel.get(1).ausgabe());
 
Du Lösung hat Dir @Oneixee5 schon geflüstert, aber vielleicht sollten wir das mal im Detail betrachten.

Die "naheliegendste" Lösung bestünde darin, das JLabel in der Karte zu speichern. Das ist ein absolutes "No Go", denn damit bindest Du Dein Spielmodel unweigerlich an das Framework und bist auf immer verdammt, Swing zu nutzen 🙂

Statt das JLabel könnte man natürlich das Bild in der Karte speichern. Auch das ist nicht ganz unproblematisch, denn es könnte z. B. sein, dass Du unterschiedliche Bilder für unterschiedliche Displays brauchst.

Die nächst abstraktere Möglichkeit wäre, den relevanten Teil eines Dateinamens in die Karte aufzunehmen. Das funktioniert, stellt aber in der Regel eine Verbindung zum Dateisystem her, was man auch nicht unbedingt möchte. Ist nicht ganz optimal, aber zumindest ein gangbarer Weg.

In der Regel gibt der Karte eine "Beschreibung" des Symbols mit, das dann an anderer Stelle in ein Bild "übersetzt" wird. Wenn Du aufgepasst hast, wirst Du feststellen, dass der "relevante Teil eines Dateinamens" ja auch nur eine Beschreibung des Symbols ist. In diesem letzten Schritt geht es also nur noch darum, sich nicht auf den "Dateinamen" zu fixieren.
 
Die Arraylist enthält nur Objekte vom Typ Karte. Damit kannst du zwar die Farbe ausgeben aber es gibt keine Methode für ein "Symbol".
Leider haben auch weder Zahlkarte noch Aktionskarte ein "Symbol". Du musst noch mal beschreiben was du eigentlich tun willst, bzw. den Karten erst einmal ein "Symbol" zuweisen.
Java:
        final ArrayList<Karte> kartenstapel = new ArrayList<>();
        kartenstapel.add(new Karte("rot"));
        kartenstapel.add(new Karte("blau"));
        kartenstapel.add(new Karte("rot"));

        System.out.println(kartenstapel.get(1).ausgabe());
Ich hätte eigentlich gerne eine Methode in meinem Hauptprogramm, wo ich die Karten aus meiner Arraylist "Kartenstapel" darauf prüfe, welche farben und welche zahlen diese haben. Und dadurch wollte ich dann das jeweilige bild im jLabel ausgeben.

Über den Konstruktor von der Klassenhirarchie habe ich auch schon versucht ein "Symbol" zu integrieren, worin ich die Bilder dann speichere. Da gab es aber das Problem, dass ich diese nicht ausgeben konnte.

Wäre einer der 2 Dinge umsetzbar?
 
In etwa so:
Java:
public class Main {

    private static class Karte {

        public String farbe;
        private final String symbol;
        private final int wert;

        public Karte(final String farbe, final String symbol, final int wert) {
            this.farbe = farbe;
            this.symbol = symbol;
            this.wert = wert;
        }

        public String getFarbe() {
            return this.farbe;
        }

        public void setFarbe(final String farbe) {
            this.farbe = farbe;
        }

        public String getSymbol() {
            return this.symbol;
        }

        public int getWert() {
            return this.wert;
        }

        public String getImageName() {
            return String.format("/ressources/%s-%s-%s.png", this.symbol ,this.farbe,this.wert);
        }

        @Override
        public String toString() {
            return "Karte [farbe=" + this.farbe + ", symbol=" + this.symbol + ", wert=" + this.wert + "]";
        }

    }

    public static void main(final String[] args) throws IOException {

        final ArrayList<Karte> kartenstapel = new ArrayList<>();
        kartenstapel.add(new Karte("rot", "herz", 5));
        kartenstapel.add(new Karte("blau", "karo", 7));
        kartenstapel.add(new Karte("rot", "kreis", 1));

        System.out.println(kartenstapel.get(0));
        final Karte karte = kartenstapel.get(1);
        System.out.println(karte.getFarbe() + " " + karte.getWert());

        ...
        final BufferedImage img = ImageIO.read(Karte.class.getResource(karte.getImageName()));
        final JLabel label = new JLabel();
        label.setIcon(new ImageIcon(img));
        ...
    }

}
Statt der Strings/int's für Farbe, Symbol und Wert würde man normalerweise Konstanten oder Enum's verwenden.
 
Noch ein Hinweis: Ich weiß nicht wie viele Karten du anzeigen möchtest und wie groß diese sein sollen. Dein Ansatz ist da nicht sehr effizient. Das könnte zu Problemen mit Speicher und Geschwindigkeit führen. Wenn du nur wenige Karten anzeigst bzw. im Speicher hältst gibt es kein Problem.
 

Zurück
Oben