Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

Blackjack Game


Blackjack ist das meistgespielte Karten-Glücksspiel, das in Spielcasinos angeboten wird. Verwendet werden ein oder mehrer vollständige Sätze von Bridgekarte (je 52 Karten) verwendet Die Karten haben folgende Werte:

  • Ein Ass zählt nach Belieben ein oder elf Punkte
  • Zweier bis Zehner zählen entsprechend ihren Augen
  • Bildkarten (Buben, Damen, Könige) zählen zehn Punkte

Die Spielregeln können leicht von einander abweichen. Wir verwenden folgende Regeln: Der Kartengeber verteilt zu Beginn zwei Karten an den Spieler. Auch er bekommt zwei Karten, wobei die eine verdeckt bleibt und die andere aufgedeckt wird.

Der Spieler kann solange weitere Karten verlangen (er sagt "ziehen" oder "Karte" oder "noch eine" oder "Hit"), bis er glaubt, nahe genug an 21 Punkte herangekommen zu sein und keine weitere Karte mehr wünscht (er sagt "ich halte" oder "stand" oder "stay"). Wenn er aber den Wert 21 überschreitet, hat er verloren ("busted").

 

Nachdem der Spieler keine Karte mehr wünscht, nimmt der Geber so lange Karten auf, bis er mindestens 17 Punkte hat. Übersteigt dabei sein Kartenwert 21, hat er verloren. Anderfalls werden die Karten aufgedeckt und die Kartenpunkte werden verglichen. Ist der Spieler näher bei 21, so gewinnt er. Haben beide gleich viel Kartenpunkte, so gewinnt der Kartengeber.

Im Beispiel 1 wird eine einfache Variante mit nur einem Spieler implementiert. Im echten Blackjack wird um Einsätze gespielt, die wir vorerst weglassen. In der Regel spielen mehrere Spieler mit, wobei jeder Spieler nur gegen den Kartengebenr spielt.

Programmcode downloaden (BlackJack1.zip) 

Programmcode:

// BlackJack1.java

import ch.aplu.jcardgame.*;
import ch.aplu.jgamegrid.*;
import ch.aplu.util.Monitor;

public class BlackJack1 extends CardGame
{
  public enum Suit
  {
    SPADES, HEARTS, DIAMONDS, CLUBS
  }

  public enum Rank
  {
    ACE, KING, QUEEN, JACK, TEN, NINE, EIGHT, SEVEN, SIX, FIVE, FOUR, THREE, TWO
  }
  // ------------------------ Locations -----------------
  private Location upperLocation = new Location(300, 120);
  private Location bottomLocation = new Location(300, 470);
  private Location middleLocation = new Location(300, 300);
  private Location hideLocation = new Location(-500-500);
  private Location buttonLocation = new Location(300, 575);
  private Location gameOverLocation = new Location(300, 300);
  // ----------------------------------------------------

  private Deck deck = new Deck(Suit.values(), Rank.values(), "cover");
  private Hand dealer = new Hand(deck);
  private Hand player = new Hand(deck);
  private Actor gameOverActor = new Actor("sprites/gameover.gif");
  private GGButton standButton = new GGButton("sprites/standBtn.gif");
  private GGButton restartButton = new GGButton("sprites/restartBtn.gif");
  private Hand talon;

  public BlackJack1()
  {
    super(600, 600, 30);
    setTitle("BlackJack - Extended Version");
    setStatusText("Dealing out. Please wait...");
    initButtons();
    while (true)
    {
      init();
      Monitor.putSleep();
    }
  }

  private void showHands()
  {
    RowLayout rowLayout = new RowLayout(bottomLocation, 350);
    player.setView(thisrowLayout);
    player.draw();
    RowLayout rowLayout1 = new RowLayout(upperLocation, 350);
    dealer.setView(thisrowLayout1);
    dealer.draw();
    talon.setVerso(true);
    talon.setView(thisnew StackLayout(middleLocation));
    talon.draw();
  }

  private void init()
  {
    talon = deck.dealingOut(0, 0, false)[0];
    showHands();

    Card card = talon.getLast();
    talon.transfer(card, player, true);
    card.setVerso(false);
    card = talon.getLast();
    card.setVerso(true);
    talon.transfer(card, dealer, true);
    card = talon.getLast();
    talon.transfer(card, player, true);
    card.setVerso(false);
    card = talon.getLast();
    talon.transfer(card, dealer, true);
    card.setVerso(false);

    CardAdapter cardAdapter = new CardAdapter()
    {
      public void leftDoubleClicked(Card card)
      {
        card.transfer(player, true);
        card.setVerso(false);
        int value = getHandValue(player);
        setStatusText(value);
        if (value > 21)
        {
          gameOver("You bust! Your card values " + value
            + " exceed 21  ---  Please click to restart.");
        }
      }
    };

    talon.addCardListener(cardAdapter);
    setStatusText(getHandValue(player));
    standButton.setLocation(buttonLocation);
    talon.setTouchEnabled(true);
    setStatusText(getHandValue(player));
  }

