AndorraDotNet

Comunitat d'usuaris .NET del pais dels pirineus
¿No perteneces a AndorraDotNet? ¡Regístrate y sé un miembro!
Iniciar sesión | REGÍSTRATE AQUÍ | Ayuda
en Buscar

Andorra Net User Group Blog

Sudoku en Assembler

:-)

Tal i com sona. Acabo de llegir-ho en el blog de Carlos Fouz a Geeks.ms, i la veritat es que trobo que és una frikada increíble. Per veure el codi formatejat es recomana el programa ConText que es freeware.

logocontext

Us deixo una captura i el codi font per si algú es tan friki de provar-ho:

sudoku

Codi:

;SuDoKu
;Carlos A. Fouz Rodríguez (base - UOC)

.model small         ;modell de memòria SMALL
.stack 1024

DOSSERVICE  EQU  21H	; serveis DOS
BIOSSERVICE EQU  10H	; serveis BIOS

.data 
 Board db '   - S U D O K U -  ' ;Tauler de joc que es mostra a l'inici del programa
        db '  1 2 3 4 5 6 7 8 9 '
        db ' ÉÍÍÍÍÍËÍÍÍÍÍËÍÍÍÍÍ»'
        db '1º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '2º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '3º ³ ³ º ³ ³ º ³ ³ º'
        db ' ÌÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÍ͹'
        db '4º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '5º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '6º ³ ³ º ³ ³ º ³ ³ º'
        db ' ÌÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÍ͹'
        db '7º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '8º ³ ³ º ³ ³ º ³ ³ º'
        db ' ºÄÅÄÅĺÄÅÄÅĺÄÅÄÅĺ'
        db '9º ³ ³ º ³ ³ º ³ ³ º'
        db ' ÌÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍ͹'
        db ' º                 º'
        db ' ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ'
        

  ;Matriu 9x9 amb els valors inicials ; Possible solució
  Sudoku  db '123456789' ; 123456789
  	  db '456789123' ; 456789123
  	  db '789123456' ; 789123456 
  	  db '9123456  ' ; 912345678
  	  db '345678   ' ; 345678912
  	  db '67891    ' ; 678912345
  	  db '8912     ' ; 891234567
  	  db '234    9 ' ; 234567891
  	  db '567      ' ; 567891234

  ;Matriu 9x9 on posarem els números
  Play   db '         '
  	 db '         '
  	 db '         '
  	 db '         '
  	 db '         '
  	 db '         '
  	 db '         '
  	 db '         '
  	 db '         '


  State     db 1  ; 0: Sortir, hem pitjat la tecla 'q' per sortir o s'ha acabat el temps.
                  ; 1: Continuem jugant.
                  ; 2: Guanyador, hem omplert la matriu Play correctament.

  ;Variables per indicar la posició del cursor dins la matriu Sodoku i Play.
  ;No les utilitzeu per indicar la posici¢ del cursor a la pantalla.
  RowCur    db 4  ; [0-8] Val 0:Fila 1,    val 8:Fila 9    (posició inicial:4 = Fila 5)
  ColCur    db 4  ; [0-8] Val 0:Columna 1, val 8:Column 9  (posició inicial:4 = Columna 5)

  RowIni    db ?  ;Fila inicial pel procediment CheckPos
  ColIni    db ?  ;Columna inicial pel procediment CheckPos
  BoxIni    db ?  ;Casella on comença la regió on està la posició que estem mirant.
 
  ;Variables amb els missatges que sortiran per pantalla.
  MsgHelpVacio  db '          ','$'
  MsgExit   db 'Oh! No has pogut acabar!','$'
  MsgWinner db 'Enhorabona!  Has acabat.','$'
  Numeros db '0$1$2$3$4$5$6$7$8$9$'


.code


