
El papel de la pantalla
La pantalla web no termina en dibujar el tablero. Tiene que reducir las pulsaciones por error, impedir jugadas duplicadas mientras se espera la respuesta del servidor y volver a cargar las partidas guardadas. Sobre todo en un teléfono pequeño, es más seguro no confirmar una piedra con un solo toque.
Paso 1: Crear la jugada en dos pasos
Al tocar por primera vez una intersección vacía, solo se muestra una piedra provisional dorada. La jugada se envía al servidor cuando se vuelve a tocar el mismo punto o se pulsa el botón "Jugar". Si se toca otro punto, solo cambia la posición provisional. Hasta que responde el servidor, el botón y la entrada en el tablero se bloquean un momento para que la misma jugada no se guarde dos veces.
Paso 2: Hacer del servidor la fuente original del estado de la partida
Cuando el servidor recibe una jugada, comprueba el código de partida y la clave de acceso y verifica que sea el turno de ese jugador. Solo las jugadas que superan el motor de reglas se guardan en una transacción, y después se ejecuta el turno de la IA. No hay que fiarse del tablero que tiene el navegador: aplicar la nueva jugada al último estado del servidor evita las manipulaciones y los conflictos con pantallas desactualizadas.
- Validar y guardar la jugada del humano.
- Pedir a la IA la siguiente jugada con el último tablero guardado.
- Comprobar la jugada de la IA con el motor de reglas.
- Guardar la jugada de la IA y el resultado de las capturas.
- Devolver a la pantalla el último estado completo.
Paso 3: Separar la revisión de la partida del continuar
Pulsar las flechas de atrás y adelante durante la revisión no debe cambiar el último estado de la partida real. Solo cuando se elige "Continuar desde aquí" mientras se ve una jugada pasada se crea una nueva variante copiada hasta ese punto. Si se cortara de inmediato la secuencia existente, el usuario podría perder por error la partida original.
Paso 4: Mostrar con honestidad el final y el recuento
Cuando ambos jugadores pasan seguidos o el usuario pide el recuento, se pueden calcular el territorio vacío, las piedras capturadas y el komi de blancas. Pero si no se puede juzgar por completo la vida y muerte de las piedras muertas del tablero, el resultado debe indicarse como "recuento de referencia". Explicar qué se ha contado es más útil para el usuario que ocultar los límites del cálculo automático.
Lista de comprobación antes de publicar
- ¿Se recupera la partida en curso tras una recarga?
- ¿Se evita que una jugada se guarde dos veces en una red lenta?
- ¿Es imposible abrir la partida de otra persona con una clave de acceso distinta?
- ¿La partida original no cambia mientras se ven jugadas pasadas?
- ¿El tablero y la secuencia de jugadas siguen coincidiendo cuando ocurre un error?
Al conectar todo hasta aquí se obtiene la primera versión completa. A partir de ahí, los fallos encontrados en los registros de partidas reales, como escaleras, bocas de tigre o pases prematuros, se pueden evaluar y corregir de un tipo en uno.
El código real de este paso
La pantalla de revisión construye el tablero reproduciendo la secuencia guardada desde el principio hasta la jugada indicada. La secuencia original no se toca, así que avanzar y retroceder no cambia el último estado de la partida real.
mariago-web/lib/board.ts
export type ReplayState = {
board: Stone[];
ko: Point | null;
lastMove: Point | null;
capB: number;
capW: number;
passStreak: number;
toPlay: Stone;
};
/** 기보 0..upto 수까지 재현 (upto=0 이면 빈 판). */
export function replayMoves(
moves: Array<{ color: 1 | 2; pass?: boolean; r?: number; c?: number }>,
upto: number,
): ReplayState {
let board = emptyBoard();
let ko: Point | null = null;
let lastMove: Point | null = null;
let capB = 0;
let capW = 0;
let passStreak = 0;
let toPlay: Stone = BLACK;
const n = Math.max(0, Math.min(upto, moves.length));
for (let i = 0; i < n; i++) {
const m = moves[i];
const who = m.color as Stone;
if (m.pass) {
passStreak += 1;
lastMove = null;
} else if (m.r != null && m.c != null) {
const res = tryPlay(board, m.r, m.c, who, ko);
if (res.ok) {
board = res.board;
ko = res.koPoint;
lastMove = { r: m.r, c: m.c };
if (who === BLACK) capB += res.captured;
else capW += res.captured;
passStreak = 0;
}
}
toPlay = who === BLACK ? WHITE : BLACK;
}
return { board, ko, lastMove, capB, capW, passStreak, toPlay };
}Modelo utilizado: Qwen3-VL-8B-Instruct + adaptador LoRA (lora_mix_qwen_r5). El código fuente completo y la descripción del modelo están en la entrada "8. El código fuente completo y los modelos utilizados".
COMMENTS · CHAPTER 06
Conectar la partida web con el guardado de partidas 0 comentarios
Todavía no hay comentarios. Deja una pregunta o algo que quieras añadir.
Para publicar un comentario, empieza con Google y registra un apodo y un correo.
Empezar con Google