A pesar que no voy a explicar paso por paso cómo se construyó esta aplicación, me he decidido a escribir este artículo por si a alguien le interesa conocer una posible implementación del juego del Ahorcado en Javascript. Además, nos servirá de práctica para las personas que están aprendiendo jQuery o el dibujo con el elemento Canvas.
Para empezar, dejo un enlace a la página del juego en funcionamiento, para que los interesados puedan ver el resultado final de esta práctica.
Framework Javascript jQuery:
Usamos jQuery para simplificar las cosas durante la programación en Javascript. Puedes aprender en el Manual de jQuery.
Librería jQuery UI:
Las librerías jQuery UI nos sirven para crear diversos componentes de interfaz de usuario avanzados, como botones o cajas de diálogo. Podría hacerse sin estas librerías, igual que también sin el propio jQuery, pero la verdad es que simplifican nuestra vida bastante y nos ayudan a realizar un juego más atractivo visualmente y facilitan una mejor experiencia de usuario. En DesarrolloWeb.com también puedes aprender jQuery UI.
Canvas del HTML 5:
Utilizamos el componente CANVAS para pintar cada una de las partes del cuerpo del ahorcado que se colocan según la persona que juega va cometiendo errores. La propia estructura de la ahorca también está pintada con el elemento Canvas del HTML 5. También podríamos hacer este juego sin utilizar el Canvas, colocando simples imágenes generadas con algún editor gráfico, pero justamente lo que deseamos es hacer una aplicación donde podamos practicar con el elemento Canvas. Puedes aprender sobre esto en el Manual de Canvas del HTML 5.
Aparte de todo esto, por supuesto, utilizamos el lenguaje Javascript, que se puede aprender en la sección Javascript a fondo.
Una vez hemos reparado en el detalle de cómo se escoge la palabra inicialmente para el juego, podemos ver el resto del código. Para ver cómo hemos hecho este script para el juego del ahorcado recomiendo leer la parte en la que se inicia la aplicación y luego ir revisando cada una de las funciones a medida que se van invocando desde el inicio.
Como cualquier aplicación o script jQuery, el código que se ejecuta al principio está dentro método ready del objeto document.
$(document).ready(function(){
//código que inicia la aplicación
}
Podemos ver a continuación las 300 líneas de código que hacen el juego completo.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Aplicaciçon de Ahorcado</title>
<link type="text/css" href="css/cupertino/jquery-ui-1.8.1.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.1.custom.min.js"></script>
<script>
function aleatorio(inferior,superior){
numPosibilidades = superior - inferior + 1
aleat = Math.random() * numPosibilidades
aleat = Math.floor(aleat)
return parseInt(inferior) + aleat
}
function esta(caracter, miarray){
//console.log("buscando ", caracter, " en ", miarray)
for(var j=0;j<miarray.length;j++){
if (caracter==miarray[j]){
return true;
}else{
//console.log("el caracter ", caracter, " no es el valor del array ",miarray[j] )
}
}
return false;
}
function estanTodas(arrayAciertos, mipalabra){
for(var i=0; i<mipalabra.length; i++){
if(!esta(mipalabra.charAt(i),arrayAciertos))
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// PALABRAS
////////////////////////////////////////////////////////////////////////////////
var palabras = ['ahorcado', 'lavadora', 'invierno', 'plastico', 'ordenador', 'colador', 'guantera', 'alimentador', 'calculos'];
var palabraEscogida = palabras[aleatorio(0,palabras.length-1)]
var aciertos = [];
//console.log(palabraEscogida);
function escribePalabra(palabra, arrayAciertos){
//console.log("estoy en escribePalabra y arrat de aciertos es: " , arrayAciertos);
var texto = '';
for(var i=0; i<palabra.length; i++){
texto += "<span>";
var cActual = palabra.charAt(i);
if(esta(cActual,arrayAciertos)){
texto += cActual;
}else{
texto += '_';
}
texto += "</span>";
//console.log(cActual)
}
$("#letras").html(texto);
}
////////////////////////////////////////////////////////////////////////////////
//// inicio todo!!!
////////////////////////////////////////////////////////////////////////////////
$(document).ready(function(){
//creo los botones con las letras
var letras = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
for(i=0; i<letras.length; i++){
//creo el span de la letra
letraActual = $('<span class="botonletra">' + letras[i] + '</span>');
letraActual.data("letra",letras[i]);
//lo convierto en un botón
letraActual.button();
letraActual.click(function(){
//traigo la letra pulsada
var miletra = $(this).data("letra").toLowerCase()
//miro si esa letra está en la palabra
if(palabraEscogida.indexOf(miletra)!=-1){
//si está, va para aciertos
aciertos.push(miletra);
escribePalabra(palabraEscogida, aciertos);
//miro si ha ganado
if(estanTodas(aciertos,palabraEscogida)){
var caja = $('<div class="dialogletra" title="Has Ganado!!">Felicidades! has adivinado la palabra!!</div>');
caja.dialog({
modal: true,
width: 600,
buttons: {
"Ok": function(){
$(this).dialog("close");
}
}
});
}
}else{
//no estaba
numFallos++;
dibujaAhorado(numFallos);
//miro si se ha perdido
if(numFallos==6){
var caja = $('<div class="dialogletra" title="Has Perdido!!">Lo lamento!! la palabra era: ' + palabraEscogida + '</div>');
caja.dialog({
modal: true,
width: 600,
buttons: {
"Ok": function(){
$(this).dialog("close");
}
}
});
}
}
//una vez pulsado el botón, lo desabilito y quito su evento click
$(this).button("disable");
$(this).unbind( "click" );
})
$("#botonesletras").append(letraActual);
}
//inicio el canvas
dibujaAhorado(numFallos);
//inicio las palabras
escribePalabra(palabraEscogida, aciertos);
});
/////////////////////////////////
//CANVAS
/////////////////////////////////
function cargaContextoCanvas(idCanvas){
var elemento = document.getElementById(idCanvas);
if(elemento && elemento.getContext){
var contexto = elemento.getContext('2d');
if(contexto){
return contexto;
}
}
return false;
}
function borrarCanvas(contexto, anchura, altura){
contexto.clearRect(0,0,anchura,anchura);
}
function dibujaHorca(ctx){
ctx.fillStyle = '#462501';
ctx.fillRect(64,9,26,237);
ctx.fillRect(175,193,26,53);
ctx.fillRect(64,193,136,15);
ctx.fillRect(64,9,115,11);
ctx.beginPath();
ctx.moveTo(64,65);
ctx.lineTo(64,80);
ctx.lineTo(133,11);
ctx.lineTo(118,11);
ctx.fill();
}
function dibujaCabeza(ctx){
var img = new Image();
img.onload = function(){
ctx.fillStyle = '#f2d666';
ctx.drawImage(img,150,38);
ctx.fillRect(172,12,4,28);
}
img.src = 'images/picture.jpg';
}
function dibujaCuerpo(ctx){
ctx.beginPath();
ctx.moveTo(171,82);
ctx.lineTo(168,119);
ctx.lineTo(162,147);
ctx.lineTo(189,149);
ctx.lineTo(185,111);
ctx.lineTo(183,83);
ctx.fill()
}
function dibujaBrazoIzq(ctx){
ctx.beginPath();
ctx.moveTo(173,102);
ctx.lineTo(140,128);
ctx.lineTo(155,133);
ctx.lineTo(178,114);
ctx.fill()
}
function dibujaBrazoDer(ctx){
ctx.beginPath();
ctx.moveTo(180,99);
ctx.lineTo(222,121);
ctx.lineTo(209,133);
ctx.lineTo(183,110);
ctx.fill()
}
function dibujaPiernaIzq(ctx){
ctx.beginPath();
ctx.moveTo(166,142);
ctx.lineTo(139,175);
ctx.lineTo(164,178);
ctx.lineTo(175,144);
ctx.fill()
}
function dibujaPiernaDer(ctx){
ctx.beginPath();
ctx.moveTo(178,145);
ctx.lineTo(193,178);
ctx.lineTo(212,170);
ctx.lineTo(188,142);
ctx.fill()
}
////////////////////////////////////////////////////////
// GESTION DE FALLOS
////////////////////////////////////////////////////////
var numFallos = 0;
function dibujaAhorado(numerrores){
var contexto = cargaContextoCanvas('canvasahorcado');
if(contexto){
dibujaHorca(contexto);
if(numFallos>0){
dibujaCabeza(contexto)
}
contexto.fillStyle = '#1f3e18';
if(numFallos>1){
dibujaCuerpo(contexto)
}
if(numFallos>2){
dibujaBrazoIzq(contexto)
}
if(numFallos>3){
dibujaBrazoDer(contexto)
}
if(numFallos>4){
dibujaPiernaIzq(contexto)
}
if(numFallos>5){
dibujaPiernaDer(contexto)
}
}
}
</script>
<style type="text/css">
body{
font-size: 0.7em;
font-family: Trebuchet MS, verdana, arial, sans-serif;
}
.botonletra{
font-size: 0.9em;
margin: 2px;
width: 30px;
text-align: center;
}
.dialogletra{
font-size: 3em;
text-align: center;
padding-top: 15px;
}
#botonesletras{
width: 330px;
clear: both;
}
#dibujoahorcado{
margin-bottom: 20px;
}
#letras{
font-size: 3em;
text-align:center;
width: 320px;
clear: both;
margin-bottom: 10px;
}
#letras span{
width: 30px;
text-align:center;
padding-left: 5px;
}
</style>
</head>
<body>
<div id="dibujoahorcado">
<canvas id="canvasahorcado" width="320" height="250">
El Ahorcado sólo funciona en navegadores que soporten Canvas. Actualízate a Firefox o Chrome, por poner dos posibilidades.
</canvas>
</div>
<div id="letras">
</div>
<div id="botonesletras"></div>
</body>
</html>
Eso es todo!! quedan bastantes cosas que explicar en el tintero, pero estoy seguro que se podrán entender siguiendo los comentarios del código y las referencias a manuales y artículos donde explicamos cosas como jQuery o el componente Canvas.
Para acabar, podemos ver el ejercicio en marcha en una página aparte.