Sudoku - Commodore VIC-20

Foro dedicado a la programación en todo tipo de sistemas clásicos.
dancresp
Amiga 1200
Amiga 1200
Mensajes: 1393
Registrado: 23 Dic 2008, 17:53
Sistema Favorito: MSX
primer_sistema: ZX81
Primera consola: Atari 2600
Gracias dadas: 3 veces
Gracias recibidas: 20 veces

Sudoku - Commodore VIC-20

Mensajepor dancresp » 25 Abr 2013, 23:13

DSC_1100.jpg
DSC_1100.jpg (108.06 KiB) Visto 6609 veces


EL JUEGO
El objetivo de un SUDOKU es rellenar una cuadrícula de 9x9, que a su vez está dividida en 9 regiones de 3x3, con números de 1 al 9 sin repetir ninguna cifra en la misma fila, columna y región.

El sistema muestra una cantidad de números, que no podemos modificar, y debemos deducir el resto hasta completar todas las casillas.

Controles:
Usa las teclas Q - A - O - P para mover el cursor por la cuadrícula.
Usa los números del 1 al 9 para poner ese número en la posición del cursor.
Pulsa el "0" para borrar el contenido de una celda.
Pulsa "RETURN" para revisar el estado del juego. Se borran los números erróneos y finaliza el juego si no hay fallos.
Pulsa "H" para que el programa ponga el número correcto en la posición del cursor.
Pulsa "R" para mostrar la solución del SUDOKU y finalizar la partida.

Descargar el juego en formato "TAP":
Sudoku.rar
(9.95 KiB) Descargado 301 veces


BLOQUES
He dividido el programa en 12 bloques:

- Definición de variables e inicialización.
- Gestión de teclas.
- Posición del cursor: forma y posición.
- Poner número en una celda.
- Mostrar SUDOKU correcto.
- Corregir el SUDOKU introducido.
- Generar un SUDOKU.
- Mostrar el SUDOKU en pantalla.
- Pantalla de presentación.
- Imprimir la cabecera.
- Rutina de pulsar una tecla.
- Lista de SUDOKU correctos para generar las variantes.


COMO FUNCIONA
He optado por estructurar el programa con una instrucción por línea para facilitar su comprensión.

Se utilizan las siguientes variables, principalmente:

V$() = Matriz donde se guardan el SUDOKU resuelto.
T$() = Matriz donde se guarda los números que se ven en pantalla.
M$() = Matriz donde se indican las casillas fijas (1) o modificables (0).
X = Posición horizontal del cursor respecto a las posiciones del tablero.
Y = Posición vertical del cursor respecto a las posiciones del tablero.

El resto de variables son utilizadas en distintos procesos sin ser de ámbito global.

10 - Definimos las matrices.
50 - Llamamos a la rutina que muestra la presentación (3000) y la que genera el SUDOKU (2000).
90 – Llama a la rutina que destaca la celda activa.
100 - Bloque con el que controlamos el teclado para mover el cursor, ayudar, corregir o resolver el SUDOKU.
500 - Calcula la posición del cursor según la casilla activa.
600 - Pone el valor y color de la casilla activa. Si el número es 0 imprime un punto.
700 - Muestra la solución del SUDOKU. Finaliza la partida.
800 - Rutina de revisión del SUDOKU introducido.
840 - En función de los fallos muestra un mensaje u otro.
890 - Si el SUDOKU es correcto (N=0) se acaba el juego y salta a 50.
900 - Si no es correcto salta a 90, que muestra el cursor.
2000 - Seleccionamos uno de los 3 SUDOKU predefinidos y lo cargamos en B$.
2010 - Si un número aleatorio entre 0 y 1 es menos de 0.5 invertimos el tablero diagonalmente.
2030 - Decidimos si rotamos las columnas verticalmente, y cuantas posiciones (0 a 2).
2040 - Decidimos si rotamos las columnas horizontalmente, y cuantas posiciones (0 a 2).
2080 - Guardamos el SUDOKU en las matrices para su posterior control.
2110 - Ocultamos las celdas en función del nivel de dificultad seleccionado (L). N=L*8.
2500 - Mostramos el SUDOKU definitivo en pantalla.
3000 - Mostramos la pantalla de presentación.
3100 - Seleccionamos el nivel de dificultad pidiendo un número entre 1 y 8. Se guarda en (L).
4000 - Borramos la pantalla y ponemos la cabecera en vídeo inverso.
4100 - Rutina que espera a la pulsación de una tecla.
9000 –Líneas DATA donde guardamos los SUDOKU predefinidos. Se pueden entrar todos los que se quieran.


