Vistas de página en total

Mostrando entradas con la etiqueta AHORCADO. Mostrar todas las entradas
Mostrando entradas con la etiqueta AHORCADO. Mostrar todas las entradas

miércoles, 24 de julio de 2013

AHORCADO (5/5)

    Ya tenemos las herramientas necesarias para hacer el juego. Las rutinas expuestas antes, no necesitamos guardarlas en librerías, pues son parte de este programa. Por lo tanto son parte del código principal.
    Este, por lo tanto, es el fichero .asm completo que habrá que compilar.
    En el usamos funciones de time, de stdio, de string, y de main.
    El ejecutable resulta de 5232 Bytes

   Es importante pedir la letra con getch, la almacenamos en letra, y luego la convertimos en mayúsculas con upr.

   El programa está preparado para ser un .exe. Para que sea .com debemos colocar la directiva "_modelo com" y linkarlo con una librería preparada para .com.
    Esta librería se formará compilando todas las rutinas expuestas anteriormente pero con esta directiva. y creando luego una libreria completa para .com
   En el caso de que se compile como .com habrá que pasar los datos al final del programa. Esto no lo podemos hacer ahora, pues se producen problemas de compilación.

AHORCADO.ASM
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

include main.mac
include stdio.mac
include string.mac
include time.mac

_modelo exe
_stack 250

_data
;palabras
p1 db 9,"BARCELONA",0
P2 DB 4,"CASA",0
P3 DB 4,"CAMA",0
P4 DB 5,"ARBOL",0
P5 DB 7,"ARMARIO",0
P6 DB 5,"COJIN",0
P7 DB 5,"SUELO",0
P8 DB 4,"FLOR",0
P9 DB 3,"PAN",0
P10 DB 11,"ENCRUCIJADA",0
P11 DB 4,"HOJA",0
P12 DB 8,"CUADERNO",0
P13 DB 11,"ENSAMBLADOR",0
P14 DB 8,"PROGRAMA",0
P15 DB 7,"COLEGIO",0
P16 DB 6,"CAMARA",0

TABLA DW OFFSET P1
      DW OFFSET P2
      DW OFFSET P3
      DW OFFSET P4
      DW OFFSET P5
      DW OFFSET P6
      DW OFFSET P7
      DW OFFSET P8
      DW OFFSET P9
      DW OFFSET P10
      DW OFFSET P11
      DW OFFSET P12
      DW OFFSET P13
      DW OFFSET P14
      DW OFFSET P16

PAL_SEL DW 0
mascara DB "__________________________",0

a_buscar dw 0
letra db 0
fallos db 0
titulo db "AHORCADO",0
pregunta db "INDICA UNA LETRA",0
acierto db "!Enhorabuena! Acertaste",0
perdio db "!Lo siento! Has periddo",0
NW_intento db "Quieres intentarlo de nuevo? S/N",0
limpia db "    ",0
HORCA DB 218,196,196,196,0   ;"┌───┐"


_code
ahorcado proc far
        main   ; inicia
nw:
        call nw_pal    ;gernera una nueva palabra
        mov fallos,0   ;coloca el contador fallos a 0
        ;Preparamos la pantalla
        clrscr
        gotoxy 10,2     ;dibujamos horca
        puts titulo
        gotoxy 8,4
        puts horca
        gotoxy 8,5
        putchar 179
        gotoxy 8,6
        putchar 179
        gotoxy 8,7
        putchar 179
        gotoxy 8,8
        putchar 179
        gotoxy 8,9
        putchar 193
 
        gotoxy 10,10   ; muestra la mascara incial
        puts mascara
        gotoxy 10,13     ; hacemos la pregunta
        puts pregunta
_otro:
        gotoxy 29,13      ;limpia la ultima respuesta
        puts limpia
        gotoxy 29,13
        getch letra    ;pedimos la letra
        upr letra    ;convierte en mayuscula
        call buscar    ;busca la letra
        cmp bh,1       ; 1 si encuentra la letra
        je bien
        inc fallos     ; cuenta un fallo
        cmp fallos,8
        jne bien
        ;perido el juego
        gotoxy 11,4
        putchar 191  ;"┐"   ;dibuja la horca
        gotoxy 10,20         ;Perdiste
        puts perdio
        jmp  nw_int          