;*******************************************************************************
; Esborra la pantalla completament escrivint espais en blanc
; Parametres d'entrada: Cap
; Parametres de sortida: Cap
;*******************************************************************************
ClearScreen:

  push AX
  push BX
  push CX
  push DX

  ;Inicialització per posicionar el cursor
  mov bh,00h        ;pàgina
  mov dh,00h        ;fila inicial
  mov dl,00h        ;columna inicial
  mov ah,02h        ;servei per posicionar el cursor
  int BIOSSERVICE

  mov bh,00h        ;pàgina
  mov bl,07h        ;atribut
  mov cx,2000       ;80*25nombre de caràcters a escriure
  mov al,' '        ;caràcter
  mov ah,09h        ;servei per escriure caràcter.
  int BIOSSERVICE

  pop DX
  pop CX
  pop BX
  pop AX

ret

;*******************************************************************************
; Mostra el Tauler de joc sense Dades, és a dir, mostra la matriu Board
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: Cap
;*******************************************************************************
PrintBoard:

  push AX
  push BX
  push CX
  push DX
  push SI

  ;Inicialitzar registres
  mov bh,00h        ;pagina  
  mov dh,00         ;fila inicial a pantalla on mostraurem el Tauler.
  mov dl,24         ;columna inicial a pantalla on mostrarem el Tauler.

  mov bl,07h        ;atribut
  mov cx,1          ;escriurem 1 caràcters cada cop
  
  mov si,0          ;índex per accedir al tauler
  
LoopPB:
  mov ah,02h        ;servei per posicionar el cursor
  int BIOSSERVICE

  mov al,BOARD[SI]  ;caràcter
  mov ah,09h        ;servei per escriure caràcter.
  int BIOSSERVICE

  inc si            ;incrementem l'índex per accedir a les dades
		    ;Actualitzem posició del cursor (fila i columna)
  inc dl            ;columna 
  cmp dl, 44
  jl LoopPB
  mov dl, 24
  inc dh            ;fila
  cmp dh, 23 
  jl LoopPB

  ;Posar el cursor a la posició inicial (5,5)
  mov al,2          ;multipliquem per 2 per saltarnos les ratlles del tauler.
  mul RowCur
  mov dh,al
  add dh,03         ;03: fila a pantalla de la posició (1,1)
  mov al,2
  mul ColCur
  mov dl,al
  add dl,26         ;26: columna a pantalla de la posició (1,1)

  mov ah,02h        ;servei per posicionar el cursor
  mov bh,00h        ;pagina
  int BIOSSERVICE

  pop SI
  pop DX
  pop CX
  pop BX
  pop AX

  ret

;*******************************************************************************
; Verifica quins números no es poden posar en una casella de la matriu Play
;
; Paràmetres d'entrada: SI: Index dins la matriu Play (posició que volem mirar)
; SI: pot pendre valors de 0 a 80.
;
; Paràmetres de sortida: AX: Registre on el bit 'i' indica que en aquella 
; posició NO podem posar-hi el nombre 'i'. AX (bit 15 - bit 0) només utilitzarem
; del (bit 9 - bit 1). EX: 0000 0000 0001 0110 vol dir que a la posició indicada 
; per SI de la matriu Play no podem posar els nombres 1,2 i 4
;*******************************************************************************
CheckPos:

  push BX
  push CX
  push DX
  push SI

  mov ch,Play[SI]   ;agafem la posició que estem verificant, la guardem a la pila
  mov Play[SI],' '  ;i la posem en blanc per no verificar-la.

  mov bl,9          ;Determinal la posició inicial de la fila i columna.
  mov AX,SI         ;SI és la posició dins la matriu Play.
  	    
  div bl            ;dividim SI entre 9
  mov ColIni,ah     ;AH:(reste):columna, AL(quocient): fila
  mov RowIni,al     ;RowIni: fila inicial dins de Play.
                    ;ColIni: columna inicial dins de Play.
  
  mov bl,3          ;Calculem la casella on comanença el quadrant de la posició  
  mov AX,0          ;que estem mirant.
  mov al,ColIni         
  div bl            ;AL(quocient): 
  mov ah,0          ;AH:(reste): no el volem.
  mul bl            
  mov cl,al  

  mov AX,0          
  mov al,RowIni     
  div bl            ;AL(quocient): 
  mov ah,0          ;AH:(reste): no ens cal.
  mov bl,27
  mul bl
  add al,cl
  mov BoxIni,al  

  mov AX,0
  mov al,RowIni
  mov bl,9
  mul bl            ;multipliquem AL(fila)*9
  mov SI,AX         ;SI: Índex de la matriu Play
  add AX,9
  mov BX,AX         ;BX: Índex de la matriu Play on hem de parar.
  mov AX,0          ;AX: Màscara on acumulem els numeros que anem trobant.

CheckRow:
  
  cmp Play[SI],' '
  je ContRow

  mov DX,0000000000000001b  ;DX: Màscara on indicarem el número trobat
  mov Cl,Play[SI]
  sub cl,48
  shl DX,cl          ;posem el 1 a la posició del número que tenim a Play.
  or  AX,DX          ;actualitzarem la màscara AX.
  
ContRow:  
  add SI,1
  cmp SI,BX
  jl  CheckRow


  mov BX,0          
  mov bl,ColIni         
  mov SI,BX         ;SI: Índex de la matriu Play
  
CheckColumm:

  cmp Play[SI],' '
  je ContColumm

  mov DX,0000000000000001b  ;DX: Màscara on indicarem el número trobat
  mov Cl,Play[SI]
  sub cl,48
  shl DX,cl         ;posem el 1 a la posició del número que tenim a Play.
  or  AX,DX          ;actualitzarem la màscara AX.
  
ContColumm:  
  add SI,9
  cmp SI,81
  jl  CheckColumm

  mov BX,0          
  mov bl,BoxIni         
  mov SI,BX         ;SI: Índex de la matriu Play on comença el quadrant.
  add BX,20         ;BX: Índex de la matriu Play on hem de parar. 

CheckBox:

  cmp Play[SI],' '
  je ContBox1

  mov DX,0000000000000001b  ;DX: Màscara on indicarem el número trobat
  mov Cl,Play[SI]
  sub cl,48
  shl DX,cl          ;posem el 1 a la posició del número que tenim a Play.
  or  AX,DX          ;actualitzarem la màscara AX.
  
ContBox1:
  add SI,1

  cmp Play[SI],' '
  je ContBox2

  mov DX,0000000000000001b  ;DX: Màscara on indicarem el número trobat
  mov Cl,Play[SI]
  sub cl,48
  shl DX,cl          ;posem el 1 a la posició del número que tenim a Play.
  or  AX,DX          ;actualitzarem la màscara AX.
  
ContBox2:  
  add SI,1

  cmp Play[SI],' '
  je ContBox3

  mov DX,0000000000000001b  ;DX: Màscara on indicarem el número trobat
  mov Cl,Play[SI]
  sub cl,48
  shl DX,cl          ;posem el 1 a la posició del número que tenim a Play.
  or  AX,DX          ;actualitzarem la màscara AX.
  
ContBox3:

  add SI,7
  cmp SI,BX
  jl  CheckBox

  pop SI

  mov Play[SI],ch  ;restaurem el valor de la matriu Play.

  pop DX
  pop CX
  pop BX
  ;AX té la màscara amb el números que no es poden posar a la posició SI de Play

  ret

;*******************************************************************************
; Copia els valors inicials de la matriu Sudoku a la matriu Play.
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: Cap
;*******************************************************************************
IniPlay:

  mov si,0            ;Índex per anar copiant la informació.
 
  ;Iniciem el bucle per fer la cópia.
LoopIP:

  mov cl,Sudoku[SI]   ;Agafem el valor de la matriu Sudoku
  mov Play[SI],cl     ;Posem el valor a la matriu Play.

  inc si              ;incrementem l'índex per accedir a la següent posició
  cmp si, 81          ;matriu de 9x9 posicions (0-80)
  jl LoopIP
  ret

;*******************************************************************************
; Mostra quins números es poden escriura a la casella del cursor.
; S'ha de tenir en compte que si és casella d'un dels valors inicals no s'hi pot
; escriure res.
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: Cap
;*******************************************************************************
PrintHelp:

  ;eliminem missatge de ajuda anterior pintant la variable MsgHelpVacio
  mov dh,21             ;fila
  mov dl,26             ;columna
  push DX
  lea dx,MsgHelpVacio
  push DX
  call PrintMessage
  add sp,4

  ;POSICIO CURSOR AL ARRAY : Multipliquem per 9 el RowCur + el valor del ColCur
  mov ax,9
  mul RowCur
  mov dx,0
  mov dl,ColCur
  add ax, dx
  mov si, ax         ; si indica la posicio del digit al array

  ;controlem que aquesta posicio es una de las que pot escriure l'usuari
  cmp SUDOKU[ si ],' '
  jne noHelp

  Call CheckPos      ; si es el parametre d´entrada que indica la posicio en l´array
                     ; Paràmetres de sortida: AX: Registre on el bit 'i' indica que en aquella
                     ; posició NO podem posar-hi el nombre 'i'. AX (bit 15 - bit 0) només utilitzarem
                     ; del (bit 9 - bit 1). EX: 0000 0000 0001 0110 vol dir que a la posició indicada
                     ; per SI de la matriu Play no podem posar els nombres 1,2 i 4
  jmp helpCheck1

noHelp:
  mov ax, 0000001111111110b ;si no pot escriure generem la nostre propia AX
helpCheck1:
  ;AX tenim els possibles valors
  mov bl,26             ;columna on escriurem el missatge
  ;verifiquem si pot escriure el 1
  mov dx, ax
  and dx, 0000000000000010b
  cmp dx, 0000000000000010b
  je helpCheck2
  mov dh,21             ;fila
  mov dl,bl             ;columna
  push DX
  lea dx,Numeros[ 2 ]
  push DX
  call PrintMessage     ;pintem el numero 1
  add sp,4
  inc bl                ;incrementem columna per escriure més numeros

helpCheck2:
  ;verifiquem si pot escriure el 2
  mov dx, ax
  and dx, 0000000000000100b
  cmp dx, 0000000000000100b
  je helpCheck3
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 4 ]
  push DX
  call PrintMessage    ;pintem el numero 2
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck3:
  ;verifiquem si pot escriure el 3
  mov dx, ax
  and dx, 0000000000001000b
  cmp dx, 0000000000001000b
  je helpCheck4
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 6 ]
  push DX
  call PrintMessage    ;pintem el numero 3
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck4:
  ;verifiquem si pot escriure el 4
  mov dx, ax
  and dx, 0000000000010000b
  cmp dx, 0000000000010000b
  je helpCheck5
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 8 ]
  push DX
  call PrintMessage    ;pintem el numero 4
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck5:
  ;verifiquem si pot escriure el 5
  mov dx, ax
  and dx, 0000000000100000b
  cmp dx, 0000000000100000b
  je helpCheck6
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 10 ]
  push DX
  call PrintMessage    ;pintem el numero 5
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck6:
  ;verifiquem si pot escriure el 6
  mov dx, ax
  and dx, 0000000001000000b
  cmp dx, 0000000001000000b
  je helpCheck7
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 12 ]
  push DX
  call PrintMessage
  add sp,4             ;pintem el numero 6
  inc bl               ;incrementem columna per escriure més numeros

helpCheck7:
  ;verifiquem si pot escriure el 7
  mov dx, ax
  and dx, 0000000010000000b
  cmp dx, 0000000010000000b
  je helpCheck8
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 14 ]
  push DX
  call PrintMessage    ;pintem el numero 7
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck8:
  ;verifiquem si pot escriure el 8
  mov dx, ax
  and dx, 0000000100000000b
  cmp dx, 0000000100000000b
  je helpCheck9
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 16 ]
  push DX
  call PrintMessage    ;pintem el numero 8
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

helpCheck9:
  ;verifiquem si pot escriure el 9
  mov dx, ax
  and dx, 0000001000000000b
  cmp dx, 0000001000000000b
  je finHelp
  mov dh,21            ;fila
  mov dl,bl            ;columna
  push DX
  lea dx,Numeros[ 18 ]
  push DX
  call PrintMessage    ;pintem el numero 9
  add sp,4
  inc bl               ;incrementem columna per escriure més numeros

finHelp:
  ret