  private void initButtons()
  {
    restartButton.addButtonListener(new GGButtonAdapter()
    {
      public void buttonClicked(GGButton button)
      {
        restartButton.setLocation(hideLocation);
        cleanUp();
        Monitor.wakeUp();
      }

      public void buttonReleased(GGButton button)
      {
        
      }

      public void buttonPressed(GGButton button)
      {
        
      }
    });
    addActor(restartButton, hideLocation);
    restartButton.setRefreshEnabled(false);

    standButton.addButtonListener(new GGButtonAdapter()
    {
      public void buttonClicked(GGButton button)
      {
        standButton.setLocation(hideLocation);
        dealersTurn();
        evaluateRound();
      }
    });
    addActor(standButton, hideLocation);
    standButton.setRefreshEnabled(false);
  }

  private void cleanUp()
  {
    gameOverActor.removeSelf();
    talon.removeAll(false);
    player.removeAll(false);
    dealer.removeAll(false);
  }

  private void evaluateRound()
  {
    int dealerValue = getHandValue(dealer);
    int playerValue = getHandValue(player);
    String score = playerValue + " (you) versus "
      + dealerValue + " (dealer)  ---  Please click to restart.";

    if (dealerValue > 21)
      gameOver("Dealer bust! His card values " + dealerValue
        + " exceed 21  ---  Please click to restart.");
    else
    {
      if (playerValue > dealerValue)
        gameOver("You won! " + score);
      if (playerValue == dealerValue)
        gameOver("Tie! " + score);
      else
        gameOver("You lost! " + score);
    }
  }

  private void gameOver(String reason)
  {
    dealer.setVerso(false);
    setStatusText(reason);
    talon.setTouchEnabled(false);
    addActor(gameOverActor, gameOverLocation);
    standButton.setLocation(hideLocation);
    restartButton.setLocation(buttonLocation);
  }

  private void dealersTurn()
  {
    talon.setTargetArea(new TargetArea(dealer.getHandLocation()));
    while (getHandValue(dealer) < 17)
    {
      Card newCard = talon.getLast();
      newCard.transfer(dealer, true);
      newCard.setVerso(false);
    }
  }

  private int getHandValue(Hand hand)
  {
    int value = 0;
    for (Card card : hand.getCardList())
    {
      switch ((Rank)card.getRank())
      {
        case TWO:
          value += 2;
          break;
        case THREE:
          value += 3;
          break;
        case FOUR:
          value += 4;
          break;
        case FIVE:
          value += 5;
          break;
        case SIX:
          value += 6;
          break;
        case SEVEN:
          value += 7;
          break;
        case EIGHT:
          value += 8;
          break;
        case NINE:
          value += 9;
          break;
        case TEN:
          value += 10;
          break;
        case JACK:
          value += 10;
          break;
        case QUEEN:
          value += 10;
          break;
        case KING:
          value += 10;
          break;
        case ACE:
          if (value + 11 > 21)
            value += 1;
          else
            value += 11;
          break;
      }
    }
    return value;
  }

  private void setStatusText(int value)
  {
      setStatusText(value + " points in your hand.    "
        + "Double-click card talon to Hit or press Stand.");
  }


  public static void main(String[] args)
  {
    new BlackJack1();
  }
}


Erklärungen zum Programmcode:
initButtons()
Die Buttons Stand und Restart werden erzeugt, zum Spielfenster hinzugefügt, aber nicht angezeigt. Der Button Stand wird erst angezeigt, nachdem der Spieler die ersten zwei Karten erhalten hat. Mit dem Button Restart kann nach Spielende ein neues Spiel gestarten werden
while (true)
{
   init();
   Monitor.putSleep();
}
Nachdem die Methode init() ausgeführt wurde, welche die Kartenhände initialiert und das Austeilen der ersten Karten bewirkt, halten wir mit putSleep() der Applikationsthread an. Das weitere Programm läuft über Callbacks. Wenn das Spiel fertig ist und Restart-Button gedrückt wird, wecken wir den Tread mit wakeUp() wieder auf und das Spiel erneut initialisiert
cleanUp()
Vor der erneueten Initialisierung müssen alle Resourcen aufgeräumt werden
getHandValue() Die totale Punktezahl in einer Hand wird auf Grund der Kartenwerte bestimmt. Falls die 11 Punkte für ein Ass zu einem Bust führen, wird dass Ass nur mit einem Punkt bewertet
evaluateRound() Auf Grund der Kartenwerte des Kartengebers und des Spielers wird ermittelt, wer gewinnt

 

Beispiel 2: Blackjack-Game mit Einsätzen

Der Spieler startet mit 100 Jetons. Nach dem die ersten zwei Karten verteilt wurden, muss der Spieler den Einsatz festlegen und auf ok klicken.Falls er gewinnt, wird dieser Einsatzt aufaddiert, anderfalls abgezogen.

Programmcode downloaden (BlackJack.zip) 

 

 

Programmcode:

// BlackJack.java

import ch.aplu.jcardgame.*;
import ch.aplu.jgamegrid.*;
import ch.aplu.util.Monitor;
import java.awt.*;

public class BlackJack extends CardGame
{
  public enum Suit
  {
    SPADES, HEARTS, DIAMONDS, CLUBS
  }

  public enum Rank
  {
    ACE, KING, QUEEN, JACK, TEN, NINE, EIGHT, SEVEN, SIX, FIVE, FOUR, THREE, TWO
  }
  // ------------------------ Locations -----------------
  private Location upperLocation = new Location(300, 110);
  private Location bottomLocation = new Location(300, 450);
  private Location middleLocation = new Location(300, 280);
  private Location hideLocation = new Location(-500-500);
  private Location buttonLocation = new Location(300, 560);
  private Location toolBarLocation = new Location(50, 450);
  private Location betLocation = new Location(480, 470);
  private Location fundLocation = new Location(480, 450);
  private Location gameOverLocation = new Location(300, 300);
  // ----------------------------------------------------
  private final int START_MONEY = 100;
  private Deck deck = new Deck(Suit.values(), Rank.values(), "cover");
  private Hand dealer = new Hand(deck);
  private Hand player = new Hand(deck);
  private Actor gameOverActor = new Actor("sprites/gameover.gif");
  private GGButton standButton = new GGButton("sprites/standBtn.gif");
  private GGButton restartButton = new GGButton("sprites/restartBtn.gif");
  private Hand talon;
  private int currentBet = 0;
  private int funds = START_MONEY;
  private TextActor currentBets = null;
  private TextActor currentFunds = null;
  private ToolBar toolBar = new ToolBar(this);

  //TODO: Implement "BlackJack_mar30": Ace + 10 is best way to get 21 points
  //TODO: hide toolBar after setting bet.
  //TODO: Fatal Error, why?
  //TODO: rightclick for counting downwards?
  public BlackJack()
  {
    super(600, 600, 30);
    setTitle("BlackJack - Extended Version");
    setStatusText("Dealing out. Please wait...");
    showBet();
    initButtons();
    initToolBar();
    while (true)
    {
      init();
      Monitor.putSleep();
    }
  }

  private void showHands()
  {
    RowLayout rowLayout = new RowLayout(bottomLocation, 350);
    player.setView(thisrowLayout);
    player.draw();
    RowLayout rowLayout1 = new RowLayout(upperLocation, 350);
    dealer.setView(thisrowLayout1);
    dealer.draw();
    talon.setVerso(true);
    talon.setView(thisnew StackLayout(middleLocation));
    talon.draw();
  }

  private void init()
  {
    talon = deck.dealingOut(0, 0)[0];
    showHands();

    Card card = talon.getLast();
    talon.transfer(card, player, true);
    card.setVerso(false);
    card = talon.getLast();
    card.setVerso(true);
    talon.transfer(card, dealer, true);
    card = talon.getLast();
    talon.transfer(card, player, true);
    card.setVerso(false);
    card = talon.getLast();
    talon.transfer(card, dealer, true);
    card.setVerso(false);

    CardAdapter cardAdapter = new CardAdapter()
    {
      public void leftDoubleClicked(Card card)
      {
        card.transfer(player, true);
        card.setVerso(false);
        int value = getHandValue(player);
        setStatusText(value);
        if (value > 21)
        {
          gameOver("You bust! Your card values " + value
            + " exceed 21  ---  Please click to restart."-currentBet);
        }
      }
    };

    talon.addCardListener(cardAdapter);
    setStatusText(getHandValue(player));
    toolBar.setLocation(toolBarLocation);
  }

  private void initButtons()
  {
    restartButton.addButtonListener(new GGButtonAdapter()
    {
      public void buttonClicked(GGButton button)
      {
        restartButton.setLocation(hideLocation);
        cleanUp();
        Monitor.wakeUp();
      }

      public void buttonReleased(GGButton button)
      {

      }

      public void buttonPressed(GGButton button)
      {
 
      }

  });
    addActor(restartButton, hideLocation);
    restartButton.setRefreshEnabled(false);


    standButton.addButtonListener(new GGButtonAdapter()
    {
      public void buttonClicked(GGButton button)
      {
        standButton.setLocation(hideLocation);
        dealersTurn();
        evaluateRound();
      }
    });
    addActor(standButton, hideLocation);
    standButton.setRefreshEnabled(false);
  }

