Blackjack-Basisstrategie in JavaScript umsetzen

Ein ausführlicher Guide für Entwickler: die Basisstrategie als JSON abbilden und im Code blitzschnell nachschlagen.

Basisstrategie lernen — interaktiver Trainer

Warum die Basisstrategie in den Code gehört

Die Basisstrategie ist eine deterministische Entscheidungstabelle, die den Hausvorteil auf nur 0,5 % senkt. Wenn du einen Simulator, einen Trainer oder einen KI-gestützten Dealer baust, ist es viel einfacher und besser wartbar, diese Tabelle als strukturierte Daten (JSON) abzulegen und mit einer schnellen Lookup-Funktion abzufragen, als Hunderte verschachtelter Bedingungen zu schreiben.

Dieser Ansatz trennt Daten von Logik. Dein Code wird dadurch lesbarer, besser testbar und lässt sich leichter an andere Regelvarianten anpassen. Ob Casinospiel, Trainings-App oder Statistiktool: Dieses Muster spart dir Zeit und vermeidet Bugs.

Datenmodell: JSON-Nachschlagetabelle

Speichere die Strategietabelle als JSON-Objekt. Jeder Schlüssel steht für die Zeile der Spielerhand (harte Summen, weiche Summen und Paare), jeder Wert ist eine Zuordnung von der offenen Dealerkarte zum Aktionscode:

JSON-Strategietabelle
// small excerpt (full table would include all rows)
const blackjackStrategy = {
  "5-8": {"2":"H","3":"H","4":"H","5":"H","6":"H","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "9": {"2":"H","3":"D","4":"D","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "10": {"2":"D","3":"D","4":"D","5":"D","6":"D","7":"D","8":"D","9":"D","10":"H","A":"H"},
  "11": {"2":"D","3":"D","4":"D","5":"D","6":"D","7":"D","8":"D","9":"D","10":"D","A":"D"},
  "12": {"2":"H","3":"H","4":"S","5":"S","6":"S","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "13": {"2":"S","3":"S","4":"S","5":"S","6":"S","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "14": {"2":"S","3":"S","4":"S","5":"S","6":"S","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "15": {"2":"S","3":"S","4":"S","5":"S","6":"S","7":"H","8":"H","9":"H","10":"SR","A":"SR"},
  "16": {"2":"S","3":"S","4":"S","5":"S","6":"S","7":"H","8":"H","9":"SR","10":"SR","A":"SR"},
  "A2": {"2":"H","3":"H","4":"H","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "A3": {"2":"H","3":"H","4":"H","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "A4": {"2":"H","3":"H","4":"D","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "A5": {"2":"H","3":"H","4":"D","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "A6": {"2":"H","3":"D","4":"D","5":"D","6":"D","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "A7": {"2":"D/S","3":"D/S","4":"D/S","5":"D/S","6":"D/S","7":"S","8":"S","9":"H","10":"H","A":"H"},
  "2-2": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"P","8":"H","9":"H","10":"H","A":"H"},
  "3-3": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"P","8":"H","9":"H","10":"H","A":"H"},
  "4-4": {"2":"H","3":"H","4":"H","5":"P","6":"P","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "6-6": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"H","8":"H","9":"H","10":"H","A":"H"},
  "7-7": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"P","8":"H","9":"H","10":"H","A":"H"},
  "8-8": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"P","8":"P","9":"P","10":"P","A":"SP"},
  "9-9": {"2":"P","3":"P","4":"P","5":"P","6":"P","7":"S","8":"P","9":"P","10":"S","A":"S"}
};

Der Auszug folgt der Basisstrategie-Tabelle für 6 Decks, Dealer zieht bei weicher 17, Verdoppeln auf beliebige zwei Karten, Verdoppeln nach dem Teilen erlaubt, spätes Aufgeben.

H
Karte
S
Halten
D
Verdoppeln (sonst Karte)
P
Teilen
SR
Aufgeben (sonst Karte)
SP
Aufgeben (sonst Teilen)
D/S
Verdoppeln, sonst Halten

Lookup-Funktion: einfach und schnell

Mit einer kleinen Funktion schlägst du den empfohlenen Zug über den Tabellenschlüssel und die offene Dealerkarte nach. Sie gibt direkt den Aktionscode zurück und hat die Komplexität O(1).

JavaScript-Lookup-Funktion
// Lookup-Funktion
function getBlackjackAction(playerHand, dealerCard, strategyTable) {
  if (!strategyTable) strategyTable = blackjackStrategy; // ohne Parameter auf die globale Tabelle zurückgreifen
  playerHand  = String(playerHand).toUpperCase();
  dealerCard  = String(dealerCard).toUpperCase();

  const row = strategyTable[playerHand];
  if (!row) return null; // unbekannte Zeile
  return row[dealerCard] || null; // Aktion oder null bei unbekannter Dealerkarte
}

// Beispiele
console.log(getBlackjackAction("A7", "6"));   // "D/S"
console.log(getBlackjackAction("16", "10"));  // "SR"
console.log(getBlackjackAction("9-9", "7"));  // "S"

So bleiben Strategie und Logik getrennt: Das JSON sind die Daten, die Funktion ist der Lookup bzw. Adapter. Regelvarianten (z. B. Dealer zieht/hält bei weicher 17 oder andere Regeln zum Aufgeben) tauschst du ganz einfach aus, indem du ein anderes JSON-Objekt lädst.

Sofortige Lookups

Komplexität O(1) bedeutet gleichbleibende Performance, auch bei komplizierten Regelvarianten.

Einfache Wartung

Du änderst Strategieregeln in den JSON-Daten statt in verschachtelter Bedingungslogik.

Skalierbares Design

Ideal für Simulationen, die Tausende Hände pro Sekunde durchspielen.

Erweiterung für echte Karten als Eingabe

Im Produktiveinsatz soll die Funktion vielleicht rohe Karten (z. B. ['A','6']) statt vorberechneter Zeilenschlüssel annehmen. Schreib dafür einen kleinen Normalisierer, der:

  • Paare erkennt (beide Ränge gleich) → Zeile wie "8-8"
  • weiche Summen erkennt (enthält ein Ass, das als 11 zählt) → Zeile wie "A6"
  • sonst auf harte Summen zurückfällt (Zahlensumme) → Zeile wie "16"
Funktion zum Normalisieren der Hand
// Beispiel für einen Normalisierer (sehr klein)
function normalizeHand(cards) {
  // cards: Array mit Rängen, z. B. ['A','6'] oder ['9','9'] oder ['10','6']
  const ranks = cards.map(c => String(c).toUpperCase());
  if (ranks.length === 2 && ranks[0] === ranks[1]) {
    // Paar
    return `${ranks[0]}-${ranks[1]}`;
  }
  const hasAce = ranks.includes('A');
  const numeric = ranks.reduce((sum, r) => sum + (r === 'A' ? 11 : (r === 'J' || r === 'Q' || r === 'K' ? 10 : parseInt(r,10) || 0)), 0);
  // einfache Erkennung weicher Hände bei zwei Karten
  if (hasAce && ranks.length === 2) {
    const other = ranks.find(r => r !== 'A');
    return `A${other}`;
  }
  return String(numeric);
}

Kombiniere den Normalisierer mit getBlackjackAction, damit sowohl strukturierte Schlüssel als auch rohe Karten-Arrays funktionieren. So wird deine API flexibler und angenehmer zu benutzen.

Warum Entwickler dieses Modell nutzen sollten

Klarheit

Der datengetriebene Ansatz hält die Logik lesbar und wartbar. Schluss mit Spaghetticode aus verschachtelten if-Anweisungen.

Performance

Lookup in konstanter Zeit, ideal für Simulationen mit Tausenden Händen pro Minute.

Flexibilität

Tausche Tabellen für Regelvarianten aus oder baue Trainingsmodi, ohne deine Kernlogik anzufassen.

Testbarkeit

Lässt sich mit verschiedenen Strategietabellen und Grenzfällen leicht per Unit-Test prüfen.

Modularität

Strategiedaten lassen sich unabhängig aus Dateien, APIs oder Datenbanken laden.

Internationalisierung

Unterstütze regionale Blackjack-Varianten mit separaten JSON-Dateien.

Ressourcen & nächste Schritte

Bereit, das Gelernte anzuwenden? Probier unseren interaktiven Trainer aus und sieh die Basisstrategie in Aktion:

21Count — interaktiver Basisstrategie-Trainer

Komplette JavaScript-Datei mit Beispielen herunterladen

Enthält die vollständige Strategietabelle, Lookup-Funktionen, den Normalisierer und Anwendungsbeispiele – bereit für deine Projekte.