5.
El juego del Ahorcado.
Contenido
de este apartado:
5.1.
Pautas generales.
La
idea básica de lo que tiene que hacer el juego es la siguiente:
- Generar
un número al azar, y con ese número escoger una palabra
de
entre las predefinidas. Esa es la palabra que deberá adivinar el
usuario.
- Repetimos:
- El
usuario elige una letra.
- Si
esa letra está en la palabra buscada, mostramos en que
posiciones
se encuentra.
- Si
no está en la palabra, le queda un intento menos.
- Hasta
que se quede sin intentos o acierte la palabra.
El
resto de características ya son "refinamientos". Por ejemplo, si
termina sin acertar, le decimos cual era la palabra buscada.
Además,
por tratarse de un juego gráfico, en cada "pasada" comprobaremos
cuantos fallos lleva, para dibujar la correspondiente parte del
"patíbulo"
de nuestro ahorcado.
Y
todavía no buscamos una gran presentación, nos basta con
que la apariencia sea sencilla, algo así:

Por tanto, la única
complicación es: escribir texto en pantalla, dibujar
líneas y círculos, y generar números al azar. Todo
eso ya lo samos hacer, así que vamos con ello...
5.2 Ahorcado en
C.
Debería ser fácil de seguir...
/*------------------------------*/
/*
Intro a la programac de
*/
/*
juegos, por Nacho Cabanes */
/*
*/
/*
IPJ05C.C
*/
/*
*/
/*
Quinto ejemplo: juego del */
/*
ahorcado (versión básica)
*/
/*
*/
/*
Comprobado
con:
*/
/*
- Djgpp 2.03 (gcc 3.2)
*/
/*
y Allegro 4.02 -
MsDos */
/*
- MinGW 2.0.0-3 (gcc 3.2) */
/*
y Allegro 4.02 -
Win 98 */
/*
- DevC++ 4.9.9.2(gcc 3.4.2) */
/*
y Allegro 4.03 -
Win XP */
/*------------------------------*/
#include
<stdio.h> /*
Rutinas estándar, como "printf" */
#include
<string.h> /*
Manejo de cadenas */
#include
<stdlib.h> /*
Para "rand" */
#include
<time.h> /*
Para "time" */
#include
<ctype.h> /*
Para "tolower" */
#include
<allegro.h>
#define
NUMPALABRAS 10
#define
MAXINTENTOS 5
/* No deberíamos modificar
el número máximo de intentos,
porque vamos
a dibujar 5 "cosas" cuando se equivoque" */
char
palabra[80],
intento[80],
letras[80];
/*
La palabra a adivinar, la que */
/*
el jugador 2 va consiguiendo y */
/*
las letras que se han probado */
int
oportunidades;
/*
El número de intentos permitido */
char
letra;
/*
Cada letra que prueba el jug. dos */
int
i;
/*
Para mirar cada letra, con "for" */
int
acertado;
/*
Si ha acertado alguna letra */
char
ficticia[2];
/*
Aux, para añadir letra a cadena */
char
mensaje[80];
/*
Los letreros que mostrar en pantalla */
char
datosPalabras [NUMPALABRAS][80]=
{
"Alicante","Barcelona","Guadalajara","Madrid",
"Toledo","Malaga","Zaragoza","Sevilla",
"Valencia","Valladolid"
};
void PrimerFallo()
/*
Primer fallo: */
{
/*
Dibujamos la "plataforma" */
line(screen,20,180,120,180,
palette_color[13]);
}
void SegundoFallo()
/*
Segundo fallo: */
{
/*
Dibujamos el "palo vertical" */
line(screen,100,180,100,125,
palette_color[13]);
}
void TercerFallo()
/*
Tercer fallo: */
{
/*
Dibujamos el "palo superior" */
line(screen,100,125,70,125,
palette_color[13]);
}
void CuartoFallo()
/*
Cuarto fallo: */
{
/*
Dibujamos la "cuerda" */
line(screen,70,125,70,130,
palette_color[13]);
}
void QuintoFallo()
/*
Quinto fallo: */
{
int j;
/*
Dibujamos la "persona" */
/*
Cabeza */
circle(screen,70,138,8,
palette_color[12]);
/*
Tronco */
line(screen,70,146,70,160,
palette_color[12]);
/*
Brazos */
line(screen,50,150,90,150,
palette_color[12]);
/*
Piernas */
line(screen,70,160,60,175,
palette_color[12]);
line(screen,70,160,80,175,
palette_color[12]);
}
int
main()
{
allegro_init();
/*
Inicializamos Allegro */
install_keyboard();
/*
Intentamos entrar a modo grafico */
if (set_gfx_mode(GFX_SAFE,320,200,0,0)!=0){
set_gfx_mode(GFX_TEXT,0,0,0,0);
allegro_message(
"Incapaz
de
entrar a modo grafico\n%s\n",
allegro_error);
return 1;
}
/*
Si todo ha ido bien: empezamos */
srand(time(0));
/*
Valores iniciales */
strcpy(palabra,
datosPalabras[ rand()%(NUMPALABRAS+1)]);
oportunidades = MAXINTENTOS;
strcpy(letras,"");
/*
Relleno con _ y " " lo que ve Jug. 2 */
for (i=1;
i<=strlen(palabra);
i++)
if (palabra[i-1]=='
' )
intento[i-1]='
';
else
intento[i-1]='_';
intento[i]='\0'; /* Y
aseguro que termine correctamente */
/*
Parte repetitiva: */
do {
clear_bitmap(screen);
/* Dibujo lo que corresponde
del "patibulo" */
if (oportunidades
<=4)
PrimerFallo();
if (oportunidades
<=3)
SegundoFallo();
if (oportunidades
<=2)
TercerFallo();
if (oportunidades
<=1)
CuartoFallo();
/*
Digo cuantos intentos le quedan */
textprintf(screen,
font, 80,18,
palette_color[15],
"Te
quedan
%d intentos", oportunidades);
/*
Le muestro c¢mo va */
textprintf(screen,
font, 80,32,
palette_color[15],
intento,
oportunidades);
/*
Las letras intentadas */
textprintf(screen,
font, 20,72,
palette_color[14],
"Letras
intentadas:
%s", letras);
/* Y
le pido otra letra */
textprintf(screen,
font, 20,60,
palette_color[14],
"Que
letra?");
letra = readkey()&0xff;
/*
Añado esa letra a las tecleadas*/
strcpy
(ficticia,"a"); /*
Usando una cadena de texto aux */
ficticia[0]=
letra;
strcat
(letras,
ficticia);
acertado = 0; /*
Miro a ver si ha acertado */
for (i=1;
i<=strlen(palabra);
i++)
if(tolower(letra)==
tolower(palabra[i-1]))
{
intento[i-1]=
palabra[i-1];
acertado = 1;
}
if (!
acertado ) /*
Si falló, le queda un intento menos */
oportunidades --;
}
while (
strcmp (intento,palabra) /*
Hasta que acierte */
&& (oportunidades>0));
/* o
gaste sus oportunidades */
/*
Le felicito o le digo cual era */
if (
strcmp (intento,palabra)==0)
textprintf(screen,
font, 20,100,
palette_color[11],
"Acertaste!");
else
{
textprintf(screen,
font, 20,100,
palette_color[11],
"Lo
siento.
Era: %s", palabra);
QuintoFallo();
}
readkey();
return 0;
}
/*
Termino con la "macro" que me pide Allegro
*/
END_OF_MAIN();
|
5.3.
Ahorcado en Pascal.
Esta versión debería ser aun más fácil de
seguir que la de C:
(*----------------------------*) (* Intro a la programac de *) (* juegos, por Nacho Cabanes *) (* *) (* IPJ05P.PAS *) (* *) (* Cuarto ejemplo: juego del *) (* ahorcado (versión básica) *) (* *) (* Comprobado con: *) (* - FreePascal 1.10 - Dos *) (* - FreePascal 2.0 -Windows *) (*----------------------------*)
uses graph, crt; (* Cambiar por "uses wincrt, ..." bajo Windows *)
const NUMPALABRAS = 10; const MAXINTENTOS = 5; (* No deberíamos modificar el número máximo de intentos, porque vamos a dibujar 5 'cosas' cuando se equivoque *)
var palabra, intento, letras: string[80]; (* La palabra a adivinar, la que *) (* el jugador 2 va consiguiendo y *) (* las letras que se han probado *)
oportunidades: integer; (* El número de intentos permitido *) oportStr: string; (* Y para convertirlo a cadena *) letra: char; (* Cada letra que prueba el jug. dos *) i: integer; (* Para mirar cada letra, con 'for' *) acertado: boolean; (* Si ha acertado alguna letra *)
mensaje: string[80]; (* Los letreros que mostar en pantalla *)
const datosPalabras: array [1..NUMPALABRAS] of string= ( 'Alicante','Barcelona','Guadalajara','Madrid', 'Toledo','Malaga','Zaragoza','Sevilla', 'Valencia','Valladolid');
procedure PrimerFallo; (* Primer fallo: *) begin (* Dibujamos la 'plataforma' *) setcolor(13); line(20, 180, 120, 180); end;
procedure SegundoFallo; (* Segundo fallo: *) begin (* Dibujamos el 'palo vertical' *) setcolor(13); line(100, 180, 100, 125); end;
procedure TercerFallo; (* Tercer fallo: *) begin (* Dibujamos el 'palo superior' *) setcolor(13); line(100, 125, 70, 125); end;
procedure CuartoFallo; (* Cuarto fallo: *) begin (* Dibujamos la 'cuerda' *) setcolor(13); line(70, 125, 70, 130); end;
procedure QuintoFallo; (* Quinto fallo: *) begin (* Dibujamos la 'persona' *) setcolor(12); (* Cabeza *) circle(70, 138, 8); (* Tronco *) line(70, 146, 70, 160); (* Brazos *) line(50, 150, 90, 150); (* Piernas *) line(70, 160, 60, 175); line(70, 160, 80, 175); end;
var gd,gm, error : integer;
BEGIN gd := D8bit; gm := m320x200; (* Si falla bajo Windows, probar gd:=0; gm:=0; *) initgraph(gd, gm, '');
(* Intentamos entrar a modo grafico *) error := graphResult; if error <> grOk then begin writeLn('No se pudo entrar a modo grafico'); writeLn('Error encontrado: '+ graphErrorMsg(error) ); halt(1); end;
(* Si todo ha ido bien: empezamos *) randomize; (* Valores iniciales *) palabra := datosPalabras[ round(random * NUMPALABRAS) + 1 ]; oportunidades := MAXINTENTOS;
letras := '';
(* Relleno con _ y ' ' lo que ve Jug. 2 *) intento := palabra; for i:=1 to length(palabra) do if palabra[i] = ' ' then intento[i] := ' ' else intento[i] := '_';
(* Parte repetitiva: *) repeat clearDevice;
(* Dibujo lo que corresponde del 'patibulo' *) if (oportunidades <= 4) then PrimerFallo; if (oportunidades <= 3) then SegundoFallo; if (oportunidades <= 2) then TercerFallo; if (oportunidades <= 1) then CuartoFallo;
(* Digo cuantos intentos le quedan *) setColor(15); str(oportunidades, oportStr); outTextXY(80, 18, 'Te quedan '+oportStr+' intentos');
(* Las letras intentadas *) outTextXY(80, 32, intento);
setColor(14); outTextXY(20, 72, 'Letras intentadas: '+letras);
(* Y le pido otra letra *) outTextXY(20, 60, 'Que letra?');
letra := readkey;
(* Añado esa letra a las tecleadas*) letras := letras + letra;
acertado := false; (* Miro a ver si ha acertado *) for i := 1 to length(palabra) do if lowercase(letra) = lowercase(palabra[i]) then begin intento[i] := palabra[i]; acertado := true; end;
if not acertado then (* Si falló, le queda un intento menos *) oportunidades := oportunidades - 1;
until (intento = palabra) (* Hasta que acierte *) or (oportunidades=0); (* o gaste sus oportunidades *)
(* Le felicito o le digo cual era *)
setcolor(15); if intento = palabra then outTextXY(20, 100, 'Acertaste!') else begin outTextXY(20, 100, 'Lo siento. Era: '+ palabra); QuintoFallo; end;
readkey; closeGraph;
end.
|
5.4.
Ahorcado con Java.
La diferencia grande con la
versión en C es la forma en que se estructura, como ya vimos en
el ejemplo anterior: en "init" pondremos todo lo que sea
inicialización, en "paint" todo lo que dibuje en pantalla
(aunque hemos desglosado ligeramente lo que hacer en el caso de
cada fallo, igual que en la versión en C), y en "keyPressed"
agruparemos las operaciones básicas que hay que realizar cuando
se pulsa una tecla.
- Las demás diferencias
son básicamente de sintaxis. Por ejemplo:
- Para escribir un texto y
una cifra usamos cosas como expresiones más parecidas a Pascal
que a C, cosas como g.drawString("Te quedan " + oportunidades + "
intentos", 80, 18);
- Para leer el
carácter que hay en una posición de una cadena usaremos
palabra.charAt(i-1) y para cambiar el carácter que hay en una
posición se haría con palabra.setCharAt(i-1, 'a').
- Para comparar dos cadenas
de texto usamos la construcción palabra.equals(otraPalabra)
- La cadena de texto que
debemos modificar con frecuencia (intento) no la definimos como String
sino como StringBuffer, que es el tipo de datos que permite operaciones
avanzadas como SetCharAt.
La apariencia será
algo como:

Y una forma de desarrollarlo sería:
/*----------------------------*/
/*
Intro a la programac de */
/*
juegos, por Nacho Cabanes */
/*
*/
/*
ipj05j.java
*/
/*
*/
/*
Cuarto ejemplo: juego del */
/*
ahorcado (versión básica) */
/*
*/
/*
Comprobado
con: */
/*
- JDK
1.4.2_01
*/
/*
- JDK
1.5.0
*/
/*----------------------------*/
import
java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public
class
ipj04j extends Applet
implements
KeyListener
{
final int
NUMPALABRAS = 10;
final
int
MAXINTENTOS = 5;
//
No deberíamos modificar el número máximo de
intentos,
//
porque vamos a dibujar 5 "cosas" cuando se equivoque
String palabra;
//
La palabra a adivinar
StringBuffer intento; // Lo que el jugador 2 va consiguiendo
String letras=""; // Las letras que se han probado
int oportunidades; // El número de intentos permitido
char
letra;
//
Cada letra que prueba el jug. dos
int
i;
//
Para mirar cada letra, con "for"
boolean
acertado;
//
Si ha acertado alguna letra
boolean
terminado; // Si la partida ha terminado
String datosPalabras []=
{
"Alicante","Barcelona","Guadalajara","Madrid",
"Toledo","Malaga","Zaragoza","Sevilla",
"Valencia","Valladolid"
};
void
PrimerFallo(Graphics g)
{ //
Primer fallo: Dibujamos la "plataforma"
g.setColor(Color.cyan);
g.drawLine(20, 180, 120, 180);
}
void SegundoFallo(Graphics g)
{ //
Segundo fallo: Dibujamos el "palo vertical"
g.drawLine(100, 180, 100, 125);
}
void TercerFallo(Graphics g)
{ //
Tercer fallo: Dibujamos el "palo superior"
g.drawLine(100, 125,
70, 125);
}
void CuartoFallo(Graphics g)
{ // Cuarto
fallo: Dibujamos la "cuerda"
g.drawLine(70, 125,
70, 130);
}
void QuintoFallo(Graphics g)
{ // Quinto
fallo: Dibujamos la "persona"
int
j;
// Cabeza
g.setColor(Color.yellow);
g.drawOval(62, 130, 16, 16);
//
Tronco
g.drawLine(70, 146,
70, 160);
//
Brazos
g.drawLine(50, 150, 90, 150);
//
Piernas
g.drawLine(70, 160,
60, 175);
g.drawLine(70, 160,
80, 175);
}
public void init() {
//
Valores iniciales
i = (int) Math.round(Math.random() * NUMPALABRAS);
palabra = datosPalabras[ i ];
oportunidades = MAXINTENTOS;
//
Relleno con * y " " lo que ve Jug. 2
intento = new
StringBuffer(palabra);
for
(i=1; i<=palabra.length(); i++)
if
(palabra.charAt(i-1) == ' ' )
intento.setCharAt(i-1, ' ');
else
intento.setCharAt(i-1, '*');
terminado = false;
requestFocus();
addKeyListener(this);
}
public void paint(Graphics
g) {
//
Primero borro el fondo en negro
g.setColor(
Color.black );
g.fillRect(
0, 0, 639, 479 );
//
Digo cuantos intentos le quedan
g.setColor(Color.white);
g.drawString("Te quedan " +
oportunidades + "
intentos",
80, 18);
//
Le muestro como va
g.drawString(intento.toString(),
80, 32);
//
Muestro las letras probadas
g.setColor(Color.yellow);
g.drawString("Letras intentadas:" +
letras,
20, 72);
//
Y le pido otra letra
g.drawString("Que letra?",
20, 60);
//
Dibujo lo que corresponde del "patibulo"
if
(oportunidades
<=
4) PrimerFallo(g);
if
(oportunidades
<=
3) SegundoFallo(g);
if
(oportunidades
<=
2) TercerFallo(g);
if
(oportunidades
<=
1) CuartoFallo(g);
//
Si se acabo: Le felicito o le digo cual era
if
((oportunidades
<=
0) || (palabra.equals(intento.toString()))) {
terminado = true;
if
(
palabra.equals(intento.toString() ) )
g.drawString("Acertaste!",
20, 100);
else
{
g.drawString("Lo siento. Era: " +
palabra,
20, 100);
QuintoFallo(g);
}
}
}
public void keyTyped(KeyEvent
e) {
letra=e.getKeyChar();
if
(! terminado) {
letras=letras+letra;
acertado = false; // Miro a ver si ha acertado
for
(i=1; i<=palabra.length(); i++)
if
(Character.toLowerCase(letra) == Character.toLowerCase(palabra.charAt(i-1)))
{
intento.setCharAt(i-1, palabra.charAt(i-1) );
acertado = true;
}
if ( ! acertado )
//
Si falló, le queda un intento menos
oportunidades --;
}
repaint();
e.consume();
}
public void keyReleased(KeyEvent
e) {
}
public void keyPressed(KeyEvent
e) {
}
}
|
 
|