bien:
        gotoxy 10,10
        puts mascara
        call muneco
        cmp bl,1      ;1 si faltan letras
        jne _fin     ; estrucutra de saltos debido a que el salto relativo no llega hasta _otro
        jmp _otro
_fin:
        gotoxy 10,20         ;ha acertado
        puts acierto
nw_int:
        gotoxy 10,21
        puts nw_intento
        getch al             ;espera pulsación antes de salir
        upr                   ;convierte al en mayusculas
        cmp al,'S'
        jne  _salir
        jmp nw
_salir: exit 0

endp

nw_pal proc near
        push di
        push si
        random
        and ax,0fh    ; tomo numeros >16
        shl ax,1      ;multiplico por dos
        add ax,offset tabla   ;indexo a la tabla de punteros a palabras
        mov si,ax      ;paso la dirección a 'SI' para indexar
        mov ax,[si]    ; recupero la dirección de la palabra de la tabla de punteros
        mov pal_sel,ax  ; almaceno la dirección de la palabra
        mov si,ax        ; paso esta dirección a si para indexar
        mov di,offset mascara  ; usa 'DI' como indexador de mascara
        mov al,[si]   ; leo el numero de letras de la palabra
ini:
        mov byte ptr [di],'_'   ;borra la mascara
        inc di             ; incrementamos puntero busqueda
        dec al           ; decremento el número de letras
        jnz ini
        mov byte ptr [di],0 ; pongo final de cadena
        pop si
        pop di
ret
nw_pal endp

; busca la letra
; devuelve bl=1 si la encuentra la letra
;          bh=1 si faltan letras
buscar proc near
        push di
        push si
        push cx
        mov bx,0  ;borra banderas
        mov si,pal_sel
        mov di,offset mascara
        mov cl,[si] ;numero de letras a contador de busqueda
        inc si ;salta la longitud de la palabra
prueba:
        mov al,letra
        cmp byte ptr [si],al ;comprueba la letra pasada en al
        jne otra
        mov [di],al ; almacena la letra en mascara
        mov bh,1  ; marca bandera letra encontrada
otra:
        cmp byte ptr [di],"_"
        jne sigue
        mov bl,1  ; bandera palabra incompleta
sigue:
        inc si
        inc di
        dec cl
        jnz prueba
        pop cx
        pop si
        pop di
ret
buscar endp

;representación del muneco
; el contador está en la variable 'fallos'
muneco proc near
        push bx
        mov bl,fallos
        cmp bl,7
        jb s1
        gotoxy 12,8
        putchar '\'
s1:
        cmp bl,6
        jb s2
        gotoxy 10,8
        putchar '/'
s2:
        cmp bl,5
        jb s3
        gotoxy 11,7
        putchar 179   ;"│"
s3:
        cmp bl,4
        jb s4
        gotoxy 11,6
        putchar 179   ;"│"
s4:
        cmp bl,3
        jb s5
        gotoxy 12,6
        putchar '\'
s5:
        cmp bl,2
        jb s6
        gotoxy 10,6
        putchar '/'
s6:
        cmp bl,1
        jb fin
        gotoxy 11,5
        putchar 'O'
fin:
        pop bx
        ret
muneco endp
_end ahorcado








lunes, 22 de julio de 2013

AHORCADO (4/5)

   Esta es la subrutina última antes de generar el programa completo.
   Con ella dibujamos el muñeco.
    Esta si que resulta fácil. Vamos comprobando el valor de fallos y vamos imprimiendo un caracter en una posición según su valor. Comenzamos a comparar del mayor número al menor de manera que se dibujen todos los caracteres por debajo del valor de fallos.
    En este caso no haría falta refrescar todo el dibujo, ya que no borramos pantalla, pero me gusta siempre dejar las cosas bien hechas por si decido cambiar el proceso principal o hacer una nueva versión.



MUÑECO
(c) José Angel Moneo Fdez

;representación del muneco
; el contador está en la variable 'fallos'
muneco proc near
        push bx
        mov bl,fallos
cmp bl,7
jb s1
gotoxy 12,8
putchar '\'
s1:
cmp bl,6
jb s2
gotoxy 10,8
putchar '/'
s2:
cmp bl,5
jb s3
gotoxy 11,7
putchar 179   ;"│"
s3:
cmp bl,4
jb s4
gotoxy 11,6
putchar 179   ;"│"
s4:
cmp bl,3
jb s5
gotoxy 12,6
putchar '\'
s5:
cmp bl,2
jb s6
gotoxy 10,6
putchar '/'
s6:
cmp bl,1
jb fin
gotoxy 11,5
putchar 'O'
fin:
        pop bx
        ret
muneco endp

jueves, 18 de julio de 2013

AHORCADO (2/5)

   Hoy vamos a ver la primera función auxiliar del juego Ahorcado. La función que selecciona la palabra.
   Esta función la hago transparente, para evitar interferencias con el proceso. para ello salvo y recupero los registros que uso en pila.
   El seudocódigo sería:
       - Genera un número aleatorio
       - Se queda con los 4 bits bajos, para que el número no resulte mayor de 15.
       - Lo multiplica por 2 y suma el offset de TABLA para obtener una dirección válida en la tabla de punteros. 
       - Guarda esta dirección como palabra seleccionada.
       - Toma su longitud e inicializa la máscara borrando lo que tuviera y colocando un cero al final para que sea imprimible por puts.
     

     El programa no es compilable si no incluimos las cabeceras y las definiciones de segmentos, pero en este caso todo es parte de un solo programa que colocaré completo en la parte 5/5.

NW_PAL
(c) José Angel Moneo Fdez

nw_pal proc near
        push di
push si
random
       and ax,0fh    ; tomo numeros >16
shl ax,1      ;multiplico por dos
add ax,offset tabla   ;indexo a la tabla de punteros a palabras
mov si,ax      ;paso la dirección a 'SI' para indexar
mov ax,[si]    ; recupero la dirección de la palabra de la tabla de punteros
mov pal_sel,ax  ; almaceno la dirección de la palabra
        mov si,ax        ; paso esta dirección a si para indexar
mov di,offset mascara  ; usa 'DI' como indexador de mascara
        mov al,[si]   ; leo el numero de letras de la palabra
ini:
mov byte ptr [di],'_'   ;borra la mascara
inc di             ; incrementamos puntero busqueda
dec al           ; decremento el número de letras
jnz ini 
mov byte ptr [di],0 ; pongo final de cadena
pop si
pop di
ret
nw_pal endp

martes, 16 de julio de 2013

AHORCADO (1/5)

     Como ya voy haciendo en el blog, voy a subir el nivel un poco más. Para ello  colocaré el código de otro de los juegos más programados como ejemplo, el "AHORCADO".
     Como este juego resulta más complejo que el anterior, lo realizaré en 5 entradas.
      En la primera que es la de hoy explicaré el planteamiento del programa. Es decir haré un análisis de las necesidades para poder estructurar el programa. No colocaré ordinogramas ni pseudocódigos, ya que resultan más complejos de hacer que el propio programa.
     Aunque no sirvan en muchos casos los pseudocódigos, si suelen servir los ordinogramas. Lo que sucede es, que al ser tan simple el lenguaje ensamblador, resulta igual de claro hacer un ordinograma que representar el código en una forma de borrador.
   
     Las 4 entradas del blog las estructuraré de la siguiente manera:
                   1- (La de hoy) Plantearé el problema y organizaré los datos. El segmento Code.
                   2- Primera rutina auxiliar
                   3- segunda rutina auxiliar
                   4- secuencia principal, y por lo tanto programa completo.


     PLANTEAMIENTO

     Como hemos dicho antes, vamos a comenzar por definir el juego, para saber lo que necesitamos construir y en que nos vamos a apoyar.


    Esta será la pantalla durante el juego. Faltan los mensajes finales en caso de perder o acertar.
    Por lo tanto necesitamos ser capaces de dibujar al muñeco y la horca. Cosa facil en principio, para ello usaremos las funciones puts y putchar.+

   ESTRUCTURA
   Necesitamos elegir una palabra de forma aleatoria. En este caso no es un número y por lo tanto parece más difícil, pero en realidad es igual de simple. Generaremos un número que nos permita elegir la palabra. Para ello crearemos una función nw_pal en la que usaremos random, con una lista de punteros a una lista de palabras.
   Necesitamos pedir una letra. Para ello usamos getch. Pero como la letra pueden ponerla en mayúsculas o en minúsculas, para no tener todas las combinaciones de palabras
    Necesitamos buscar la letra dentro de la palabra y definir si la hemos encontrado y si están todas las letras encontradas. Para ello deberemos crear una función buscar.
   Necesitamos dibujar el muñeco, según los errores que se vayan cometiendo. para ello crearemos una función muneco.
    
   Con todo esto ya tenemos analizada la situación del juego. Crearemos tres funciones, muneco (dibuja el muñeco según los errores), nw_pal (selecciona de forma aleatoria una palabra y buscar (busca la letra en la palabra seleccionada).
   Básicamente el código principal entonces queda como el del mastermind, ya que nw_pal equivale a random, muñeco a printf, y buscar a cmp.

     DATOS

   El segmento de datos lo expongo debajo de esta explicación.
   Primero definimos la lista de palabras. Como es un juego ejemplo, no pondré muchas, 16 en concreto para que sean seleccionables con un nibble.
   Quiero que las palabras sean libres, es decir que no estén sujetas a una longitud fija. Esto me plantea el problema de su indexación. Sin su longitud no es fija, no puedo localizarlas con la formula pos=x*longitud.
Pero en  cambio el juego ganará potencia si su longitud es variable.
    Para resolver este dilema, lo que haremos es crear 16 variables db, en las que escribiremos las palabras en formato string. Es decir, colocamos un byte con su longitud y luego una cadena de caracteres terminada en 0. Así podrá ser identificada y manejada de forma fácil.
   Como queremos usar la formula pos=x*longitud para poder seleccionar la palabra a través de un número random, y las palabras no tienen  longitud fija, debemos usar un truco. Este consiste en realizar una tabla de punteros (2 bytes= 1dw), con las direcciones de cada palabra. Así podremos desplazarnos por la tabla con la formula pos=x*2, y seleccionar cualquier palabra a partir del número x generado a través de random.

    La tabla es fácil de crear como una variable dw cuyos valores son los offset de cada palabra.
   Una vez elegida la palabra debemos usarla como el número a buscar. Por ello se pasará su dirección a una variable fija a_buscar. Esta es la misión de la rutina nw_pal. Deberá generar un número aleatorio, indexar con el en la tabla, recoger la dirección de la palabra elegida y guardarla en a_buscar
   Esta era la parte dificil. El resto no hace falta explicarlo. Necesitamos una variable para llevar la cuenta de fallos (fallos), y una variable para ir representando la palabra con las letras encontradas (mascara).
   El dibujo de horca está hecho mediante una lista de números, para evitar que el notepad, guarde mal los códigos ascii especiales. Si usais un editor de dos como ED no hará falta y podréis representar la barra como un texto.

_data
;palabras
p1 db 9,"BARCELONA",0
P2 DB 4,"CASA",0
P3 DB 4,"CAMA",0
P4 DB 5,"ARBOL",0
P5 DB 7,"ARMARIO",0
P6 DB 5,"COJIN",0
P7 DB 5,"SUELO",0
P8 DB 4,"FLOR",0
P9 DB 3,"PAN",0
P10 DB 11,"ENCRUCIJADA",0
P11 DB 4,"HOJA",0
P12 DB 8,"CUADERNO",0
P13 DB 11,"ENSAMBLADOR",0
P14 DB 8,"PROGRAMA",0
P15 DB 7,"COLEGIO",0
P16 DB 6,"CAMARA",0
; tabla de indexación
TABLA DW OFFSET P1
      DW OFFSET P2
      DW OFFSET P3
      DW OFFSET P4
      DW OFFSET P5
      DW OFFSET P6
      DW OFFSET P7
      DW OFFSET P8
      DW OFFSET P9
      DW OFFSET P10
      DW OFFSET P11
      DW OFFSET P12
      DW OFFSET P13
      DW OFFSET P14
      DW OFFSET P16

PAL_SEL DW 0
mascara DB "__________________________",0

a_buscar dw 0
letra db 0
fallos db 0
titulo db "AHORCADO",0
pregunta db "INDICA UNA LETRA",0
acierto db "!Enhorabuena! Acertaste",0
perdio db "!Lo siento! Has periddo",0
NW_intento db "Quieres intentarlo de nuevo? S/N",0
limpia db "    ",0
HORCA DB 218,196,196,196,0   ;"┌───┐"
ends