EL PROGRAMA

Código: Seleccionar todo

  10 DIM T$(9,9),V$(9,9),M$(9,9)

  50 GOSUB 3000:GOSUB 2000:X=1:Y=1
  90 GOSUB 600

     '
     ' Gestión Teclas
     '
 100 GOSUB 4100:GOSUB 640
 120 IF K$=CHR$(13) THEN 800
 130 IF K$="O" AND X>1 THEN X=X-1
 140 IF K$="P" AND X<9 THEN X=X+1
 150 IF K$="Q" AND Y>1 THEN Y=Y-1
 160 IF K$="A" AND Y<9 THEN Y=Y+1
 170 IF K$="R" THEN 700
 180 IF K$>="0" AND K$<="9" AND M$(Y,X)="0" THEN GOSUB 620
 190 IF K$="H" AND M$(Y,X)="0" THEN K$=V$(Y,X):GOSUB 620
 200 GOSUB 600:GOTO 100

     '
     ' Posición Cursor
     '
 500 P=7702+Y*44+X*2:RETURN

     '
     ' Poner Número
     '
 600 C=5:IF M$(Y,X)="1" THEN C=2
 610 GOTO 650
 620 IF K$="0" THEN K$="."
 630 T$(Y,X)=K$
 640 C=6:IF M$(Y,X)="1" THEN C=0
 650 GOSUB 500:POKE P,ASC(T$(Y,X)):POKE 30720+P,C
 660 RETURN

     '
     ' Mostrar Sudoku correcto
     '
 700 FOR Y=1 TO 9:FOR X=1 TO 9
 710 IF M$(Y,X)="0" THEN GOSUB 500:POKE P,ASC(V$(Y,X))
 720 NEXT X:NEXT Y
 730 PRINT "{HOME}{CRSR+DOWN}{RED}  TE HAS RENDIDO !!!"
 740 GOSUB 4100:GOTO 50

     '
     ' Corregir el Sudoku
     '
 800 N=0:F=X:I=Y
 810 FOR Y=1 TO 9:FOR X=1 TO 9
 820 IF T$(Y,X)<>V$(Y,X) THEN N=N+1:K$=".":GOSUB 620
 830 NEXT X:NEXT Y
 840 IF N=0 THEN C$="{GRN}SUDOKU CORRECTO !!!"
 850 IF N>0 THEN C$="{BLU}  HAY"+STR$(N)+" ERRORES"
 860 PRINT "{HOME}{CRSR+DOWN}  "+C$
 870 GOSUB 4100
 880 PRINT "{HOME}{CRSR+DOWN}{BLK}                      "
 890 IF N=0 THEN 50
 900 X=F:Y=I:GOTO 90

     ' ***************************************
     ' *         Generar el SUDOKU           *
     ' ***************************************
2000 RESTORE:FOR F=1 TO INT(RND(1)*3)+1:READ B$,C$:NEXT F:B$=B$+C$

     ' Invertir Diagonalmente
2010 IF RND(1)<.5 THEN 2030
2020 C$="":FOR G=81 TO 1 STEP -1:C$=C$+MID$(B$,G,1):NEXT G:B$=C$

     ' Rotar Verticalmente
2030 N=INT(RND(1)*3):FOR G=0 TO N:B$=RIGHT$(B$,27)+LEFT$(B$,54):NEXT G

     ' Rotar Horizontalmente
2040 N=INT(RND(1)*3)
2050 FOR G=0 TO N
2060 C$="":FOR F=0 TO 8:I=F*9+1:C$=C$+MID$(B$,I+3,6)+MID$(B$,I,3):NEXT F:B$=C$
2070 NEXT G

     ' Guardar el tablero en la matriz
2080 N=1:FOR Y=1 TO 9
2090 FOR X=1 TO 9:C$=MID$(B$,N,1):T$(Y,X)=C$:V$(Y,X)=C$:M$(Y,X)="1":N=N+1:NEXT X
2100 NEXT Y

     ' Ocultar parte de las celdas
2110 N=8*L:FOR F=1 TO N
2120 X=INT(RND(1)*9)+1:Y=INT(RND(1)*9)+1:IF T$(Y,X)="." THEN 2120
2130 T$(Y,X)=".":M$(Y,X)="0":NEXT F

     '
     ' Imprimir el Sudoku Final
     '
2500 GOSUB 4000:PRINT " ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿"
2510 FOR F=1 TO 3
2520 FOR I=1 TO 5:PRINT " ³     ³     ³     ³":NEXT I
2530 IF F<3 THEN PRINT " ÃÄÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÄ´"
2540 NEXT F
2550 PRINT " ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ";
2560 FOR Y=1 TO 9:FOR X=1 TO 9:K$=T$(Y,X):GOSUB 640:NEXT X:NEXT Y
2570 PRINT " [RTN]:Revisar  [H]elp "
2580 RETURN

     '
     ' Pantalla de Presentacion
     '
3000 GOSUB 4000
3010 PRINT "{CRSR-DOWN}{CRSR-DOWN}CONTROLES:{CRSR-DOWN}"
3020 PRINT "CURSOR: Q-A-O-P"
3030 PRINT "NUMERO: 1-9  0=ANULAR"
3040 PRINT "RENDIR: R"
3100 PRINT "{CRSR-DOWN}{CRSR-DOWN}{CRSR-DOWN}{CRSR-DOWN}DIFICULTAD: 1-8"
3110 GOSUB 4100:IF K$<"1" OR K$>"8" THEN 3110
3120 PRINT "{CRSR-DOWN}{CRSR-DOWN}GENERANDO..."
3130 L=VAL(K$):RETURN

     '
     ' Imprimir la Cabecera
     '
4000 PRINT "{CLR}{RVS-ON}{BLK}SUDOKU    SCAINET,2013":RETURN

     '
     ' Rutina Pulsar Tecla
     '
4100 GET K$:IF K$="" THEN 4100
4110 RETURN

     '
     ' Datos de SUDOKUS Correctos
     '
9000 DATA "835416927296857431417293658569134782123678549"
9005 DATA "748529163652781394981345276374962815"
9010 DATA "357964281468123579912587463631795842724318695"
9015 DATA "895246137176459328583672914249831756"
9020 DATA "845967312723814956961532748359178624617243895"
9025 DATA "284659137576491283492386571138725469"



EL PROYECTO
El objetivo del programa consistía en investigar un método para generar SUDOKUS automáticamente, y trasladarlo al BASIC de sistemas de 8 bits. Esto quiere decir que el proceso debía ser rápido y sencillo.

Lo que en un principio parecía algo trivial se convirtió en un quebradero de cabeza. Pero como dicen que más vale “maña que fuerza”, al final he recurrido a una solución más que digna que funciona bien, y sobretodo muy rápidamente.


APUNTES FINALES
Este programa es una adaptación de la versión del SHARP MZ-80B publicada anteriormente, con algunas mejoras para hacerlo caber en los 3.5 KB de RAM del VIC-20.

Diferencias:
- Los datos de los SUDOKU correctos están en líneas DATA en lugar de una matriz, para ahorrar memoria. De esta forma gastamos la mitad de memoria, ya que en la versión anterior los SUDOKU ocupan memoria como líneas de programa y como matrices. En esta versión, en la línea 2000 decidimos que SUDOKU usamos, cargando únicamente uno en memoria y no los tres. Cada SUDOKU ocupa dos líneas ya que el VIC-20 no admite líneas de más de 90 caracteres.

- Las matrices usadas para almacenar el SUDOKU son del tipo cadena y no numéricas. Teniendo en cuenta que solo guardamos una cifra por posición, el uso de matrices numéricas ocupaba unas 6 o 7 veces más memoria, no dejando espacio para el programa en si.

- Esta versión es en color, haciendo que las cifras fijas sean de color negro y las variables de color azul. La dígito de la celda activa es verde si nos permite modificarlo o roja si es fijo.

Por el resto, la funcionalidad de esta versión es idéntica a la original del SHARP MZ-80B.

Respecto al BASIC, esta versión es casi idéntica a la original. Las únicas modificaciones afectan a todo lo relacionado con la pantalla, ya que el BASIC del VIC-20 no permite (de una forma sencilla) situarse en una posición concreta de la pantalla. Aquí he POKEado directamente la memoria de video, tanto para los caracteres como para el color.

El programa ocupa unos 2.2 KB de RAM y durante la ejecución solo deja libres unos 160 bytes, con lo que quedaría memoria para introducir algún SUDOKU más.

Para terminar, decir que hacía 20 años que no programaba nada en el VIC-20, y ya no recordaba lo poco cómodo que es trabajar con una pantalla con tan pocas columnas. Sus 23 filas x 22 columnas son un engorro. Pero el SUDOKU ha quedado bastante bien...

