Cómo implementar la estrategia básica del blackjack en JavaScript
Una guía completa para desarrolladores sobre cómo representar la estrategia básica en JSON y hacer consultas ultrarrápidas desde el código.
Por qué la estrategia básica encaja en el código
La estrategia básica es una tabla de decisiones determinista que reduce la ventaja de la casa a solo un 0,5 %. Si desarrollas un simulador, un entrenador o un crupier asistido por IA, codificar esa tabla como datos estructurados (JSON) y usar una función de consulta rápida es mucho más sencillo y fácil de mantener que cientos de condicionales anidados.
Este enfoque separa los datos de la lógica, con lo que tu código es más legible, más fácil de probar y se adapta mejor a distintas variantes de reglas. Tanto si creas un juego de casino como una aplicación de entrenamiento o un analizador estadístico, este patrón te ahorrará tiempo y errores.
Modelo de datos: tabla de consulta en JSON
Guarda la tabla de estrategia como un objeto JSON. Cada clave representa la fila de la mano del jugador (totales duros, totales blandos y parejas), y cada valor es un mapa de la carta visible del crupier al código de acción:
// 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"}
};
El extracto sigue la tabla de estrategia básica para estas reglas: 6 barajas, el crupier pide con 17 blando, doblar con dos cartas cualesquiera, doblar tras dividir permitido, rendición tardía.
- H
- Pedir
- S
- Plantarse
- D
- Doblar (si no, pedir)
- P
- Dividir
- SR
- Rendirse (si no, pedir)
- SP
- Rendirse (si no, dividir)
- D/S
- Doblar; si no, plantarse
Función de consulta: sencilla y rápida
Usa una pequeña función para obtener la jugada recomendada a partir de la clave de la tabla y la carta visible del crupier. Devuelve directamente el código de acción y tiene complejidad O(1).
// función de consulta
function getBlackjackAction(playerHand, dealerCard, strategyTable) {
if (!strategyTable) strategyTable = blackjackStrategy; // usa la tabla global si no se pasa ninguna
playerHand = String(playerHand).toUpperCase();
dealerCard = String(dealerCard).toUpperCase();
const row = strategyTable[playerHand];
if (!row) return null; // fila desconocida
return row[dealerCard] || null; // acción, o null si la carta del crupier es desconocida
}
// ejemplos
console.log(getBlackjackAction("A7", "6")); // "D/S"
console.log(getBlackjackAction("16", "10")); // "SR"
console.log(getBlackjackAction("9-9", "7")); // "S"
Así la estrategia y la lógica quedan separadas: el JSON son los datos y la función es la consulta/adaptador. Es fácil cambiar a otras variantes de reglas (por ejemplo, que el crupier pida o se plante con 17 blando, u otras reglas de rendición) cargando otro objeto JSON.
Consultas instantáneas
La complejidad O(1) garantiza un rendimiento constante incluso con variantes de reglas complejas.
Mantenimiento sencillo
Actualiza las reglas de estrategia modificando datos JSON, no una lógica condicional complicada.
Diseño escalable
Perfecto para simulaciones que juegan miles de manos por segundo.
Ampliación para cartas reales
En producción quizá quieras que la función acepte cartas tal cual (p. ej. ['A','6']) en lugar de claves de fila ya calculadas.
Implementa un pequeño normalizador que:
- detecte parejas (los dos valores iguales) → fila como
"8-8" - detecte totales blandos (con un As que cuenta como 11) → fila como
"A6" - recurra a los totales duros (suma numérica) → fila como
"16"
// ejemplo de normalizador (muy pequeño)
function normalizeHand(cards) {
// cards: array de valores, p. ej. ['A','6'], ['9','9'] o ['10','6']
const ranks = cards.map(c => String(c).toUpperCase());
if (ranks.length === 2 && ranks[0] === ranks[1]) {
// pareja
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);
// detección sencilla de manos blandas de dos cartas
if (hasAce && ranks.length === 2) {
const other = ranks.find(r => r !== 'A');
return `A${other}`;
}
return String(numeric);
}
Combina el normalizador con getBlackjackAction para aceptar tanto claves estructuradas como arrays de cartas. Así tu API será más flexible y cómoda de usar.
Por qué los desarrolladores deberían usar este modelo
Claridad
El enfoque basado en datos mantiene la lógica legible y fácil de mantener. Se acabó el código espagueti con if anidados.
Rendimiento
Consultas en tiempo constante, aptas para simulaciones que juegan miles de manos por minuto.
Flexibilidad
Cambia de tabla para otras variantes de reglas o añade modos de entrenamiento sin tocar la lógica principal.
Facilidad de prueba
Fácil de cubrir con pruebas unitarias usando distintas tablas de estrategia y casos límite.
Modularidad
Los datos de estrategia pueden cargarse de forma independiente desde archivos, APIs o bases de datos.
Internacionalización
Admite distintas variantes regionales del blackjack con archivos JSON separados.
Recursos y próximos pasos
¿Listo para poner en práctica lo aprendido? Prueba nuestro entrenador interactivo y verás la estrategia básica en acción:
21Count: entrenador interactivo de estrategia básica
Descargar el archivo JavaScript completo con ejemplos
Incluye la tabla de estrategia completa, las funciones de consulta, el normalizador y ejemplos de uso listos para tus proyectos.