;*******************************************************************************
; Actualitza el contingut del Tauler de Joc amb les dades de la matriu indicada
; per BX. Si a la matriu Sudoku hi ha un espai en blanc en aquella posició s'ha
; d'escriure el número de diferent color.
; Paràmetres d'entrada: BX: Adreça inicial de les dades a mostrar en el tauler.
; Paràmetres de sortida: Cap
;*******************************************************************************
UpdateBoard:
  push AX
  push CX
  push DX
  push SI

  push BX           ; el tractem a apart perque ‚s on tenim l'adreca de la matriu.
                    ; el guardem perque tambe‚ l'hem d'utilitzar en els serveis BIOS

  ;Inicialitzar registres
  mov bh,00h        ;pagina
  mov dh,03         ;fila inicial on podem escriure en el tauler.
  mov dl,26         ;columna inicial on podem escriure en el tauler.

  mov cx,1          ;escriurem 1 caràcters cada cop

  mov si,0          ;índex per a les dades de Sudoku

LoopUB:
  mov ah,02h        ;servei per posicionar el cursor
  int BIOSSERVICE

  pop BX
  mov al,[BX][SI]  ;caràcter
  push BX

  ;Si a la matriu un espai en blanc s'ha d'escriure de diferent color.
  cmp Sudoku[SI],' '
  je diferentColor

  mov bl,09h        ;atribut (blau mar¡ amb intensitat)
  jmp printUpdate

diferentColor:
  mov bl,0Bh        ;atribut (blau clar amb intensitat)

printUpdate:
  mov ah,09h        ;servei per escriure caràcter.
  mov bh,00h        ;pagina
  int BIOSSERVICE

  inc si            ;incrementem l'índex per accedir a les dades
  
  ;Actualitzem posició del cursor (fila i columna)
  inc dl            ;columna ( dos salts per les linees del tauler )
  inc dl
  ;en cas que la columna sigui 44 a la seguent fila (fila + 2)e init la columna a 26
  cmp dl, 44        
  jl LoopUB
  mov dl, 26        ;columna inicial on podem escriure en el tauler.
  inc dh            ;fila  ( dos salts per les linees del tauler )
  inc dh
  cmp dh, 20        ;en cas que la fila sigui 20 ja hem finalitzat d'escriure la matriu.
  jl LoopUB

  ;Posar el cursor a la posició inicial (5,5)
  mov al,2          ;multipliquem per 2 per saltarnos les ratlles del tauler.
  mul RowCur
  mov dh,al
  add dh,03         ;03: fila a pantalla de la posició (1,1)
  mov al,2
  mul ColCur
  mov dl,al
  add dl,26         ;26: columna a pantalla de la posició (1,1)

  mov ah,02h        ;servei per posicionar el cursor
  mov bh,00h        ;pagina
  int BIOSSERVICE

  pop SI
  pop DX
  pop CX
  pop BX
  pop AX

  ret

;*******************************************************************************
; Llegim una tecla utilitzant el servei 08h de les crides al DOS. 
; Segons la tecla llegida cridarem al procediment corresponent.
;  [‘i’,’j’,’k’ o ’l’] cridar al procediment MoveCursor
;  [‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’ o ‘’] cridar al procediment ChangeNum
;  ‘q’ posa Estat=0.
; (per la lectura de teclat utilitzeu només crides als serceis del DOS).
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: Cap
;*******************************************************************************
ReadKey:

  mov ah, 07h		; demanem un digit
  int DOSSERVICE	

  ;SORTIDA DEL PROGRAMA
  cmp al,'q'
  je SalidaReadKey
  cmp al,'Q'
  je SalidaReadKey

  ;MOVIMIENT DEL CURSOR
  cmp al,'i'
  je MoveCursor
  cmp al, 'I'
  je MoveCursor
  cmp al,'j'
  je MoveCursor
  cmp al, 'J'
  je MoveCursor
  cmp al,'k'
  je MoveCursor
  cmp al, 'K'
  je MoveCursor
  cmp al,'l'
  je MoveCursor
  cmp al, 'L'
  je MoveCursor

  ;PETICIO DE CANVI DE NUMERO
  cmp al, ' '
  je ChangeNum
  cmp al, 49    ;si el codigo ASCI de la tecla es menor a 49 ('1') finalitzar
  jb finReadKey
  cmp al, 57    ;si el codigo ASCI de la tecla es mayor a 49 ('9') finalitzar
  jg finReadKey
  jmp ChangeNum ; si arriba aqui es que correspon a 1-9


  ;si no es cap tecla d´aquestes finalitzar en finReadKey
  jmp finReadKey

SalidaReadKey:
  mov State , 0   ;actualitzar State perque el bucle del main finalitzi execució

finReadKey:

  ret

;*******************************************************************************
; Segons la direcció indicada per AL i actualitza RowCur i ColCur 
; segons la direcció que s’hagi seleccionat. No s'ha de posicionar el cursor a 
; pantalla, hi un altre subrutina per fer-ho.
; Paràmetres d'entrada: AL conté la direcció del moviment ('i', 'j', 'k' o 'l')
; Paràmetres de sortida: Cap
;*******************************************************************************
MoveCursor:

  ;seleccionar el moviment que ha demanat el user.
  cmp al,'i'
  je moveCursorUp
  cmp al,'I'
  je moveCursorUp
  cmp al,'k'
  je moveCursorDown
  cmp al,'K'
  je moveCursorDown
  cmp al,'j'
  je moveCursorLeft
  cmp al,'J'
  je moveCursorLeft
  cmp al,'l'
  je moveCursorRight
  cmp al,'L'
  je moveCursorRight

moveCursorUp:        ; moviment cap amunt
  cmp RowCur,0
  je finMoveCursor
  dec RowCur
  jmp finMoveCursor
moveCursorDown:      ; moviment cap abaix
  cmp RowCur,8
  je finMoveCursor
  inc RowCur
  jmp finMoveCursor
moveCursorLeft:      ; moviment cap esquerre
  cmp ColCur,0
  je finMoveCursor
  dec ColCur
  jmp finMoveCursor
moveCursorRight:     ; moviment cap dreta
  cmp ColCur,8
  je finMoveCursor
  inc ColCur

finMoveCursor:
  call PosCurScreen

  ret

;*******************************************************************************
; Escriu / Esborra Número
; Posar el caràcter a la matriu Play. No s'ha de mostrar res.
; Només s'ha de posar el caràcter si no és un número de la matriu Sodoku.
; (la matriu actualitzada es mostrarà en un altre subrutina)
; Paràmetres d'entrada: AL conté el símbol que volem escriure a la matriu.
; Paràmetres de sortida: Cap
;*******************************************************************************
ChangeNum:

  push dx
  push ax

  ;POSICIO CURSOR AL ARRAY : Multipliquem per 9 el RowCur + el valor del ColCur
  mov ax,9
  mul RowCur
  mov dx,0
  mov dl,ColCur
  add ax, dx
  mov si, ax  ;si indica la posicio del digit al array

  cmp Sudoku[si],' '  ;verifiquem que a aquesta posicio el user pot escriure
  jne noPotChangeNum

  pop ax
  mov Play[si], al   ;guardem el valor a la array PLAY
  push ax

noPotChangeNum:
  pop ax
  pop dx

  ret

;*******************************************************************************
; Verifica si hem omplert totes les caselles (no hi ha cap posició de la matriu 
; Play que sigui un espai en blanc) i que els valors escrits siguin correctes 
; si és així canvia State a 2 (Guanyador).
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: Cap
;*******************************************************************************
CheckEnd:
push ax
push cx
   ;initzialitzem valors
   mov si,0
   mov cx,0
   mov bx,0
bucleCheckEnd:              ; recorrem totes les posicions

   cmp SUDOKU[si],' ' ;mirem si es una posicio que el user pot escriure, sino no la validem
   jne noCheckPos
   
   mov ax, si         ;guardem si en ax perque s´utilitza dintre de CheckEndPos

   call CheckEndPos

   cmp bx,1                ;verifiquem el retorn de CheckEndPos ( bx )
   jne noCheckPos
   mov cx,bx                ;si dona alguna possicio incorrecte la guardem

noCheckPos:
   inc si                  ;incrementem index
   cmp si,81
   jne bucleCheckEnd

   cmp cx,0                ; si val 0 es tot correcte
   jne errorcheckend
   mov State,2             ;Actualitzem State a 2 perque el bucle del main finalitzi execucio

errorcheckend:

pop cx
pop ax
  ret

;*******************************************************************************
; Verifica si el valor indicat per parametre (Posicio) es correcte o no
; Paràmetres d'entrada: ax indica la posicio del digit al array
; Paràmetres de sortida: bx 1 si no validem la posicio com a correcte
;*******************************************************************************
CheckEndPos:
  push cx

  mov si, ax         ; si indica la posicio del digit al array

  Call CheckPos      ; si es el parametre d´entrada que indica la posicio en l´array
                     ; Paràmetres de sortida: AX: Registre on el bit 'i' indica que en aquella
                     ; posició NO podem posar-hi el nombre 'i'. AX (bit 15 - bit 0) només utilitzarem
                     ; del (bit 9 - bit 1). EX: 0000 0000 0001 0110 vol dir que a la posició indicada
                     ; per SI de la matriu Play no podem posar els nombres 1,2 i 4


  ;verifiquem si ha d'escriure el 1
  mov dx, ax
  and dx, 0000000000000010b
  cmp dx, 0000000000000010b
  je CheckEndCheck2
  cmp Play[si],'1'
  je CheckEndCheck2
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck2:
  ;verifiquem si pot escriure el 2
  mov dx, ax
  and dx, 0000000000000100b
  cmp dx, 0000000000000100b
  je CheckEndCheck3
  cmp Play[si],'2'
  je CheckEndCheck3
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck3:
  ;verifiquem si pot escriure el 3
  mov dx, ax
  and dx, 0000000000001000b
  cmp dx, 0000000000001000b
  je CheckEndCheck4
  cmp Play[si],'3'
  je CheckEndCheck4
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck4:
  ;verifiquem si pot escriure el 4
  mov dx, ax
  and dx, 0000000000010000b
  cmp dx, 0000000000010000b
  je CheckEndCheck5
  cmp Play[si],'4'
  je CheckEndCheck5
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck5:
  ;verifiquem si pot escriure el 5
  mov dx, ax
  and dx, 0000000000100000b
  cmp dx, 0000000000100000b
  je CheckEndCheck6
  cmp Play[si],'5'
  je CheckEndCheck6
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck6:
  ;verifiquem si pot escriure el 6
  mov dx, ax
  and dx, 0000000001000000b
  cmp dx, 0000000001000000b
  je CheckEndCheck7
  cmp Play[si],'6'
  je CheckEndCheck7
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck7:
  ;verifiquem si pot escriure el 7
  mov dx, ax
  and dx, 0000000010000000b
  cmp dx, 0000000010000000b
  je CheckEndCheck8
  cmp Play[si],'7'
  je CheckEndCheck8
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck8:
  ;verifiquem si pot escriure el 8
  mov dx, ax
  and dx, 0000000100000000b
  cmp dx, 0000000100000000b
  je CheckEndCheck9
  cmp Play[si],'8'
  je CheckEndCheck9
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

CheckEndCheck9:
  ;verifiquem si pot escriure el 9
  mov dx, ax
  and dx, 0000001000000000b
  cmp dx, 0000001000000000b
  je finalCheckEnd
  cmp Play[si],'9'
  je finalCheckEnd
  mov bx, 1          ;si no es correcte actualitzem a 1 bx

finalCheckEnd:
  pop cx
  ret

;*******************************************************************************
; Mostra un missatge a la posició indicada de la pantalla.
; L'adreça del missatge i la posició es passen per la pila. 
; Paràmetres d'entrada: Adreça del missatge [bp+4] i posició (fila,columna) [bp+6]
; Paràmetres de sortida: Cap
;*******************************************************************************
PrintMessage:
     push bp
     mov bp,sp
     push ax           ;salvem a la pila els registres que utilitzem
     push bx
     push dx
     push si

     mov ah,02h        ;servei per posicionar el cursor
     mov bh,00h        ;p…gina
     mov dx,[bp+6]     ;Posem a dh la fila i a dl la columna per escriure
     int BIOSSERVICE

     mov dx,[bp+4]	    ;posem l'adre‡a del missatge al registre DX.
     mov ah,09h
     int DOSSERVICE

     pop si            ;restaurem els registre amb els valor inicials.
     pop dx
     pop bx
     pop ax
     pop bp
  ret

;*******************************************************************************
; Posiciona cursor a la pantalla en base a les variables RowCur i ColCur.
; Paràmetres d'entrada: Cap
; Paràmetres de sortida: cap 
;*******************************************************************************
PosCurScreen:
  push ax
  push dx
  push bx

  ;RowCur  [0-8] Val 0:Fila 1,    val 8:Fila 9    (posició inicial:4 = Fila 5)
  ;control de la fila
  mov al,2          ;multipliquem per 2 per saltarnos les ratlles del tauler.
  mul RowCur        ;el resultat a al
  add al, 3         ;augmentem 3 a al que es el valor incial per aribar a la primera fila del tauler.
  mov dh,al

   ;ColCur  [0-8] Val 0:Columna 1, val 8:Column 9  (posició inicial:4 = Columna 5)
   ;control de la columna
  mov al,2          ;multipliquem per 2 per saltarnos les ratlles del tauler.
  mul ColCur        ;el resultat a al
  add al, 26        ;augmentem 26 a al que es el valor incial per aribar a la primera columna del tauler.
  mov dl,al

  mov bh,00h        ;pàgina
  mov ah,02h        ;servei per posicionar el cursor
  int BIOSSERVICE

errorPosCurScreen:

  pop ax
  pop dx
  pop bx

  ret


;*******************************************************************************
; Programa Principal
;*******************************************************************************
Main:
  STARTUPCODE

  Call ClearScreen   ; netegem la pantalla

  Call PrintBoard    ; mostra el tauler de jov buit ( mostra les línies del tauler)

  push BX
  lea BX , Sudoku   ; cargem les dades de inici del sudoku de l'array Sudoku2
  Call UpdateBoard   ; mostra es numeros que es donen inicialment ( matriu Sudoku )
  pop BX

  Call IniPlay       ; initialitzem la matriu Play amb els valors inicials de la matriu Sudoku


bucle:

  Call PrintHelp      ;Mostrar l'ajuda

  call PosCurScreen   ;Posicionar el cursor al tauler

  call ReadKey        ;llegir una tecla i fer els canvis corresponents a la matriu de dades

  push BX
  lea BX , Play
  Call UpdateBoard   ;Actualitzar el Tauler mostra es numeros  matriu play
  pop BX
    
  call CheckEnd;Verificar si el tauler ja s´ha complert completament

;CONDICIO SORTIDA DEL BUCLE ( STATE != 1 )
cmp State, 1
je bucle

  ;mirem el motiu de la sortida del bucle i mostrem missatge.
  mov dh,24             ;fila
  mov dl,23             ;columna
  push DX

  cmp State, 0
  je stateMessage               
  lea dx,MsgWinner     ; 2: Guanyador, hem omplert la matriu Play correctament.
  jmp fin

stateMessage:
  lea dx,MsgExit       ; 0: Sortir, hem pitjat la tecla 'q' per sortir o s'ha acabat el temps.

fin:
  push DX
  call PrintMessage    ;pintem per pantalla el missatge de finalització d'execució
  add sp,4
  EXITCODE 0           ;finalitzem l'execució

end Main

Comentarios

Aún no ha hecho nadie ningún comentario. Escribe alguno y sé el primero :P

About lfranco

Nacido en 1971 en Barcelona (España), Lluís Franco es MVP en la categoría de Visual Developer desde 2003, MCP Developer, Project Manager y desarrollador en Fimarge Societat Gestora de Patrimonis, situada en Andorra. Desde 1994, ha estado principalmente trabajando en el desarrollo de aplicaciones sobre plataformas Windows. Está especializado en desarrollos financieros con Visual Basic, SQL Server y últimamente C# y ASP.NET. Ha colaborado con campusMVP impartiendo formación sobre ADO.NET, juntamente con otros MVPs como José M. Alarcón Aguín, Rodrigo Corral, Octavio Hernández, Iván González, Alejandro Mezcua, Salvador Ramos, Guillermo Som, "El Guille" o Unai Zorrilla Castro. Mantiene varios sitios Web y blogs, y también colabora con publicaciones especializadas como dotnetmania.
Ofrecido por Community Server (Commercial Edition)