Os invito a probarlo.

DSC_1108.jpg
DSC_1108.jpg (94.43 KiB) Visto 6609 veces

DSC_1099.jpg
DSC_1099.jpg (110.05 KiB) Visto 6609 veces

DSC_1102.jpg
DSC_1102.jpg (125.42 KiB) Visto 6609 veces

DSC_1103.jpg
DSC_1103.jpg (74.74 KiB) Visto 6609 veces

DSC_1104.jpg
DSC_1104.jpg (90.45 KiB) Visto 6609 veces
Última edición por dancresp el 03 Ene 2014, 13:44, editado 3 veces en total.
Buscando la IP de la W.O.P.R.

Avatar de Usuario
Jaimen
Amiga 1200
Amiga 1200
Mensajes: 1656
Registrado: 17 Mar 2009, 13:39
Sistema Favorito: Amstrad CPC
primer_sistema: Amstrad CPC
Ubicación: Madrid
Gracias dadas: 159 veces
Gracias recibidas: 19 veces

Re: Sudoku - Commodore VIC-20

Mensajepor Jaimen » 26 Abr 2013, 07:53

Como siempre, fantástico. El VIC-20 es una de mis máquinas pendientes... :D
Mi galeria de fotos en 500px.com

Avatar de Usuario
mike_01
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 142
Registrado: 08 Dic 2012, 00:58
Sistema Favorito: VIC20
primer_sistema: VIC20
consola_favorita: NeoGeo
Primera consola: (Otro)
Ubicación: Valencia

Re: Sudoku - Commodore VIC-20

Mensajepor mike_01 » 26 Abr 2013, 15:58

¡Está genial! Siempre me sorprenderá la de programas y juegos vistosos que se pueden hacer con los 3KB del VIC-20.
Enhorabuena por el trabajo dancresp, y por tu exposición del proyecto.

De momento, no tengo mi VIC-20 a punto para probarlo, pero cuando tenga un rato lo probaré al menos con el VICE.

Por cierto, me estaba preguntando como convertir el programa BASIC en un fichero WAV para cargarlo en el VIC-20 de alguna manera, y me he encontrado que mediante el VICE y con el programa TapWav se puede hacer.

Avatar de Usuario
zitror
Amiga 2500
Amiga 2500
Mensajes: 5349
Registrado: 02 Jul 2006, 00:16
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
Ubicación: El interior de un Z80
Gracias dadas: 248 veces
Gracias recibidas: 104 veces
Contactar:

Re: Sudoku - Commodore VIC-20

Mensajepor zitror » 27 Abr 2013, 11:49

=D>

Sí que se ve engorroso el listado de basic, ¿no hay forma en el VIC de habilitar menos columnas o unos caracteres más pequeños?

Lo dicho, =D>
(C) 1.982 Sinclair Research Ltd

La buhardilla de Zitror

dancresp
Amiga 1200
Amiga 1200
Mensajes: 1393
Registrado: 23 Dic 2008, 17:53
Sistema Favorito: MSX
primer_sistema: ZX81
Primera consola: Atari 2600
Gracias dadas: 3 veces
Gracias recibidas: 20 veces

Re: Sudoku - Commodore VIC-20

Mensajepor dancresp » 27 Abr 2013, 22:52

zitror escribió:Sí que se ve engorroso el listado de basic, ¿no hay forma en el VIC de habilitar menos columnas o unos caracteres más pequeños?

Existen algunos cartuchos que permiten usar modos de 40 y 80 columnas.

El de 40 columnas redefine los caracteres usando una matriz más pequeña, en lugar de los 8x8 pixels habituales, pero la de 80 columnas funciona de otra forma porque lleva una RAM extra.

Pero lo dicho, programarlo en BASIC es poco cómodo con esa resolución.
No conozco ningún otro sistema que tenga más filas que columnas...
Buscando la IP de la W.O.P.R.

dancresp
Amiga 1200
Amiga 1200
Mensajes: 1393
Registrado: 23 Dic 2008, 17:53
Sistema Favorito: MSX
primer_sistema: ZX81
Primera consola: Atari 2600
Gracias dadas: 3 veces
Gracias recibidas: 20 veces

Re: Sudoku - Commodore VIC-20

Mensajepor dancresp » 03 Ene 2014, 13:44

Subo el hilo y adjunto enlace al fichero ".tap" para poderlo cargar desde un emulador.
Buscando la IP de la W.O.P.R.


Volver a “Programación”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados