Erste Schritte Grundsätzlicher Aufbau

Reggie()

Bekanntes Mitglied
Hi Leute,
ich versuche gerade ein einfaches Kartenspiel umzusetzen und würde gerne wissen, ob meine Gedanken zum Aufbau grundsätzlich in die richtige Richtung gehen. Denn ich komme aus der prozedualen Welt und bin mit dem Konzept der obejektorientierten Programmierung noch nicht warm.
Also:
Ich kann die Spielkarten sehr gut in 3 Kategorien einteilen, die alle etwas völlig unterschiedliches machen und darstellen (Personenkarten, Aktionskarten, Sonderkarten).
Also dachte ich mir, dass ich eine Mutterklasse Karte erstelle (abstract?) und jede der Kartenkategorien wird eine eigene Unter-Klasse. Der Grund dafür ist, weil ich die Orte, an denen sich die Karten im Spielverlauf nur befinden können (Ziehstapel, Ablagestapel, HandSpieler[n], AuslagejeweiligerSpieler[n]) als Arraylist des Typs Karte verwalte. Karten-Objekte erstelle ich ja keine, aber alle gehören (erben) ja zum Typ Karte.

Ist das zu kompliziert gedacht? ich könnte natürlich auch nur 1 Klasse Karte machen und die Kategorie ist einfach ein Attribut der Klasse Karte.

Bin offen für Vorschläge, Erklärungen, Tipps und hoffe ich verstehe es.
 

VfL_Freak

Top Contributor
Moin,

das ist so realtiv schwierig zu beurteilen, da wir nicht genau wissen, was diese 3 Kategorien unterscheidet!
Aber in Sinne einer sauberen Objektorientierung, würde ich (vermutlich) die erste Variante vorziehen!

Karten-Objekte erstelle ich ja keine, aber alle gehören (erben) ja zum Typ Karte
Den Satz verstehe ich nicht so ganz ...
Wenn irgendwas vom Typ 'Karte' erbt, muss es doch zwangsläufig ein Objekt sein!
Platt gesagt: bspw. eine integer-Variable könnte ja schlecht von irgendeiner Klasse erben !!

Gruß Klaus
 

Reggie()

Bekanntes Mitglied
Der Gedanke war der: Jede Spielkarte ist ein Objekt einer der 3 Klassen. Da die Orte, an denen sich Spielkarten befinden können, ArrayList sein müssen, müssen die Spielkarten die selbe Mutterklasse haben (Karte). Oder verstehe ich da was falsch?

Zu den unterschieden der Spielkarten:
Personenkarten haben Instanzvariablen mit Werten, die wichtig sind für den ausgelegten Bereich (Punkte für Kampfkraft und Siegbedingung).
Aktionskarten können verwendet werden, um - gegen Bezahlung - ausgelegte Karten des Gegners zu manipulieren.
Sonderkarten können in bestimmten Situationen Einfluss auf einen bestimmten Vorgang nehmen.
 

Reggie()

Bekanntes Mitglied
da wir hier ja in der Anfängersektion sind, möchte ich gleich mal meine Gedanken in Form von Code verdeutlichen.
Mutterklasse:
Code:
public static class Karte()
{
int kartenid;
}
Eine der 3 Subklassen:
Code:
public class Personenkarte()
{
   public string kartentyp;
   public int kopfgeld;
   public int agil;
   public int kampfkraft;
   public boolean abwerbbar;

   public Personenkarte(int id, string typ, int kg, int agi, int kraft, boolean abw)
   {
   super.kartenid = id;
   kartentyp = typ;
   kopfgeld = kg;
   agil = agi;
   kampfkraft = kraft;
   abwerbbar = abw;
   }
}
Und so würde ich die Karten generieren:
Code:
class Piratenspiel()
{
   public static void main( string[] args )
   {
   Personenkarte[] pk = new Personenkarte[52];
   Personenkarte pk[1] = new Personenkarte(1,"Kapitän",50,3,3,FALSE);
   Personenkarte pk[2] = new Personenkarte(2,"Koch",10,2,2,TRUE);
   }
}
Sind alle 52 Karten erstellt, müsste ich sie an die Arraylist Ziehstapel "übergeben". Hat der Ziehstapel dann den Typ Karte?
 