  private void cleanUp()
  {
    gameOverActor.removeSelf();
    talon.removeAll(false);
    player.removeAll(false);
    dealer.removeAll(false);
  }

  private void evaluateRound()
  {
    int dealerValue = getHandValue(dealer);
    int playerValue = getHandValue(player);
    String score = playerValue + " (you) versus "
      + dealerValue + " (dealer)  ---  Please click to restart.";

    if (dealerValue > 21)
      gameOver("Dealer bust! His card values " + dealerValue
        + " exceed 21  ---  Please click to restart."currentBet);
    else
    {
      if (playerValue > dealerValue)
        gameOver("You won! " + score, currentBet);
      else
        gameOver("You lost! " + score, -currentBet);
    }
  }

  private void gameOver(String reason, int amount)
  {
    funds += amount;
    setStatusText(reason);
    talon.setTouchEnabled(false);
    addActor(gameOverActor, gameOverLocation);
    dealer.setVerso(false);
    standButton.setLocation(hideLocation);
    restartButton.setLocation(buttonLocation);
    currentBet = 0;
    showBet();
  }

  private void dealersTurn()
  {
    talon.setTargetArea(new TargetArea(dealer.getHandLocation()));
    while (getHandValue(dealer) < 17)
    {
      Card newCard = talon.getLast();
      newCard.transfer(dealer, true);
      newCard.setVerso(false);
    }
  }

  private int getHandValue(Hand hand)
  {
    int value = 0;
    for (Card card : hand.getCardList())
    {
      switch ((Rank)card.getRank())
      {
        case TWO:
          value += 2;
          break;
        case THREE:
          value += 3;
          break;
        case FOUR:
          value += 4;
          break;
        case FIVE:
          value += 5;
          break;
        case SIX:
          value += 6;
          break;
        case SEVEN:
          value += 7;
          break;
        case EIGHT:
          value += 8;
          break;
        case NINE:
          value += 9;
          break;
        case TEN:
          value += 10;
          break;
        case JACK:
          value += 10;
          break;
        case QUEEN:
          value += 10;
          break;
        case KING:
          value += 10;
          break;
        case ACE:
          if (value + 11 > 21)
            value += 1;
          else
            value += 11;
          break;
      }
    }
    return value;
  }

  private void setStatusText(int value)
  {
    if (currentBet == 0)
      setStatusText(value + " points in your hand.    "
        + "Place a bet.");
    else
      setStatusText(value + " points in your hand.    "
        + "Double-click card talon to Hit or press Stand.");
  }

  private void showBet()
  {
    if (currentBets != null)
      currentBets.removeSelf();
    if (currentFunds != null)
      currentFunds.removeSelf();

    currentBets = new TextActor("Bet: " + currentBet, Color.white, getBgColor(),
      new Font("Arial", Font.BOLD, 16));
    addActor(currentBets, currentBet != 0 ? betLocation : hideLocation);
    currentFunds = new TextActor("Funds: " + funds, Color.white, getBgColor(),
      new Font("Arial", Font.BOLD, 16));
    addActor(currentFunds, fundLocation);
  }

  private void initToolBar()
  {
    final ToolBarStack number1 =
      new ToolBarStack("sprites/number30.gif"10);
    final ToolBarStack number10 =
      new ToolBarStack("sprites/number30.gif"10);
    ToolBarSeparator separator =
      new ToolBarSeparator(2, 30, Color.black);
    final ToolBarItem okBtn =
      new ToolBarItem("sprites/okBtn30.gif"2);
    toolBar.addItem(number10, number1, separator, okBtn);
    toolBar.show(hideLocation);

    toolBar.addToolBarListener(new ToolBarAdapter()
    {
      public void leftPressed(ToolBarItem item)
      {
        if (item == okBtn)
        {
          okBtn.show(1);
          int bet = number10.getItemId() * 10 + number1.getItemId();
          System.out.println("ok "+ bet);
          if (bet != 0)
          {
            currentBet = bet;
            talon.setTouchEnabled(true);
            standButton.setLocation(buttonLocation);
            setStatusText(getHandValue(player));
            showBet();
          }
        }
        else
          ((ToolBarStack)item).showNext();
      }

      public void leftReleased(ToolBarItem item)
      {
        if (item == okBtn)
        {
          item.show(0);
          int bet = number10.getItemId() * 10 + number1.getItemId();
          if (bet != 0)
            toolBar.setLocation(hideLocation);
        }
      }
    });
  }

  public static void main(String[] args)
  {
    new BlackJack();
  }
}


Erklärungen zum Programmcode: