Implémenter la stratégie de base du blackjack en JavaScript

Un guide complet pour développeurs : représenter la stratégie de base en JSON et effectuer des recherches ultra-rapides dans le code.

Apprendre la stratégie de base — entraîneur interactif

Pourquoi la stratégie de base a sa place dans le code

La stratégie de base est une table de décision déterministe qui ramène l'avantage de la maison à seulement 0,5 %. Si vous développez un simulateur, un entraîneur ou un croupier assisté par IA, encoder cette table sous forme de données structurées (JSON) et utiliser une fonction de recherche rapide est bien plus simple et plus facile à maintenir que des centaines de conditions imbriquées.

Cette approche sépare les données de la logique : votre code devient plus lisible, plus facile à tester et à adapter à différentes variantes de règles. Que vous construisiez un jeu de casino, une application d'entraînement ou un outil d'analyse statistique, ce modèle vous fera gagner du temps et limitera les bugs.

Modèle de données : une table de correspondance JSON

Stockez le tableau de stratégie dans un objet JSON. Chaque clé représente la ligne de la main du joueur (totaux durs, totaux souples et paires), et chaque valeur associe la carte visible du croupier au code de l'action :

Table de stratégie JSON
// 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"}
};

Cet extrait suit le tableau de stratégie de base pour : 6 jeux, le croupier tire sur 17 souple, double sur deux cartes quelconques, double après séparation autorisé, abandon tardif.

H
Tirer
S
Rester
D
Doubler (sinon tirer)
P
Séparer
SR
Abandonner (sinon tirer)
SP
Abandonner (sinon séparer)
D/S
Doubler, sinon rester

La fonction de recherche : simple et rapide

Utilisez une petite fonction pour trouver le coup recommandé à partir de la clé de la table et de la carte visible du croupier. Elle renvoie directement le code de l'action, avec une complexité en O(1).

Fonction de recherche JavaScript
// fonction de recherche
function getBlackjackAction(playerHand, dealerCard, strategyTable) {
  if (!strategyTable) strategyTable = blackjackStrategy; // repli sur la table globale si aucune n'est passée
  playerHand  = String(playerHand).toUpperCase();
  dealerCard  = String(dealerCard).toUpperCase();

  const row = strategyTable[playerHand];
  if (!row) return null; // ligne inconnue
  return row[dealerCard] || null; // action, ou null si la carte du croupier est inconnue
}

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

Cette approche sépare la stratégie de la logique : le JSON contient les données, la fonction sert de recherche et d'adaptateur. Pour passer à une autre variante de règles (par ex. le croupier tire ou reste sur 17 souple, ou d'autres règles d'abandon), il suffit de charger un autre objet JSON.

Recherches instantanées

Une complexité en O(1) garantit des performances constantes, même avec des variantes de règles complexes.

Maintenance facile

Modifiez les règles de stratégie en changeant les données JSON, pas une logique conditionnelle complexe.

Une conception évolutive

Idéal pour des simulations qui jouent des milliers de mains par seconde.

Accepter de vraies cartes en entrée

En production, vous voudrez peut-être que la fonction accepte des cartes brutes (par ex. ['A','6']) au lieu de clés de ligne précalculées. Écrivez un petit normaliseur qui :

  • détecte les paires (deux rangs identiques) → ligne du type "8-8"
  • détecte les totaux souples (un As compté pour 11) → ligne du type "A6"
  • se rabat sinon sur les totaux durs (somme numérique) → ligne du type "16"
Fonction de normalisation de la main
// exemple de normaliseur (très simple)
function normalizeHand(cards) {
  // cards : tableau de rangs, par ex. ['A','6'] ou ['9','9'] ou ['10','6']
  const ranks = cards.map(c => String(c).toUpperCase());
  if (ranks.length === 2 && ranks[0] === ranks[1]) {
    // paire
    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);
  // détection naïve des mains souples à deux cartes
  if (hasAce && ranks.length === 2) {
    const other = ranks.find(r => r !== 'A');
    return `A${other}`;
  }
  return String(numeric);
}

Combinez le normaliseur avec getBlackjackAction pour accepter soit des clés structurées, soit des tableaux de cartes brutes. Votre API devient ainsi plus souple et plus pratique à utiliser.

Pourquoi les développeurs devraient adopter ce modèle

Clarté

Une approche pilotée par les données garde la logique lisible et facile à maintenir. Fini le code spaghetti truffé de if imbriqués.

Performance

Une recherche en temps constant, adaptée aux simulations qui jouent des milliers de mains par minute.

Flexibilité

Changez de table pour une autre variante de règles ou ajoutez des modes d'entraînement sans toucher au cœur de votre logique.

Testabilité

Facile à tester unitairement avec différentes tables de stratégie et différents cas limites.

Modularité

Les données de stratégie peuvent être chargées indépendamment depuis des fichiers, des API ou des bases de données.

Internationalisation

Prenez en charge les variantes régionales du blackjack avec des fichiers JSON distincts.

Ressources et prochaines étapes

Prêt à mettre tout cela en pratique ? Essayez notre entraîneur interactif pour voir la stratégie de base en action :

21Count — Entraîneur interactif de stratégie de base

Télécharger le fichier JavaScript complet avec exemples

Comprend la table de stratégie complète, les fonctions de recherche, le normaliseur et des exemples d'utilisation prêts pour vos projets.