VfL_Freak

Top Contributor
Moin,
ja, das sieht schon mal nicht so schlecht aus :)

Allerdings musst Du die Vererbung auch angeben
public class Personenkarte()
extends Karte // !!!

Wozu brauchst Du die KartenID ... vor allem, warum in der Superklasse?

Dann
Java:
class Piratenspiel()
{
   public static void main( string[] args )
   {
   Personenkarte[] pk = new Personenkarte[52];
   Personenkarte pk[1] = new Personenkarte(1,"Kapitän",50,3,3,FALSE);
   Personenkarte pk[2] = new Personenkarte(2,"Koch",10,2,2,TRUE);
   }
}
Vorsicht, wenn Dein Array 52 Werte umfasst, dann läuft der Index von pk von 0 bis 51 (nicht von 1 - 52) !!!

Gruß Klaus
 

Reggie()

Bekanntes Mitglied
ja stimmt, das "extends" hatte ich vergessen. index fängt bei 0 an, im Beispiel nicht dran gedacht.
warum den Umweg über pk? ich dachte ich muss alle Objekte der 3 Unterklasse erstellen und diese dann in eine Arraylist der Klasse Karte speichern, oder?
 

JStein52

Top Contributor
Wenn du sie nur erstellst und dann sowieso gleich in den ziehStapel einfügst kannst du doch gleich schreiben:
Code:
ziehStapel.add(new Personenkarte(1,"Kapitän",50,3,3,FALSE));
 

Reggie()

Bekanntes Mitglied
ist dann ziehStapel eine Klasse oder eine ArrayList? kannst du mir mehr code geben?
ich suche eh nach einer besseren Lösung die Karten, die in jedem Spiel die selben sind, zu erstellen. muss ich das immer in der main machen oder geht das auch eleganter?
 

Reggie()

Bekanntes Mitglied
so?
Code:
class Piratenspiel()
{
   public static void main( string[] args )
   {
      List<Karte> ziehStapel = new ArrayList <Karte>();
      ziehStapel.add(new Personenkarte(1,"Kapitän",50,3,3,FALSE));
      ziehStapel.add(new Personenkarte(2,"Koch",20,2,2,TRUE));
   }
}
 

JStein52

Top Contributor
Nach dem was du bis jetzt gepostet hast würde ich in der Klasse Piratenspiel so was wie eine Methode "spielen" machen die in einer Endlosschleife "spielt" (wie immer das bei deinem Spiel geht) bis der Spieler "beenden" eingibt. Und in main erstellst du ein Objekt der Klasse Piratenspiel und rufst anschliessend dessen Methode "spielen" auf. Und für das Anlegen des ziehStapels machst du einfach eine private Methode die das erledigt.
 

JStein52

Top Contributor
zum ziehen generierst du dir einfach eine zufällige Zahl kartenNr die zwischen 0 und der aktuellen Grösse des ziehStapels liegt und holst dir diese Karte aus dem ziehStapel und machst was damit:
Code:
 Karte gezogeneKarte = ziehStapel.get(kartenNr);

Edit: und die gezogene Karte musst du natürlich mit remove aus dem ziehStapel entfernen ;)

ich glaube das geht sogar in einem Schritt:
Code:
Karte gezogeneKarte = ziehStapel.remove(kartenNr);
 

Reggie()

Bekanntes Mitglied
zum ziehen generierst du dir einfach eine zufällige Zahl kartenNr die zwischen 0 und der aktuellen Grösse des ziehStapels liegt und holst dir diese Karte aus dem ziehStapel und machst was damit
Ich hatte mir das so gedacht, dass ich nach dem Erstellen der Karten den Ziehstapel einmach durchmische. und dann immer eine Karte nach der anderen von "oben" ziehe, wie im richtigen Kartenspiel. Muss ich denn beim Ziehen einer zufälligen Karte nicht prüfen, ob eine Karte mit der Zufalls-ID überhaupt im Stapel liegt?
 

JStein52

Top Contributor
Noch zu deinem Code:
den ziehStapel darfst du nicht innerhalb von main anlegen sondern das sollte eine Instanzvariable von "Piratenspiel" sein, d.h. 3-4 Zeilen weiter oben ;);)
 

JStein52

Top Contributor
Was die kartenID bei dir für eine semantische Bedeutung haben soll verstehe ich nicht. Wenn du damit die Karten nur durchnummerieren willst kannst du sie genau so gut weglassen.
 

Jardcore

Top Contributor
ist dann ziehStapel eine Klasse oder eine ArrayList? kannst du mir mehr code geben?
ich suche eh nach einer besseren Lösung die Karten, die in jedem Spiel die selben sind, zu erstellen. muss ich das immer in der main machen oder geht das auch eleganter?
Du könntest die Karten in einem geeigneten Format in einer Textdatei speichern und diese Datei dann einlesen. In der Main würden dann daraus "echte" Karten erstellt und zu deiner Liste hinzugefügt.

Hier eine mögliche Karten Datei in .json format.
Code:
[
{
    "typ" : "aktionskarte",
    "name" : "Lebensraub",
    "beschreibung" : "Du verlierst @value Leben",
    "aktion" : "lebensAbzug",
    "value" : 10,
},
//usw.
}
]
Code:
[
{
    "typ" : "personkarte",
    "name" : "Dr Who",
    "beschreibung" : "Raum- und Zeitreisender"
},
]

Java:
public class CardGameLauncher {
    public static void main(String[] args) {
        CardGame game = new CardGame();
        game.start();
    }
}

Java:
public class CardGame {
    private boolean isRunning = true;
    private ArrayList<Card> cards;

    public CardGame() {
        this.cards = new ArrayList<Card>();
        loadCards();
    }

     public void start() {
         CollectionsUtils.shuffel(cards);
         gameloop();
     }

     private void loadCards() {
          // Hier die Logik für das Laden der Json Datei
          /* pseudoCode
              List<ActionCardDto> actionCardDtos = new Json().fromJson("aktionskarten.json");
              for(ActionCardDto dto : actionCardDtos) {
                  Aktionskartecard = new Aktionskarte();
                  card.setName(dto.name);
                  card.setDescription(dto.description);
                  //...
                 cards.add(card);
              }
             // Das nochmal für die anderen Kartentypen
          */
     }

     private void gameloop() {
          while(isRunning) {
              input();
              update();
              render();
          }
     }
}
 

JStein52

Top Contributor
Genau so meinte ich das. Und ob die Karten in einer Datei liegen oder nicht hängt vom Spieltyp ab. Wenn es ein Spiel in der Art wie Skat ist dann sind die Karten seit Jahrhunderten fest und werden auch die nächsten hundert Jahre fest sein, dann ist das mit der Datei ein Overkill. Ansonsten ist das eine sehr schöne Idee.
 

Reggie()

Bekanntes Mitglied
so langsam verliere ich den Anschluss. warum sollte ich eine Partie als Objekt erstellen und alles Vorgänge im Spiel als dessen Methoden, wenn ich das auch prozedual in der main mittels Schleifen und Bedingungen machen kann? Ok, da habe ich mir wohl schon selbst die Antwort gegeben... in Java sind Lösungen halt objektorierntiert (auch wenn man den Nutzen nicht imemr versteht).
Noch eine Frage: wo bzw. wie erschaffe ich die Spieler? Ich denke mit einer Klasse Spieler. Kann ich dann beim Erschaffen der Partie gleich die Spielerobjekte erstellen?
 

Reggie()

Bekanntes Mitglied
JStein52 hat gesagt.:
den ziehStapel darfst du nicht innerhalb von main anlegen sondern das sollte eine Instanzvariable von "Piratenspiel" sein.

Was die kartenID bei dir für eine semantische Bedeutung haben soll verstehe ich nicht. Wenn du damit die Karten nur durchnummerieren willst kannst du sie genau so gut weglassen.
Kannst du das mit den Instanzvariablen von Piratenspiel nochmal erläutern?
Ich dachte Kartennummern sind wichtig, da es auch Karten gibt, die mehrmals in identischer Form vorkommen (nicht alle Karten sind einzigartig). Aber dann lass ich es weg.

da ihr mir so toll helft, wäre es sinnvoll, wenn ich meinen Code im Bereich "Spieleprogrammierung" poste und aktuell halte? Ich glaube so lerne ich es am besten.
 

JStein52

Top Contributor
@Reggie() : so
Code:
/**
*
* @author Juergen
*/
public class Piratenspiel {

    Random zufall = new Random();
    List<Karte> ziehStapel = new ArrayList <Karte>();
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Piratenspiel meinSpiel = new Piratenspiel();
        meinSpiel.spielen();
    }
}
 

JStein52

Top Contributor
Ich denke mit einer Klasse Spieler. Kann ich dann beim Erschaffen der Partie gleich die Spielerobjekte erstellen
Ja und ja.

Code:
/**
*
* @author Juergen
*/
public class Piratenspiel {

    Random zufall = new Random();
    List<Karte> ziehStapel = new ArrayList <Karte>();
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Piratenspiel meinSpiel = new Piratenspiel();
        meinSpiel.spielen();
    }
   
    public void spielen() {
   
        while (true) {
            // hier kommt die endlosschleife zum spielen rein
           
            // Benutzer fragen was er machen will
           
            // bei neuem Spiel Karten erzeugen
            kartenErzeugen();
            // Spieler erzeugen
            spielerErzeugen();
           
            // und spielen
           
        }
    }
   
    private void kartenErzeugen() {
      ziehStapel.add(new Personenkarte(1,"Kapitän",50,3,3,false));
      ziehStapel.add(new Personenkarte(2,"Koch",20,2,2,true));
      // usw.

    }

    private void spielerErzeugen() {
        // geeignete Struktur zum speichern der Spieler ueberlegen und die
        // dann erzeugen

    }
}
 

Reggie()

Bekanntes Mitglied
zu deinem code: könnte ich die Spielkarten mittels Methode von der class Piratenspiel erstellen?
Java:
public class Piratenspiel() {
    Random zufall = new Random();
    List<Karte> ziehStapel = new ArrayList <Karte>();
  
    public void deckbau() {
        ziehStapel.add(new Personenkarte(1,"Kapitän",50,3,3,FALSE));
        ziehStapel.add(new Personenkarte(2,"Koch",20,2,2,TRUE));
        //usw.
    }

    public static void main(String[] args) {
        Piratenspiel meinSpiel = new Piratenspiel();
        meinSpiel.deckbau();
        meinSpiel.spielen();
    }
}
 

Reggie()

Bekanntes Mitglied
wenn ich so die verschiedenen Stapel definiere
Java:
List<Karte> ziehStapel =   new ArrayList <Karte>();
List<Karte> ablageStapel = new ArrayList <Karte>();
wie mache ich das dann mit den Händen der verschiedenen Spieler?
mache ich ein mehrdimensionales Array oder eine ArrayList als Attribut der Klasse Spieler?
Java:
Public class Spieler() {
    string name;
    byte nummer;
    List<Karte> handkarten;

    Public Spieler(string name, byte nummer) {
        this.name = name;
        this nummer = nummer;
        List<Karte> handkarten = new ArrayList<Karte>;
        // handkarten würde ich vor der ersten Spielrunde verteilen
    }
}

bevor du wieder fragst: die nummer soll zum "Durchschalten" der Spieler in einer Schleife sein (der Reihe nach). Aber vermutlich macht man das eh wieder anders :)
 

mrBrown

Super-Moderator
Mitarbeiter

JStein52

Top Contributor
Und noch ein Fehler ist drin:
Code:
    Public Spieler(string name, byte nummer) {
        this.name = name;
        this nummer = nummer;
        List<Karte> handkarten = new ArrayList<Karte>;
        // handkarten würde ich vor der ersten Spielrunde verteilen
    }
Damit legst du im Konstruktor von Spieler eine neue (lokale) Liste namens handkarten an. Du musst den Typ davor weglassen.
Code:
    Public Spieler(string name, byte nummer) {
        this.name = name;
        this nummer = nummer;
        handkarten = new ArrayList<Karte>;
        // handkarten würde ich vor der ersten Spielrunde verteilen
    }
 

Reggie()

Bekanntes Mitglied
ich habe das mit den Arrays und ArrayLists nie richtig verstanden. in Basic war das noch super einfach
Code:
Dim handkarten(52) as String
und gut ist
 

mrBrown

Super-Moderator
Mitarbeiter
ich habe das mit den Arrays und ArrayLists nie richtig verstanden. in Basic war das noch super einfach
Code:
Dim handkarten(52) as String
und gut ist
Ist in Java nicht viel schwerer: List<String> handkarten = new ArrayList(); oder String[] handkarten = new String[52] und gut ist ;)
 

mrBrown

Super-Moderator
Mitarbeiter
heisst es nicht List<String> handkarten = new ArrayList<String>; ? als Eckige Klammern statt Runde? und muss der Typ rein oder kann das auch leer bleiben? oder hast du das einfach nur kurz gehalten?
Runde müssen da hin, du willst ja den Konstruktor aufrufen.

Spitze Klammern müssen da hin (die hab ich grad vergessen), den Typ muss man in diesen aber nicht angeben, wenn er durch das List<String> handkarten = klar ist ;)
Richtig wäre also List<String> handkarten = new ArrayList<>();
 

Reggie()

Bekanntes Mitglied
ja klar, jetzt hab ichs verstanden. am "new" erkennt man, dass man ein neues Objekt einer Klasse instanziert. Die Klasse ist hier "ArrayList". und runde Klammern ohne Inhalt "()" kennzeichnen einen Standardkonstruktor. stimmt das soweit?
 

Reggie()

Bekanntes Mitglied
ich mische den ziehStapel Collections.shuffle(ziehStapel)
ziehe ich die erste Karte dann mit ziehStapel.get(0) ?
oder sollte ich ein zufälliges Objekt ziehen? ziehStapel.get((int)(Math.random() * ziehStapel.length);
 

mrBrown

Super-Moderator
Mitarbeiter
Ich persönlich würde mischen und die erste Karte jeweils mit Karte karte = ziehStapel.remove() ziehen, das entfernt die gleichzeitig auch
 

Reggie()

Bekanntes Mitglied
wie würde dieser Befehl aussehen, wenn die Spieler in einem Array sind und ich einen speziellen Spieler zB. nr3 ansprechen will? Spieler.index(3).handkarten.add(ziehStapel.remove(0))
habe grad gelesen, dass die remove.methode keinen Rückgabewert (void) hat, oder habe ich mich da verlesen?
 

mrBrown

Super-Moderator
Mitarbeiter
wie würde dieser Befehl aussehen, wenn die Spieler in einem Array sind und ich einen speziellen Spieler zB. nr3 ansprechen will? Spieler.index(3).handkarten.add(ziehStapel.remove(0))
Im Pinzip so, schöner ist allerdings, wenn der Spieler eine Methode hat, um ihm eine Karte zu geben, und außerhalb des Spielers nicht direkt auf Handkarten zugegriffen wird.

habe grad gelesen, dass die remove.methode keinen Rückgabewert (void) hat, oder habe ich mich da verlesen?
Ne, remove(int) gibt das entfernte Element zurück
 

Reggie()

Bekanntes Mitglied
mein Java-editor sagt, das steckt voller Fehler. also ich kann keine finden.
Java:
public class Piratenspiel {
  public short runde;
  public byte aktiverSpieler;
  public byte final MAXSPIELER = 4;
 
  public Piratenspiel(short r, byte as) {
    runde = r;
    aktiverSpieler = as;
    }
 
  public void naechsteRunde() {
    runde++;
    }
 
  public void naechsterSpieler() {
    if (aktiverSpieler < MAXSPIELER)  
       aktiverSpieler++;
    else
       aktiverSpieler=1;
  }
 
  public static void main( string[] args ) {
    Piratenspiel partie = new Piratenspiel(1,1);
    System.out.println(partie);
    partie.naechsterunde();
    partie.naechsterSpieler();
    System.out.println(partie);
    }
}
ich erwarte die Ausgabe:
runde 1 aktiverSpieler 1
runde 2 aktiverSpieler 2
leider passiert garnichts
 

krgewb

Top Contributor
Bei mir kommen auch Fehler, wenn ich dein Programm in Eclipse lade. Ich habe mal die Fehler als Kommentar dazugeschrieben
Java:
public class Piratenspiel {
    public short runde;
    public byte aktiverSpieler;

    public byte final MAXSPIELER = 4; // Syntax error on token "final", delete this token
 
  public Piratenspiel(short r, byte as) { // Illegal modifier for the constructor in type Piratenspiel;
                                          // only public, protected & private are permitted
    runde = r;
    aktiverSpieler = as;
    }

    public void naechsteRunde() {
        runde++;
    }

    public void naechsterSpieler() {
        if (aktiverSpieler < MAXSPIELER) // MAXSPIELER cannot be resolved to a variable
            aktiverSpieler++;
        else
            aktiverSpieler = 1;
    }

    public static void main(string[] args) { // string cannot be resolved to a type
        Piratenspiel partie = new Piratenspiel(1, 1); // The constructor Piratenspiel(int, int) is undefined
        System.out.println(partie);
        partie.naechsterunde(); // The method naechsterunde() is undefined for the type Piratenspiel
        partie.naechsterSpieler();
        System.out.println(partie);
    }
}
 
Zuletzt bearbeitet:

Reggie()

Bekanntes Mitglied
ok, es heisst nicht byte final MAXSPIELER sondern final byte MAXSPIELER
aber wie kann denn bitte in public static void main(string[] args) { ein Fehler sein????
und die anderen Fehler sagen mir nix. ok, ein Tippfehler naechsterunde statt naechsteRunde
 

Reggie()

Bekanntes Mitglied
ich sollte wohl doch mit Eclipse arbeiten, da hats sowas immer automatisch korrigiert... ich bekomme es dennoch nicht zum laufen :(
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Mein erstes eigenes Projekt - Aufbau und Strukturierung Java Basics - Anfänger-Themen 6
B fragen zu Aufbau eines UML-Klassendiagramm Java Basics - Anfänger-Themen 1
L Best Practice Code Refactoring für Methoden mit fast gleicher Aufbau Java Basics - Anfänger-Themen 6
1 Erste Schritte Aufbau Java Basics - Anfänger-Themen 7
D regex Aufbau Frage Java Basics - Anfänger-Themen 4
R Theoretischer aufbau einer Messenger App? Java Basics - Anfänger-Themen 10
U Erste Schritte Aufbau eines kleinen Matrizen-Programms(MVC; OOP) Java Basics - Anfänger-Themen 20
T Java Projekt aufbau Java Basics - Anfänger-Themen 5
D Best Practice String aufbau - Char Array oder Anhängen Java Basics - Anfänger-Themen 11
A System.out.println() - Aufbau Java Basics - Anfänger-Themen 1
T System.out.print : Frage zu Aufbau Java Basics - Anfänger-Themen 4
T Verständnisfragen zum Aufbau Java Basics - Anfänger-Themen 6
P Systematischer Aufbau einer Klasse Java Basics - Anfänger-Themen 6
M Aufbau der Klassenbibliothek und Referenzvariable Java Basics - Anfänger-Themen 5
D Klassen Aufbau Kartenspiel Java Basics - Anfänger-Themen 20
S DateiSuche - Aufbau der SuFu Java Basics - Anfänger-Themen 2
A Jtree Aufbau Java Basics - Anfänger-Themen 5
T Desktop Anwendung Aufbau Java Basics - Anfänger-Themen 5
7 Interfaces - Aufbau Java Basics - Anfänger-Themen 9
G Aufbau MVC-Pattern Java Basics - Anfänger-Themen 6
G Aufbau Paketstruktur Java Basics - Anfänger-Themen 3
J Tutorials oder Sourcen über den Aufbau kleinerer Apps Java Basics - Anfänger-Themen 2
B Klasse nach Aufbau und Struktur checken? Java Basics - Anfänger-Themen 15
B Aufbau eines Programms Java Basics - Anfänger-Themen 10
J Aufbau von Klassen und zugriff auf alle Variablen Java Basics - Anfänger-Themen 7

Ähnliche Java Themen

Neue Themen


Oben