Kartenspiel

xEpix3

Mitglied
Liebe Community,
ich habe nun versucht ein Kartendeck zu programmieren und hab dafür zwei Klassen geschrieben. Zum einen eine Karte-Klasse und zum anderen eine KartenSpiel-Klasse. Meine Frage ist nun, ob die Klassen fehlerfrei geschrieben sind und wie ich das Kartendeck irgendwie anzeigen kann?
Liebe Grüße
[CODE lang="java" title="Karte"]public class Karte{
private final static int KARO= 0;
private final static int HERZ = 1;
private final static int PIK = 2;
private final static int KREUZ= 3;

private final static int BUBE= 11;
private final static int DAME= 12;
private final static int KOENIG= 13;
private final static int ASS = 1;

private final int farbe;
private final int wert;

//Konstruktor
public Karte(int f, int w){
farbe = f;
wert = w;
}

public String farbeInString(){
switch (farbe){
case KARO:
return "Karo";
case HERZ:
return "Herz";
case PIK:
return "Pik";
case KREUZ:
return "Kreuz";
}
System.out.println("Farbe falsch! : "+farbe);
return "-1";
}

public String wertInString() {
if ((wert>=2)&&(wert<=10))
return " " + wert;
switch (wert){
case 1:
return "A";
case 11:
return "B";
case 12:
return "D";
case 13:
return "K";
}
return "-1";
}

public String KarteInString(){
return farbeInString() + "-" + wertInString();
}
}[/CODE]

[CODE lang="java" title="KartenSpiel"]import java.util.*;

public class KartenSpiel{
private Karte[] stapel;
private int kartenImSpiel;

//Konstruktor
public KartenSpiel(){
stapel = new Karte[52];
int zaehler = 0;
for (int f=0; f<4; f++ ){
for (int w=1; w<14; w++ ){
stapel[zaehler] = new Karte(f, w);
zaehler++;
}
}
mischen();
}

public void mischen() {
Karte temp;
kartenImSpiel = 52;
Random rand = new Random();
for (int i=kartenImSpiel-1; i>=0; i--) {
int zuff = rand.nextInt(kartenImSpiel);
if (zuff!= i) {
temp = stapel;
stapel = stapel[zuff];
stapel[zuff] = temp;
}
}
}

public int kartenAnzahl() {
return kartenImSpiel;
}

public Karte gibEineKarte(){
if (kartenImSpiel == 0)
mischen();
kartenImSpiel--;
return stapel[kartenImSpiel];
}

public static void main(String args[]){
KartenSpiel test = new KartenSpiel();
test.gibEineKarte();
test.kartenAnzahl();
}
}[/CODE]
 
M

Mart

Gast
Java:
    private final static int KARO= 0;
    private final static int HERZ = 1;
    private final static int PIK = 2;
    private final static int KREUZ= 3;
    
    private final static int BUBE= 11;
    private final static int DAME= 12;
    private final static int KOENIG= 13;
    private final static int ASS = 1;
diese wären besser in enums umgesetzt

ob die klassen fehlerfrei sind sagt dir der compiler

Java:
    public Karte(int f, int w){
        farbe = f;
        wert = w;
    }
die namen haben aussage wie kartoffel puffer also f und w

Java:
    public String KarteInString(){
        return farbeInString() + "-" + wertInString();
    }
das entspricht "object als string" hier ist die toString() methode bevorzugt zu überschreiben


das anzeigen wäre dann
Java:
for ( var karte : stapel){
    system.out.println ( karte.toString() ) bzw karte karteInString()
}
das toString() kannst du dann weglassen das macht system.out .println automatisch
 

Blender3D

Top Contributor
Meine Frage ist nun, ob die Klassen fehlerfrei geschrieben sind und wie ich das Kartendeck irgendwie anzeigen kann?
Du erkennst Fehler durch testen. Das Anzeigen kannst Du mittels der
Java:
toString()
auf der Konsole bewältigen. Damit lässt sich dort das Ganze erst einmal grob testen. Solltest Du ein grafische Ausgabe planen, könnte man den Klassen eine Methode
Java:
public void draw( Graphics g ){    .. }
mittels Vererbung verpassen.
Hier ein Konsolenbeispiel eines einfachen Tests. Ich habe dafür eigene Klassen gemacht.
1641765205893.png
[CODE lang="java" title="TestCardDeck"]import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class TestCardDeck {
public static void main(String[] args) {
CardDeck deck = new CardDeck();
ArrayList<Card> cards = new ArrayList<>();
System.out.println("Das neue Deck:\n" + deck);
printSeperator();
int cnt = 0;
do {
Card card = deck.drawCard();
cards.add(card);
System.out.println((cnt + 1) + "\t--> " + card );
} while (++cnt < 11);
printSeperator();
System.out.println("Das benutzte Deck:\n" + deck);
printSeperator();
System.out.println("Die gezogenen Karten nach Werten sortiert!:");
Collections.sort(cards);
System.out.print(Arrays.toString(cards.toArray(new Card[cards.size()])));
}

private static void printSeperator() {
System.out.println("-------------------------------------------------------------");
}
}[/CODE]
[CODE lang="java" title="Card"]public class Card implements Comparable<Card> {
public enum COLOR {
Diamonds, Spades, Hearts, Clubs
};

public static final int ACE = 1;
public static final int JACK = 11;
public static final int QUEEN = 12;
public static final int KING = 13;

public final int value;
public final COLOR color;

public Card(int value, COLOR color) throws IllegalArgumentException {
if (value < ACE || value > KING)
throw new IllegalArgumentException("Ungueltiger Karten Wert");
this.value = value;
this.color = color;
}

@Override
public int compareTo(Card card) {
if (value == card.value)
return 0;
if (card.value == ACE)
return -1;
if (value == ACE)
return 1;
return value > card.value ? 1 : -1;
}

@Override
public String toString() {
return "<" + color.toString().charAt(0) + "," + valueToStr() + ">";
}


private String valueToStr() {
if (value >= JACK && value <= KING)
return new char[]{ 'J', 'Q', 'K' }[value - JACK] + "";
return value == 1 ? "A" : value + "";
}
}[/CODE]
[CODE lang="java" title="CardDeck"]import java.util.BitSet;
import java.util.Random;

public class CardDeck {
private final Random rnd = new Random(System.currentTimeMillis());
public final static int NUM_CARDS = 52;
public final static int NUM_COLORS = 4;
private BitSet used = new BitSet(NUM_CARDS);

public Card drawCard() {
if (isEmpty())
throw new IllegalAccessError("Es gibt keine Karten mehr im Deck!");
int pos = getValidRandomPos();
return removeCard(pos);
}

private int getValidRandomPos() {
int pos = 0;
do {
pos = rnd.nextInt(NUM_CARDS);
} while (used.get(pos) == true);
return pos;
}

public boolean isEmpty() {
return used.cardinality() == NUM_CARDS;
}

private Card posToCard(int pos) {
int colorId = pos / Card.KING;
int value = pos % Card.KING + 1;
return new Card(value, Card.COLOR.values()[colorId]);
}

public Card removeCard(int pos) throws IndexOutOfBoundsException {
if (pos < 0 || pos >= NUM_CARDS)
throw new IndexOutOfBoundsException();
if (used.get(pos))
return null;
used.set(pos);
return posToCard(pos);
}

public void reset() {
used.clear();
}

@Override
public String toString() {
StringBuffer tmp = new StringBuffer();
for (int i = 0; i < NUM_CARDS; i++) {
if (i != 0 && i % Card.KING == 0)
tmp.append(System.lineSeparator());
if (used.get(i))
tmp.append(i % Card.KING == 9 ? " < >" : " < >");
else
tmp.append(" " + posToCard(i));
}
return tmp.toString();
}

}[/CODE]
 
Zuletzt bearbeitet:
M

Mart

Gast
falls es dich interessiert wie ich es lösen würde, da du gegen ein "objekt" prinzip "verstößt"
deine karte weis alle kombinationen bzw weis zu viel

Java:
enum Farbe{
    SCHELLEN,GRUEN,HERZ,EICHEL;
}
enum Typ{
    SAU,KOENIG,DAME...;
}
wenn du diese enums hast kannst du deine Karte so gestalten
Java:
public class Karte{
Typ typ;
Farbe farbe;
    public Karte(Typ typ, Farbe farbe)
    {
        ---
    }
}
in der anderen methode kannst du dann so erzeugen
Java:
Karte karte = new Karte(Typ.SAU,Farbe.SCHELLEN);

du kannst über das enum auch drüber iterieren
mit
Java:
for ( var typ : Typ.values())
bin mir aber nicht sicher so könntest du schickeren lesbareren code bauen

PS ich bin großer fan von enums die nur die enum namen drin haben :)
 
M

Mart

Gast
Das musst Du mir erklären.
schau dir yugioh karten an

wäre es klug in einer karte alle möglichen kombinationen ( wie mosnter, zauber ) zu speichern als static final ? soll man alles rein packen?

muss die Karte wissen dass es zauber und fallen gibt wenn es selber ei nmosnter ist ? nein nicht wirklich
eg das da
Java:
    private final static int KARO= 0;
    private final static int HERZ = 1;
    private final static int PIK = 2;
    private final static int KREUZ= 3;
   
    private final static int BUBE= 11;
    private final static int DAME= 12;
    private final static int KOENIG= 13;
    private final static int ASS = 1;
natürlich kann man alles rein packen... du kannst auch eine komplette fx anwendung in eine klasse shcreiben... ist halt dann scheiß code dewegen in anführungs zeichen und der satz "wenn es dich interessiert" ... da mein vorschlag optional ist nur die fragen die er hat kommen erstens von unwissenheit ( toString() ) methode wie die funktioniert wurde geklärt
und er kennt sich (vlllt) selber nicht mehr aus und löst dadurch mehr fragen aus => vllt durch code strukturierung können diese von vorneherein eingeschränkt werden auf fragen die neue sachen ansprechen und sich nicht immer um das drehen was schon mal gelernt wurde
 

Blender3D

Top Contributor
wäre es klug in einer karte alle möglichen kombinationen ( wie mosnter, zauber ) zu speichern als static final ? soll man alles rein packen?
[CODE lang="java" title="Card" highlight="14-18"]public class Card implements Comparable<Card> {
public enum COLOR {
Diamonds, Spades, Hearts, Clubs
};

public static final int ACE = 1;
public static final int JACK = 11;
public static final int QUEEN = 12;
public static final int KING = 13;

public final int value;
public final COLOR color;

public Card(int value, COLOR color) throws IllegalArgumentException {
if (value < ACE || value > KING)
throw new IllegalArgumentException("Ungueltiger Karten Wert");
this.value = value;
this.color = color;
}

@Override
public int compareTo(Card card) {
if (value == card.value)
return 0;
if (card.value == ACE)
return -1;
if (value == ACE)
return 1;
return value > card.value ? 1 : -1;
}

@Override
public String toString() {
return "<" + color.toString().charAt(0) + "," + valueToStr() + ">";
}


private String valueToStr() {
if (value >= JACK && value <= KING)
return new char[]{ 'J', 'Q', 'K' }[value - JACK] + "";
return value == 1 ? "A" : value + "";
}
}[/CODE]
Die Karte gibt dem Benutzer dadurch die Möglichkeit sie mit sprechenden Konstanten zu erzeugen.
Java:
Card card = new Card(Card.JACK, Card.COLOR.Hearts);
Selbstverständlich könnte man für den Wert auch einen Enum wie für die Farbe verwenden.
Da das Rechnen mit integer Werten naheliegt spricht hier aber auch nichts gegen Konstante. Wichtig dabei ist es aber den Wertebereich auf die zulässigen Werte zu begrenzen. Das passiert bei einem Enum automatisch.
[CODE lang="java" highlight="2-3"] public Card(int value, COLOR color) throws IllegalArgumentException {
if (value < ACE || value > KING)
throw new IllegalArgumentException("Ungueltiger Karten Wert");
this.value = value;
this.color = color;
}[/CODE]
Diese Technik findet in Swing sehr häufig Anwendung.
Bsp:
Java:
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
M

Mart

Gast
du kannst dem enum auch einfach einen wert mitgeben ... dann kannst du auch rechnen

Java:
card{
    koenig(4)
        ..
    card(Integer augenzahl){
        
    }
}
 

mihe7

Top Contributor
Vom Grundsatz her ist natürlich beides möglich und der int-Ansatz war früher auch die einzige Möglichkeit in Java - was auch der Grund sein dürfte, dass es in Swing so gemacht wurde ;)

Allerdings würde ich ein enum bevorzugen, weil es mehr Informationen liefert. Als Parameter verwendet, stellt schon die Signatur klar, was zu übergeben ist. Hier kann die IDE automatisch vervollständigen. Die Prüfung des ints kann dagegen erst zur Laufzeit erfolgen.
 

Ähnliche Java Themen

Neue Themen


Oben