www.r-krell.de
Webangebot für Schule und Unterricht, Software, Fotovoltaik und mehr

Willkommen/Übersicht  >  Informatik  >  Informatik mit Java, SWE-2   >  Kartenspiel mit Quelltext


Kartenspiel "Rot & Schwarz"

Nach dem Webstart erscheint ein Extra-Fenster mit dem
Kartenspiel-Programm als Ergebnis der Projektarbeit:

Bitte oben zwei Namen eingeben und die [starten]-Taste
drücken, danach [weiter] und/oder [automatisch]



Wenn die Java-JRE installiert ist, können Sie das Programm jetzt sofort ausführen:

Hier klicken zum Webstart des Kartenspiel-Programms Rot&Schwarz

Danach Öffnen von Kartenspiel_RS.jnlp [mit Java(TM) Webstart Launcher (Standard)] wählen/bestätigen
und bei evtl. Sicherheitswarnung vor der Ausführung von RS_Start das Risiko akzeptieren und OK drücken.

Wenn Sie außerdem gefragt werden, ob Sie eine Desktop- und eine Startmenüverknüpfung anlegen wollen,
sollten Sie zustimmen, wenn Sie das Programm auch nach Verlassen dieser Webseite nochmal ausprobieren wollen.

Wird nach dem Klick Kartenspiel_RS.jnlp herunter geladen oder werden Sie gefragt, womit Sie Kartenspiel_RS.jnlp öffnen wollen
oder ob/wohin Sie die Datei speichern wollen, haben Sie entweder kein Java installiert oder ihr Browser (z.B. Opera) unterstützt keinen Webstart.
Im letzten Fall empfiehlt sich nachfolgend der Download der .jar-Datei:

Sie können Kartenspiel auch als ausführbare Java-Datei Kartenspiel_Rot&Schwarz(r-krell.de).jar (71 kB) herunter laden und später lokal auf Ihrem Rechner starten (Java-Umgebung JRE vorausgesetzt). Die Ausführung als Applet im Browser wird von mir hingegen nicht mehr angeboten: Gründe, Abhilfe und alle Downloads (in neuem Tab)



Nachfolgend der vollständige Quelltext des "Rot & Schwarz"-Applets (für Erläuterungen vgl. meine Seite "Softwareengineering und Projektarbeit").
Jede Klasse steht in einer eigenen, gleichnamigen Datei:


zum Inhaltsverzeichnis (oben) / zum Seitenende

Startdatei

Diese - im UML-Diagramm noch nicht enthaltene Datei - startet das Kartenspiels je nach Umgebung (Web oder lokal) automatisch als Applet oder als Application


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 6.6.2013
>  
>  // Startdatei für den Start entweder als Applet oder als Application, je nach Umgebung
>  
>  
public class RS_Start extends javax.swing.JApplet
>    
// entweder extends javax.swing.JApplet oder extends java.applet.Applet 
>  
{        
>   
public static void main (String[] s)
>   {
>    RS_SpielGUI sp = 
new RS_SpielGUI("Rot&Schwarz (r-krell.de)"); // als Application
>  
 }
>   
>   
public void init()  
>   {
>    RS_SpielGUI sp = 
new RS_SpielGUI("r-krell.de Rot&Schwarz");   // als Applet
>  
 }
>  } 


zum Inhaltsverzeichnis (oben) / zum Seitenende

Oberfläche des Kartenspiels

Die Oberfläche wurde weitgehend mit dem GUI-Builder vom Java-Editor erstellt. Bitte beachten Sie die Hinweise/Kommentare zur Grafik!

  
>  
// Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 6.6.2013
>  
>  // Grafische Oberfläche, die außerdem alle weiteren Objekte definiert/erzeugt/enthält.
>  // Stellt Eingabe-, Steuerungs- und Ausgabe-Möglichkeiten für das Spiel bereit.
>  // Die Oberfläche wurde weitgehend mit dem GUI-Builder vom Javaeditor (Version 11.39) erzeugt
>  // und von Hand ergänzt. Der Start als Applet oder als Application erfolgt aus RS_Start.
>  
>  // Die Spielregeln bzw. die Spielidee sind/ist in RS_Spiel beschrieben!
>  
>  
import java.awt.*;
>  
import java.awt.event.*;
>  
import javax.swing.*;
>  
import javax.swing.event.*;
>  
>  
/**
>   *
>   * Rot & Schwarz = Tod & Leben - Kartenspiel
>   *
>   * @version 2.1 vom 06.06.2013 (v1 vom 02.05.2013)
>   * @author R. Krell (www.r-krell.de)
>   */
>  
>  
public class RS_SpielGUI extends JFrame {
>   
// Anfang Attribute
>  
 RS_Spiel spiel; // Spiel (eigener Thread)
>  
 RS_Ablaufkontrolle ak = new RS_Ablaufkontrolle(); // hierauf greifen diese Oberfläche 
>  
  // und das spiel zu: Druck von weiter und automatisch wird registriert 
>  
 String bildVrz = "bilder/"// Name des Unterverzeichnisses für die Kartenbilder
>  
          // ".\\bilder\\" geht nicht für alle Fälle (inkl. .jar); 
>  
 private JTextField jTfZahl = new JTextField();
>   
private JLabel jLabel1 = new JLabel();
>   
private JTextField jTfSpielerR = new JTextField();
>   
private JLabel jLabel2 = new JLabel();
>   
private JTextField jTfSpielerS = new JTextField();
>   
private JLabel jLbAnzR = new JLabel();
>   
private JLabel jLbAnzS = new JLabel();
>   
private JButton jBtStart = new JButton();
>   
private JLabel jLabel3 = new JLabel();
>   
private JTextField jTfKarteR = new JTextField();
>   
private JLabel jLabel4 = new JLabel();
>  
 private JTextField jTfKarteS = new JTextField();
>  
 private JLabel jLbBildR = new JLabel(); // doch Label zur..
>  
 private JLabel jLbBildS = new JLabel(); // ..Anzeige der gelegten Karten
>  
 private ImageIcon ii = new ImageIcon(getClass().getResource(bildVrz+"bottom02.gif")); //!!! 
>  
  // Für das Laufenlassen des Spiels als normale Application mit lokalem Bildverzeichnis reicht
>  
  // ii = new ImageIcon(bildVrz+"bottom02.gif"); 
>  
  // Aber Applets dürfen keine Disk-I/0-Operationen machen. 
>  
  // Und das Spiel könnte so nicht zusammen mit den Bildern in .jar-Datei gepackt werden. 
>  
  // Mit getClass().getResource(..) ist hingegen das Bilder-Laden sowohl lokal wie aus/im .jar
>  
  // und sowohl für Applets wie für Applications möglich!
>  
 private JLabel jLbZaehler = new JLabel();
>   
private JTextField jTfStich = new JTextField();
>   
private JButton jBtWeiter = new JButton();
>   
private JButton jBtAuto = new JButton();
>   
private JTextField jTfGewinner = new JTextField();
>   
private JTextArea jTaAusgabe = new JTextArea("");
>    
private JScrollPane jTaAusgabeScrollPane = new JScrollPane(jTaAusgabe);
>   
>   
private JLabel jLabel0 = new JLabel();
>   
// Ende Attribute
>  
 
>   
public RS_SpielGUI(String title) {
>    
// Frame-Initialisierung
>  
  super(title);
>    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
>    
int frameWidth = 298
>    
int frameHeight = 460;
>    
// Höhe 640 mit Anzeige von jTaAusgabe, 464 ohne.
>  
  setSize(frameWidth, frameHeight);
>    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
>    
int x = (d.width - getSize().width) / 2;
>    
int y = (d.height - getSize().height) / 2;
>    setLocation(x, y);
>    Container cp = getContentPane();
>    cp.setLayout(
null);
>    
// Anfang Komponenten
>  
  
>    jTfZahl.setBounds(
128402524);
>    jTfZahl.setText(
"32");
>    jTfZahl.setToolTipText(
"Spiel mit 32 oder mit 52 Karten");
>    jTfZahl.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jTfZahl);
>    jLabel1.setBounds(
40165520);
>    jLabel1.setText(
"Spieler 1");
>    jLabel1.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    cp.add(jLabel1);
>    jTfSpielerR.setBounds(
84011324);
>    jTfSpielerR.setText(
"(rot)");
>    jTfSpielerR.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfSpielerR.setToolTipText(
"Name des 1. Spielers");
>    jTfSpielerR.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jTfSpielerR);
>    jLabel2.setBounds(
192165520);
>    jLabel2.setText(
"Spieler 2");
>    jLabel2.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    cp.add(jLabel2);
>    jTfSpielerS.setBounds(
1604011324);
>    jTfSpielerS.setText(
"(schwarz)");
>    jTfSpielerS.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfSpielerS.setToolTipText(
"Name des 2. Spielers");
>    jTfSpielerS.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jTfSpielerS);
>    jLbAnzR.setBounds(
48643519);
>    jLbAnzR.setText(
"0");
>    jLbAnzR.setToolTipText(
"zeigt an, wieviele Karten Spieler 1 (noch) hat");
>    jLbAnzR.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jLbAnzR);
>    jLbAnzS.setBounds(
200643519);
>    jLbAnzS.setText(
"0");
>    jLbAnzS.setToolTipText(
"Anzahl der Karten, die Spieler 2 (noch) hat");
>    jLbAnzS.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jLbAnzS);  
>    jBtStart.setBounds(
768812925);
>    jBtStart.setText(
"starten");
>    jBtStart.setMargin(
new Insets(2222));
>    jBtStart.addActionListener(
new ActionListener() {
>  
   public void actionPerformed(ActionEvent evt) {
>  
    jBtStart_ActionPerformed(evt);
>     }
>    });
>    jBtStart.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jBtStart.setToolTipText(
"Knopfdruck startet das Spiel und beide Spieler legen je eine Karte");
>    cp.add(jBtStart);
>    jLabel3.setBounds(
561122520);
>    jLabel3.setText(
"legt");
>    jLabel3.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    cp.add(jLabel3);
>    jTfKarteR.setBounds(
813611324);
>    jTfKarteR.setText(
"(Karte)");
>    jTfKarteR.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfKarteR.setEditable(
false);
>    jTfKarteR.setHorizontalAlignment(SwingConstants.CENTER);
>    jTfKarteR.setToolTipText(
"letzte von Spieler 1 gespielte Karte");
>    cp.add(jTfKarteR);
>    jLabel4.setBounds(
2081122520);
>    jLabel4.setText(
"legt");
>    jLabel4.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    cp.add(jLabel4);
>    jTfKarteS.setBounds(
16013611324);
>    jTfKarteS.setText(
"(Karte)");
>    jTfKarteS.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfKarteS.setEditable(
false);
>    jTfKarteS.setHorizontalAlignment(SwingConstants.CENTER);
>    jTfKarteS.setToolTipText(
"letzte von Spieler 2 gespielte Karte");
>    cp.add(jTfKarteS);
>    jLbBildR.setBounds(
361686195);
>    jLbBildR.setIcon(ii); 
// Anfangsbild vor Spielbeginn
>  
  // Es erwies sich als besser, oben bereits ii zu initialisieren. Wenn auf ii verzichtet wird
>  
  // und hier jLbBildR.setIcon(new ImageIcon(getClass().getResource(bildVrz+"bottom02.gif")));
>  
  // steht, wurde z.T. das Erstbild nicht richtig angezeigt -- evtl. weil nicht rechtzeitig bzw.
>  
  // vollständig geladen vor dem nachfolgenden cp.add(jLbBildR)
>  
  jLbBildR.setToolTipText("letzte von Spieler 1 gespielte Karte (als Bild)");
>    cp.add(jLbBildR);
>    jLbBildS.setBounds(
1861686195);
>    jLbBildS.setIcon(ii); 
// Anfangsbild vor Spielbeginn, s. Kommentar 4 Zeilen höher
>  
  jLbBildS.setToolTipText("letzte von Spieler 2 gespielte Karte (als Bild)");
>    cp.add(jLbBildS);  
>    jLbZaehler.setBounds(
962409133);
>    jLbZaehler.setText(
"0");
>    jLbZaehler.setToolTipText(
"zählt die insgesamt gespielten Karten");
>    jLbZaehler.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jLbZaehler);  
>    jTfStich.setBounds(
7628812924);
>    jTfStich.setText(
"(letzter Stich)");
>    jTfStich.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfStich.setEditable(
false);
>    jTfStich.setToolTipText(
"zeigt, wer die Karten auf dem Tisch bekommt bzw. bekommen hat");
>    jTfStich.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jTfStich);  
>    jBtWeiter.setBounds(
7632012925);
>    jBtWeiter.setText(
"weiter");
>    jBtWeiter.setMargin(
new Insets(2222));
>    jBtWeiter.addActionListener(
new ActionListener() { 
>     
public void actionPerformed(ActionEvent evt) { 
>      jBtWeiter_ActionPerformed(evt);
>     }
>    });
>    jBtWeiter.setToolTipText(
"jeder Spieler legt 1 Karte, dann Pause");
>    cp.add(jBtWeiter);
>    jBtAuto.setBounds(
7635212925);
>    jBtAuto.setText(
"automatisch");
>    jBtAuto.setMargin(
new Insets(2222));
>    jBtAuto.addActionListener(
new ActionListener() { 
>     
public void actionPerformed(ActionEvent evt) { 
>      jBtAuto_ActionPerformed(evt);
>     }
>    });
>    jBtAuto.setToolTipText(
"Spiel läuft automatisch, bis [weiter] gedrückt wird oder das Spiel endet");
>    cp.add(jBtAuto);                
//!
>  
  jTfGewinner.setBounds(839226524);
>    jTfGewinner.setText(
"Bitte Namen eingeben und [starten]");
>    jTfGewinner.setFont(
new Font("Dialog", Font.PLAIN, 13));
>    jTfGewinner.setToolTipText(
"hier wird am Ende der Gewinner genannt");
>  
  jTfGewinner.setHorizontalAlignment(SwingConstants.CENTER);
>  
  jTfGewinner.setEditable(false);
>    cp.add(jTfGewinner);
>    
>    jTaAusgabeScrollPane.setBounds(
8456265137);
>    jTaAusgabe.setToolTipText(
"für Kontrollausgaben während der Programmentwicklung");
>    cp.add(jTaAusgabeScrollPane);
>    jLabel0.setBounds(
8026719);
>    jLabel0.setText(
"Kartenspiel \"Rot & Schwarz\", (C) R. Krell");
>    jLabel0.setHorizontalAlignment(SwingConstants.CENTER);
>    cp.add(jLabel0);
>    
// Ende Komponenten
>  
  
>    setResizable(
false);
>    setVisible(
true);
>   }
>   
>   
// Anfang Methoden
>  
 public void jBtStart_ActionPerformed(ActionEvent evt) {
>    
int kartenzahl = 0;
>    
try
>  
  {
>     kartenzahl = Integer.parseInt(jTfZahl.getText());
>    }
>    
catch (Exception x) { }
>    
if (kartenzahl != 32 && kartenzahl != 52
>    {
>     jTfGewinner.setText (
"** nur 32 oder 52 Karten erlaubt **");
>    } 
>    
else // Spiel starten!
>  
  { 
>     spiel = 
new RS_Spiel (ak, jTfSpielerR.getText(), jTfSpielerS.getText(), kartenzahl, bildVrz,
>     jLbAnzR, jLbAnzS, jTfKarteR, jTfKarteS, jLbBildR, jLbBildS, jLbZaehler,jTfStich, jTfGewinner, jTaAusgabe);
>     
>     spiel.start(); 
// Aufruf von Spiel in eigenem Thread -- sonst bzw. beim Aufruf von run
>  
   // bliebe [starten] gedrückt, bis das Spiel zu Ende ist und zwischenzeitlich könnten 
>  
   // weder [weiter] noch [automatisch] gedrückt werden! 
>  
   
>    }
>    jBtWeiter.requestFocus();
>   }
>   
>   
public void jBtWeiter_ActionPerformed(ActionEvent evt) {
>    ak.automatisch = 
false;
>    ak.weiter = 
true;
>   } 
// end of jBtWeiter_ActionPerformed
>  
 
>   
public void jBtAuto_ActionPerformed(ActionEvent evt) {
>    ak.automatisch = 
true;
>    ak.weiter = 
false;
>    jBtWeiter.requestFocus();
>   } 
// end of jBtAuto_ActionPerformed
>  
 
>   
// Ende Methoden
>  
 
>   
// main jetzt in RS_Start !
>  
 // public static void main(String[] args) {
>  
 //  new RS_SpielGUI("Rot&Schwarz (r-krell.de)");
>  
 // }
>  
}


zum Inhaltsverzeichnis (oben) / zum Seitenende

Ablaufkontrolle

Bauplan für das Objekt ak bzw. aK, das den Datenaustausch zwischen der Oberfläche und dem eigentlichen Spiel (=Spielkontrolle) ermöglicht, die in parallelen Threads ablaufen


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  // Auf die beiden hier gespeicherten Attribute greifen lesend und schreibend die
>  // beiden parallelen Threads RS_SpielGUI und RS_Spiel zu. Damit dient die
>  
// Ablaufkontrolle zum Nachrichtenaustausch zwischen den beiden Threads.
>  
>  
public class RS_Ablaufkontrolle
>  
{
>   
boolean automatisch = false;
>   
boolean weiter = false;
>   
>   
// weiter wird bei Druck auf die Taste [weiter] in RS_SpielGUI auf true 
>  
 // und nach einem Stich aus RS_Spiel auf false gesetzt,
>  
 // automatisch wird aus RS_SpielGUI durch Druck auf [automatisch] true und durch
>  
 // tastendruck auf [weiter] false. automatisch wird aus RS_Spiel gelesen.
>  
 
>   
>   
public void warte()
>   
// mit warte wird in RS_Spiel nach jedem Stich bzw. jedem gelegten Kartenpaar
>  
 // kurz mit der hier fest eingestellten Zeit pausiert, damit man die gelegten
>  
 // Karten sehen kann 
>  
 {
>    
try
>  
  {
>     Thread.sleep(
200);
>    }
>    
catch (InterruptedException ie)
>    {
>     System.out.println(
"** Fehler beim Warten: "+ie);
>    }
>   }
>   
>  }


zum Inhaltsverzeichnis (oben) / zum Seitenende

Spiel

Eigentliche Funktionalität des Spiels (= Spielkontrolle): läuft parallel zur Oberfläche in einem eigenen Thread. Erhält von der Oberfläche viele Oberflächenelemente (wie Textfelder u.ä), um sie direkt zu füllen. Benutzt zusammen mit der Oberfläche ein gemeinsames Objekt aK zur Ablaufkontrolle/Datenaustausch.


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 6.6.2013
>  
>  // Spielidee: Zwei Spieler erhalten anfangs jeweils die Hälfte aller gemischten Karten (einer alle roten, der andere
>  // alle schwarzen Karten). Die Spieler dürfen diese Karten nicht in der Reihenfolge ändern, sondern müssen immer
>  // von oben runter spielen (keine Strategie -- reines Glücksspiel, das durch die anfängliche Kartenverteilung
>  // vollständig vorher bestimmt ist!). Anfangs legt Spieler r eine Karte auf den Tisch, dann Spieler s. 
>  // Wer die höhere Karte hat, gewinnt den Stich und nimmt die Karten vom Tisch hinten an seine dran. 
>  // Sind die gelegten Karten gleichwertig (z.B. zwei Buben oder zwei 7er), blieben sie auf dem Tisch und beide 
>  // Spieler legen solange weitere Karten auf den Tisch, bis ein nicht-gleichwertiges Paar kommt und der
>  // Gewinner alle Karten vom Tisch als fetten Stich abräumen darf.
>  // Der Gewinner des letzten Stichs spielt als nächstes aus, der andere legt eine Karte dazu, usw.
>  // Verloren hat, wer keine Karten mehr legen kann/hat. Steht innerhalb von z.B. 1000 Stichen kein Verlierer fest,
>  // gilt das Spiel als unentschieden (weil es sonst endlos werden könnte).
>  
>  // Hier in RS_Spiel werden (nach Erzeugen und Start aus der Oberfläche RS_SpielGUI) die eigentlichen
>  // Aktionen und Funktionen des Spiels in einem eigenen Thread ausgeführt, der parallel zur Oberfläche läuft.
>  // RS_Spiel verwaltet zwei Spieler (RS_Spieler) und den (lokalen) Tisch und sorgt (in run()) dafür,
>  // dass die Spieler abwechselnd Karten legen und Stiche einsammeln, bis ein Spieler keine Karten mehr hat.
>  
>  // Der Spielablauf -- automatisch oder per Einzelschritt mit [weiter] nach jedem Stich -- wird über das Objekt aK
>  // vom Typ RS_Ablaufkontrolle beinflusst, das RS_SpielGUI und RS_Spiel gemeinsam benutzen.
>  // Damit der Spielablauf auf der Oberfläche angezeigt werden kann, erhält der Konstruktor die (Adressen/Referenzen
>  // der) in der Oberfläche definierten, erzeugten und verankerten GUI-Komponenten, um diese hier direkt
>  // mit den aktuellen Texten und Bildern füllen zu können.  
>  
>  
import javax.swing.*;
>  
>  
public class RS_Spiel extends Thread
>  {
>   
int gesamtKarten = 0;   // Anzahl der bisher gespielten Karten 
>  
 int stich = 0;          // Nummer des aktuellen Stichs
>  
 int maxStiche = 1000;   // Nach dieser Zahl von Stichen gilt das Spiel als unentschieden
>  
 RS_Ablaufkontrolle aK;  // Objekt wird gemeinsam mit der Oberfläche genutzt zum Austausch zwischen den Threads
>  
 String bildordner;      // Name der Unterverzeichnisses, in dem die Bilddateien liegen
>  
 JLabel jLbAnzR;         // Oberflächen-Komponente(n), in der/denen die Zahl der Karten ..
>  
 JLabel jLbAnzS;         // .. des jeweiligen Spielers angezeigt wird
>  
 JTextField jTfKarteR;   // Oberflächen-Komponente(n), in der/denen die von dem Spieler zuletzt ausgespielte ..
>  
 JTextField jTfKarteS;   // .. Karte als Text (z.B. "Herz 10") angezeigt wird 
>  
 JLabel jLbBildR;        // Oberflächen-Komponente(n), in der/denen das Bild der von dem Spieler zuletzt 
>  
 JLabel jLbBildS;        // .. ausgespielten Karte grafisch angezeigt wird
>  
 JLabel jLbZaehler;      // Hier wird die Zahl der ausgespielten Karten gezeigt
>  
 JTextField jTfStich;    // Hier wird als Text angezeigt, welcher Spieler den letzten Stich gewonnen hat
>  
 JTextField jTfGewinner; // Hier werden anfangs Hinweistexte und zum Schluss der Gewinner des gesamten Spiels angezeigt
>  
 JTextArea jTaAusgabe;   // für die Ausgabe von Kontrollmeldungen während der Programmentwicklung (im fertigen Spiel 
>  
 // unsichtbar, weil außerhalb des nachträglicvh verkürzten Frames)
>  
 
>   RS_Spieler r, s;        
// die beiden Spieler
>  
 RS_Schlange<RS_Karte> tisch;   // der Tisch, auf dem die ausgespielten Karten landen
>  
 
>   
public RS_Spiel (RS_Ablaufkontrolle _ak, String nameR, String nameS, int kartenzahl, String vrz,
>   JLabel _jLbAnzR, JLabel _jLbAnzS, JTextField _jTfKarteR, JTextField _jTfKarteS, JLabel _bfR, JLabel _bfS,
>   JLabel _jLbZaehler, JTextField _jTfStich, JTextField _jTfGewinner, JTextArea _jTaAusgabe)
>   {  
>    
super();               // Initialisieren des Threads              
>  
  
>    aK = _ak;
>    bildordner = vrz;
>    jLbAnzR = _jLbAnzR;
>    jLbAnzS = _jLbAnzS;
>    jTfKarteR = _jTfKarteR;
>    jTfKarteS = _jTfKarteS; 
>    jLbBildR = _bfR;
>    jLbBildS = _bfS;
>    
>    jLbZaehler = _jLbZaehler;
>    jTfStich = _jTfStich;
>    jTfGewinner = _jTfGewinner; 
>    jTaAusgabe = _jTaAusgabe;  
>    
>    r = 
new RS_Spieler();                           // Erzeugen der beiden Spieler
>  
  s = new RS_Spieler();
>    r.name = nameR;
>    s.name = nameS;
>    RS_Blatt kartendeck = 
new RS_Blatt(kartenzahl); // Erzeugen der Spielkarten
>  
  // jTaAusgabe.setText(kartendeck.kontrolle());
>  
  
>    kartendeck.mischen();                           
// Mischen der Spielkarten
>  
  r.anfangsKartenAufnehmen(kartendeck,"rot");     // Verteilen der Karten an ..
>  
  jLbAnzR.setText(""+r.kartenZahl());
>    jTaAusgabe.append(r.kontrolle());
>    s.anfangsKartenAufnehmen(kartendeck,
"schwarz"); // .. die beiden Spieler
>  
  jLbAnzS.setText(""+s.kartenZahl());
>    jTaAusgabe.append(s.kontrolle());
>    tisch = 
new RS_Schlange<RS_Karte>();            // Erzeugen des (leeren) Tischs (=Karten auf Tisch)
>  
 }
>   
>   
public void run() // eigentliche Spiel-Methode, muss run() heißen, damit sie durch den
>  
 // Aufruf von start (der in RS_SpielGUI bei Druck auf [starten] erfolgt) als eigener Thread läuft
>  
 {
>    RS_Karte karteR;
>    RS_Karte karteS;
>    RS_Spieler gewinner = r; 
// Der Gewinner des letzten Stichs spielt als Erster auf. Rot fängt an.
>  
  char richtung;
>    
boolean gleichwertig;
>    
int gleichePaare;
>    
>    
while (!r.hatVerloren() && !s.hatVerloren() && stich < maxStiche)
>    {
>     gleichePaare = 
0;                 // zählt mit, wie viele Paare gleichwertiger Karten auf dem Tisch liegen
>  
   do
>  
   {
>      gleichwertig = 
false;
>  
    karteR = r.spieltAuf();          // weil die Karten beider Spieler praktisch gleichzeitig ..
>  
    karteS = s.spieltAuf();          // .. angezeigt werden, ist hier die Reihenfolge egal/fest
>  
    gesamtKarten = gesamtKarten + 2;
>      jTfKarteR.setText(karteR.karteAlsText());
>      jTfKarteS.setText(karteS.karteAlsText());
>      jLbAnzR.setText(
""+r.kartenZahl());
>      jLbAnzS.setText(
""+s.kartenZahl());
>  
    jLbBildR.setIcon(new ImageIcon(getClass().getResource(bildordner+karteR.nenneDateinamen()))); // vgl. Kommentar //!!! in ..
>  
    jLbBildS.setIcon(new ImageIcon(getClass().getResource(bildordner+karteS.nenneDateinamen()))); // .. RS_SpielGUI bei ii !
>  
    jLbZaehler.setText(""+gesamtKarten);
>      
if (gewinner == r)               // auf dem Tisch müssen die Karten aber in der richtigen ..
>  
    {                                // .. Reihenfolge liegen (und später so aufgenommen werden) *)
>  
     tisch.rein(karteR);             // Gewinner des letzten Stichs kommt zuerst!
>  
     tisch.rein(karteS);
>      } 
>      
else
>  
    {
>       tisch.rein(karteS);
>       tisch.rein(karteR);
>      }                      
>      
// *) Hinweis: Würde immer der gleiche Spieler zuerst ausspielen und würden die Karten immer z.B. 
>  
    // erst von Spieler 1 (r), dann von Spieler 2 (s) aufgenommen, kommt es zu Endlos-Spielen ohne Gewinner!
>  
    
>      
// // Kontrollausgabe während der Programmentwicklung:  
>  
    // jTaAusgabe.setText("auto="+aK.automatisch+", weiter="+aK.weiter+"\n"+stich+"\nTisch "+tisch.kontrolle());
>  
    
>      gleichwertig = (karteR.stechkraft() == karteS.stechkraft());
>      
if (gleichwertig)
>      {
>       gleichePaare++;
>       
if (gleichePaare==1
>       {
>        jTfStich.setText(
"1 Paar: noch 2");
>       }
>       
else
>  
     {
>        jTfStich.setText(
""+gleichePaare+" Paare: noch 2");  
>       }
>       pausieren();
>       
// und dann nächstes Kartenpaar legen (durch do..while)
>  
    } // end of if
>  
    
>     } 
while (gleichwertig && !r.hatVerloren() && !s.hatVerloren());
>     stich++;                    
// Stichzähler erhöhen
>  
   
>     
if (!gleichwertig) 
>     {    
>      gewinner = s;
>      richtung = 
'>';
>      
if (karteR.stechkraft() > karteS.stechkraft())
>      {
>       gewinner = r;
>       richtung = 
'<';
>      }
>      
int i=0;
>      
while (!tisch.istLeer())   // Der Gewinner des letzten Stichs nimmt alle Karten vom Tisch
>  
    {
>       gewinner.nimmtVomTisch(tisch.raus());
>       i++;
>      }
>      jTfStich.setText(
""+i+" an "+richtung+" "+gewinner.name);  // Stich-Gewinn wird angezeigt
>  
   } 
>     jLbAnzR.setText(
""+r.kartenZahl());      // aktueller Kartenbesitz beider Spieler ..
>  
   jLbAnzS.setText(""+s.kartenZahl());      // .. wird angezeigt
>  
   pausieren();
>    }
>    
>    
>    
if (stich >= maxStiche)
>    {
>     jTfGewinner.setText(
"Unentschieden nach "+stich+" Stichen!"); 
>    } 
>    
else
>  
  {   
>     
if (r.hatVerloren())        // Wenn einer der beiden Spieler keine Karten mehr hat, ..
>  
   {
>  
    gewinner = s;     
>     } 
>     
else                        // .. hat der andere das Spiel insgesamt gewonnen ..
>  
   {
>      gewinner = r; 
>     }   
>     jTfGewinner.setText(
"Gewonnen hat "+gewinner.name+" nach "+stich+" Stichen");
>    }
>  
 } 
>   
>   
>   
private void pausieren()  // je nach Ablaufkontrolle wird eine kurze Zeit oder auf Tastendruck von [weiter] gewartet
>  
 {                         // Die Werte in aK werden auch parallel zum Spiel in der Oberfläche geändert!
>  
  if (aK.automatisch)
>    {
>     jTfGewinner.setText(
".. Spiel läuft automatisch ..");
>    }
>    
else 
>    {
>     jTfGewinner.setText(
".. Spiel läuft: [weiter] nötig .."); 
>    }
>    
do
>  
  {
>     aK.warte();                
// bei automatischen Spielablauf geht's nach kurzer Pause automtisch ..
>  
  } while (!aK.automatisch && !aK.weiter);   // .. weiter, sonst wird auf Tastendruck [weiter] gewartet
>  
  aK.weiter = false;          // (damit nach nächstem Stich wieder [weiter] nötig wird 
>  
 }
>  } 


zum Inhaltsverzeichnis (oben) / zum Seitenende

Knoten

für die (generische) Schlange, mit der hier die Karten der beiden Spieler und auf dem Tisch verwaltet werden (jede Karte in einem Knoten)


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  
public class RS_Knoten<Elementtyp>
>   
// Knoten zur allgemeinen Verwendung in der RS_Schlange
>  
 // Hier werden Schlangen von Karten (Elementtyp = RS_Karte) verwendet
>  
{
>   Elementtyp inhalt;             
// hierhin kommt das gespeicherte Element
>  
 RS_Knoten<Elementtyp> zeiger;  // hier merkt man sich den Knoten mit dem vorher
>  
                                // eingekellerten oder nachher eingeschlangten Element
>  
 
>   
public RS_Knoten (Elementtyp i, RS_Knoten<Elementtyp> z)
>   {
>    inhalt = i;
>    zeiger = z;
>   }
>  }


zum Inhaltsverzeichnis (oben) / zum Seitenende

(Warte-)Schlange

zum Verwalten der Karten der beiden Spieler und der Karten auf dem Tisch. Als Elementtyp hier wird RS_Karte verwendet. Die allgemeine generische (typisierbare) Struktur wurde hier noch um das Attribut anzahl und die Methode nenneAnzahl ergänzt, damit leicht ermittelt und angezeigt werden kann, wie viele Karten jeder Spieler gerade hat.


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  
public class RS_Schlange<Elementtyp>
>   
// dynamische Schlange unter Verwendung von RS_Knoten mit Zeigern.
>  
 // Im Kartenspiel hat jeder der beiden RS_Spieler eine Schlange von seinen Karten ("hand");
>  
 // außerdem werden bei einem Stich die auf dem Tisch liegenden Karten in 
>  
 // in der Schlange RS_Spiel.tisch verwaltet. Elementtyp = RS_Karte.
>  
 
>   
// Zur 'normalen' Schlange wurden hier noch die beiden zusätzliche Methoden
>  
 // kontrolle und nenneAnzahl hinzugefügt
>  
{
>   RS_Knoten<Elementtyp> kopf = 
null;
>   RS_Knoten<Elementtyp> schwanz = 
null;
>   
int anzahl = 0;
>   
>   
public void rein (Elementtyp neuesEl)
>   {
>    RS_Knoten<Elementtyp> neuerKnoten = 
new RS_Knoten<Elementtyp> (neuesEl, null);
>    
if (istLeer())
>    {
>     kopf = neuerKnoten;
>    }
>    
else
>  
  {
>     schwanz.zeiger = neuerKnoten;
>    }
>    schwanz = neuerKnoten;
>    anzahl++;
>   }
>   
>   
public boolean istLeer()
>   {
>    
return (kopf == null);
>   }
>   
>   
public Elementtyp zeige1()
>   {
>    
return (kopf.inhalt);
>   }
>   
>   
public Elementtyp raus()
>   {
>    Elementtyp entnommenesElement = kopf.inhalt;
>  
  kopf = kopf.zeiger;
>  
  anzahl--;
>  
  return (entnommenesElement);
>   }
>   
>   
public String kontrolle()  // zusätzlich zum Testen während der Entwicklung
>  
 {
>    String aus = 
"Schlange:\n";
>    RS_Knoten<Elementtyp> hilf = kopf;
>    
int i=0;
>    
while (hilf != null
>    {
>     aus = aus + i+
") "+((RS_Karte)hilf.inhalt).karteAlsText()+"\n";
>     i++;
>     hilf = hilf.zeiger;
>    }
>    
return (aus+"--("+anzahl+")----\n");
>   }
>   
>   
public int nenneAnzahl()   // zusätzlich, damit leicht festgestellt und
>  
                            // angezeigt werden kann, wie viele Karten jeder Spieler hat
>  
 {
>    
return (anzahl);
>   }
>  }


zum Inhaltsverzeichnis (oben) / zum Seitenende

(Spiel-)Karte


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  // Bauplan für eine Spielkarte. Erzeugen und Verwalten in/durch RS_Blatt
>  
>  
public class RS_Karte 
>  {
>   
>   
// Anfang Attribute
>  
 private String farbe;     // wie "Kreuz", "Karo",..
>  
 private String typ;       // wie "As", "7" oder "Bube" ...
>  
 private int wert;         // höherer Wert bedeutet Überlegenheit beim Stechen
>  
 private String bilddatei; // Name der Bilddatei, z.B. "08c.gif" für Kreuz 8 (s. RS_Blatt)
>  
 static int anzahlAllerKarten = 0;
>   
// Ende Attribute
>  
 
>   
public RS_Karte(String f, String t, int w, String bilddateiname) 
>   {
>    farbe = f;
>    
this.typ = t;
>    
this.wert = w;
>    bilddatei = bilddateiname;
>    anzahlAllerKarten++;
>   }
>   
>   
// Anfang Methoden
>  
 public String karteAlsText() 
>   {
>    
return (farbe+" "+typ);
>   }
>   
>   
public boolean istRot ()  // damit anfangs einer alle roten, 
>  
  // der andere alle schwarzen Karten kriegen kann
>  
 {
>    
return (farbe.equals("Herz") || farbe.equals("Karo"));
>   }
>   
>   
public int stechkraft() 
 {
>    
return (wert);
>   
}
>  
 
>   
public String nenneDateinamen ()
>   {
>    
return (bilddatei);
>   }
>   
>   
// Ende Methoden
>  
}


zum Inhaltsverzeichnis (oben) / zum Seitenende

Blatt (= Kartendeck)

erzeugt und mischt anfangs sämtliche im Spiel verwendeten Karten. Die Methoden anDenAnfang, esGibtNächste und nächsteKarte wären gar nicht nötig gewesen, weil die reihe gar nicht privat ist. Insofern wäre beim Spieler (s.u.) in der Methode anfangsKartenAufnehmen das Aufnehmen der Karten wirklich so einfach zu programmieren, wie im Feinentwurf dargestellt (wo die Methode noch nimmAnfangsKarten hieß).


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  // Hier werden alle 32 oder 52 Karten des gesamten verwendeten Kartenpäckchens (=Blatt) verwaltet.
>  // Insbesondere werden die Karten erzeugt und in der 1-dim. Reihung reihe abgelegt, können
>  // dort gemischt und mit anDenAnfang, esGibtNächste und nächsteKarte ausgelesen werden.
>  
>  
public class RS_Blatt
>  {
>   String[] farbe = {
"Kreuz""Pik""Herz""Karo"};
>   
char[]   farbB = { 'c'   ,  's' ,  'h'  ,  'd'  };  // Farb-Bez. für Bilddateien: clubs, spade, heart, diamonds;
>  
 
>   String[] typ   = {
"As","König","Dame","Bube","10", "9""8""7""6""5""4""3""2"}; // Bezeichnung
>  
 int[]    wert  = { 21 ,  14   ,  13  ,  12  , 10 ,  9 ,  8 ,  7 ,  6 ,  5 ,  4 ,  3 ,  2 }; // Stechkraft
>  
 String[] datB  = {"01""13"  , "12" "11" ,"10","09","08","07","06","05","04","03","02"}; // Bez. für Bilddateien
>  
 
>   
int kartenAnzahl;
>   RS_Karte[] reihe;
>   
 
>   
public RS_Blatt (int anzahl)
>   {
>    
if (anzahl != 32 && anzahl != 52
>    {
>     System.out.println(
"** Fehler: Unerlaubte Kartenzahl **"+anzahl+"** (statt 32 oder 52) in RS_Blatt**"); 
>     
return;
>    } 
>    kartenAnzahl = anzahl;
>    
int i = 0;
>    reihe = 
new RS_Karte[anzahl];
>  
  
>    
for (int f=0; f<4; f++) 
>    {
>     
for (int nr=0; nr<anzahl/4 ; nr++)
>     {
>      reihe[i] = 
new RS_Karte (farbe[f], typ[nr], wert[nr], datB[nr]+farbB[f]+".gif");
                                                          // ^ z.B. "08c.gif" für Kreuz 8 
>  
    i++;
>     } 
// end of for nr
>  
  } // end of for f
>  
  // kontrolle();
>  
 }
>   
>   
private void tausche (int a, int b)
>   {
>    RS_Karte hilf = reihe[a];
>    reihe[a] = reihe[b];
>    reihe[b] = hilf;
>   }      
>   
>   
public void mischen()
>   {
>    
for (int i=0; i<100; i++) 
>    {
>     
int a = (int) (Math.random() * kartenAnzahl);
>     
int b = (int) (Math.random() * kartenAnzahl);
>  
   tausche (a, b);
>    } 
// end of for
>  
 } 
>   
>   
int kNr;
>   
>   
public void anDenAnfang()
>   {
>    kNr = 
0;
>   }
>   
>   
public boolean esGibtNächste()
>   {
>    
return (kNr < kartenAnzahl);
>   }
>   
>   
public RS_Karte nächsteKarte()
>   {
>    
if (kNr < kartenAnzahl)
>    {
>     kNr++;
>     
return (reihe[kNr-1]); 
>    } 
>    
else
>  
  {
>     
return (null);
>    }
>   }
>   
>   
public String kontrolle ()
>   {
>    
int i=0;
>    String ausgabe = 
"Blatt:\n";
>    anDenAnfang();
>    
while (esGibtNächste())
>    { 
>     ausgabe = ausgabe + i+
".) "+nächsteKarte().karteAlsText()+"\n";
>     i++;
>    } 
// end of while
>  
  return (ausgabe);
>   }
>  }   


zum Inhaltsverzeichnis (oben) / zum Seitenende

Spieler

Nach der folgenden Definition werden die beiden Spieler erzeugt. Der Kartenpacken, den jeder Spieler hat, wird hier als hand bezeichnet. Die Methode  anfangsKartenAufnehmen  hätte etwas einfacher programmiert werden können, wie vorstehend schon beim Blatt beschrieben.


>  // Teil des Kartenspiel-Projekts "Rot & Schwarz"
>  // R. Krell (www.r-krell.de) 4.6.2013
>  
>  // Jeder der beiden beteiligten Spieler hat einen Namen und hält Karten auf der Hand.
>  // Weil streng von oben runter bedient werden muss und gewonnenen Karten hinten dran kommen,
>  // ist hand eine Schlange von Karten.
>  // Der Spieler muss eine Karte auf den Tisch legen können (spieltAuf),
>  // Karten einzeln vom Tisch nehmen können, anfangs entweder alle roten oder alle
>  // schwarzen Karten erhalten, seine aktuelle Kartenzahl angeben können und merken/angeben, 
>  // ob er verloren hat.
>  
>  
>  
public class RS_Spieler 
>  {
>  
>   
// Anfang Attribute
>  
 String name;
>   
private RS_Schlange<RS_Karte> hand = new RS_Schlange<RS_Karte>();
>   
// Ende Attribute
>  
 
>   
// Anfang Methoden
>  
 
>   
public boolean hatVerloren() // wer keine Karten mehr hat, hat verloren!
>  
 {
>    
return (hand.istLeer());
>   }
>   
>   
public RS_Karte spieltAuf()  // oberste Karte auf den Tisch legen
>  
 {
>    
return (hand.raus());
>   }
>   
>   
public void nimmtVomTisch (RS_Karte karte) // eine Karte vom Tisch nehmen und hinten dran
>  
  // Wird nach einem Stich mehrfach aus RS_Spiel aufgerufen (bis alle Karten vom Tisch sind)
>  
 {
>    hand.rein (karte);
>   }
>   
>   
public void anfangsKartenAufnehmen(RS_Blatt blatt, String farben) 
>    
// ein Spieler bekommt anfangs entweder alle roten (farben=rot für Herz und Karo)
>  
  // oder alle schwarzen Karten (farben=schwarz für Kreuz und Pik).
>  
  // Die Karten werden aus dem blatt (Typ RS_Blatt) bezogen (wo sie erzeugt und gemischt wurden)
>  
 {              
>    RS_Karte karte;
>    blatt.anDenAnfang();
>    
while (blatt.esGibtNächste())
>    { 
>     karte = blatt.nächsteKarte();
>     
if ((farben.equalsIgnoreCase("rot") && (karte.istRot())) 
>     || (farben.equalsIgnoreCase(
"schwarz") && (!karte.istRot())))
>     {
>      hand.rein(karte);
>     } 
// end of if   
>  
  } // end of while   
>   }
>   
>   
public int kartenZahl()    // gibt an, wie viele Karten der Spieler (noch) hat
>  
 {
>    
return (hand.nenneAnzahl());
>   }
>   
>   
public String kontrolle()  // um während der Entwicklung die Karten auf der Hand 
>  
 {                          // des Spielers kontrollieren zu können
>  
  return (name+" "+ hand.kontrolle());
>   }
>   
>   
// Ende Methoden
>  
}



zum Inhaltsverzeichnis (oben) / zum Seitenende


zurück zur Seite „Informatik mit Java, SWE-2: Softwareengineering und Projektarbeit"




zum Anfang dieser Seite
Willkommen/Übersicht   -   Was ist neu?   -   Software   -   Mathematik   -   Physik   -   Informatik   -   Schule: Lessing-Gymnasium und -Berufskolleg   -   Fotovoltaik   -   & mehr   -   Kontakt: e-Mail,  News-Abo, Gästebuch, Impressum   -   Grußkarten, site map, Download und Suche

Diese Seite ist Teil des Webangebots http://www.r-krell.de. Sie können diese Seite per e-Mail weiter empfehlen (tell a friend).