Durante cierto tiempo miré con entusiasmo este compilador de Basic, coetáneo de VisualBasic, como una solución para programar fácilmente en Windows. Sin embargo, me venció la pereza, dejé de usarlo, y cuando intenté volver descubrí que no era tan fácil como parecía…
El siguiente programa genera los movimientos posibles del caballo de ajedrez. Uso XBasic para conseguir velocidad, y porque permite usar tipos que Qbasic no permite, como los BYTE, para ahorrar memoria. Estos movimientos pueden ser interpretados por un programa qbasic como PRSALC.BAS. Hice también un programa en javascript que presentaba problemas de saltos del caballo.
' ' ' #################### ' ##### PROLOG ##### ' #################### ' PROGRAM "xbCaballo" ' 1-8 char program/file name without .x or any .extent VERSION "1.1000" ' version number - increment before saving altered program ' ' You can stop the PDE from inserting the following PROLOG comment lines ' by removing them from the prolog.xxx file in your \xb\xxx directory. ' ' Programs contain: 1: PROLOG - no executable code - see below ' 2: Entry function - start execution at 1st declared func ' * = optional 3: Other functions - everything else - all other functions ' ' The PROLOG contains (in this order): ' * 1. Program name statement PROGRAM "progname" ' * 2. Version number statement VERSION "0.0000" ' * 3. Import library statements IMPORT "libName" ' * 4. Composite type definitions TYPE <typename> ... END TYPE ' 5. Internal function declarations DECLARE/INTERNAL FUNCTION Func (args) ' * 6. External function declarations EXTERNAL FUNCTION FuncName (args) ' * 7. Shared constant definitions $$ConstantName = literal or constant ' * 8. Shared variable declarations SHARED variable ' ' ****** Comment libraries in/out as needed ***** ' ' IMPORT "xma" ' Math library : SIN/ASIN/SINH/ASINH/LOG/EXP/SQRT... ' IMPORT "xcm" ' Complex library : complex number library (trig, etc) IMPORT "xst" ' Standard library : required by most programs ' IMPORT "xgr" ' GraphicsDesigner : required by GuiDesigner programs ' IMPORT "xui" ' GuiDesigner : required by GuiDesigner programs ' DECLARE FUNCTION Entry () DECLARE FUNCTION ProbarDirec () DECLARE FUNCTION SBYTE Matriz (SSHORT X, SSHORT Y) DECLARE FUNCTION RecorrerInversoEImprimir (SSHORT X, SSHORT Y) DECLARE FUNCTION MostrarSolucion (S$) DECLARE FUNCTION SSHORT Cargarsolucion () SHARED SBYTE VengoDe[64] ' ' ' ###################### ' ##### Entry () ##### ' ###################### ' ' Programs contain: ' 1. A PROLOG with type/function/constant declarations. ' 2. This Entry() function where execution begins. ' 3. Zero or more additional functions. ' FUNCTION Entry () SHARED SBYTE VengoDe[64] SHARED SBYTE MovimientoX[7] SHARED SBYTE MovimientoY[7] AUTO SBYTE X AUTO SBYTE Y AUTO SBYTE NextX AUTO SBYTE NextY SHARED SBYTE Puntero MovimientoY[0]=-2:MovimientoX[0]=1 MovimientoY[1]=-1:MovimientoX[1]=2 MovimientoY[2]=1:MovimientoX[2]=2 MovimientoY[3]=2:MovimientoX[3]=1 MovimientoY[4]=2:MovimientoX[4]=-1 MovimientoY[5]=1:MovimientoX[5]=-2 MovimientoY[6]=-1:MovimientoX[6]=-2 MovimientoY[7]=-2:MovimientoX[7]=-1 VengoDe[0]=-1 'Idea: 'Avanzar uno a uno las direcciones; ' Direccion=0 ' Probar si las coordenadas para la Direccion estan en el mapa. ' Si se sale del mapa, saltar al final del bucle: Direccion=Direccion+1 ' Probar si las coordenadas llevan a una casilla despejada (vengode=0) ' Si ocupada (>=0), saltar al final del bucle: Direccion=Direccion+1 ' Si despejada (=-3), ' X=X+DireccionX ' Y=Y+DireccionY ' VengoDe[X,Y]=direccion. ' Avanzar el puntero de direcciones. Comprobar que sea < 64. ' Si es 64, recorrer hacia atras e imprimir. ' Volver al inicio del bucle, con direccion=0 'FIN DEL BUCLE (Direccion=Direccion+1) ' Si hemos llegado a 8 ' Tomar VengoDe y Marcar casilla actual como libre 'Volver hacia atras usando (VengoDe+4 MOD 8) 'Reducir el puntero de direcciones. '1-Marcar casillas como libres. FOR F=0 TO 64 VengoDe[F]=-3 NEXT F 'Recuperar soluciones antiguas--esto permite ejecutar el programa por lotes. SI$=INLINE$("Desea cargar soluciones antiguas desde fichero (S/N)?") RESP=0 DO WHILE RESP=0 IF (UCASE$(SI$)="S") OR (UCASE$(SI$)="Y") THEN RESP=1 IF UCASE$(SI$)="N" THEN RESP=-1 LOOP IF RESP=1 THEN R=Cargarsolucion() IF R<>-1 THEN X=R MOD 8 Y=INT(R / 8) GOTO RecienCargado END IF END IF 'Inicializar variables Puntero=0 X=0 Y=0 'Bucle principal DO NextX=X+MovimientoX[Direccion] NextY=Y+MovimientoY[Direccion] ' Probar si las coordenadas para la Direccion son validas ' Si despejada (=-3), Mat=Matriz(NextX,NextY) 'PRINT SPACE$(Puntero+1)+STRING$(Direccion)+"["+STRING$(Puntero)+"]" IF Mat=-3 THEN X=NextX Y=NextY VengoDe[Y*8+X]=Direccion Direccion=0 Puntero=Puntero+1 'Tras cargar una solucion antigua venimos aqu RecienCargado: IF Puntero=63 THEN RecorrerInversoEImprimir(X,Y) GOSUB Retroceso END IF ELSE Direccion=Direccion+1 DO WHILE Direccion>=8 GOSUB Retroceso LOOP END IF LOOP SUB Retroceso VengoDesde=Matriz(X,Y) VengoDe[Y*8+X]=-3 'Si vengodesde contiene un valor ilegal, probablemente hemos terminado. IF VengoDesde<0 THEN EXIT FUNCTION 'Si puntero es -1, probablemente hemos terminado. Puntero=Puntero-1 IF Puntero<0 THEN EXIT FUNCTION X=X+MovimientoX[(VengoDesde+4) MOD 8] Y=Y+MovimientoY[(VengoDesde+4) MOD 8] Direccion=VengoDesde+1 END SUB END FUNCTION ' ' ' ############################ ' ##### ProbarDirec () ##### ' ############################ ' FUNCTION ProbarDirec () SHARED SBYTE MovimientoX[] SHARED SBYTE MovimientoY[] FOR f=0 TO 7 FOR g=-2 TO 2 Q$="|" FOR h=-2 TO 2 IF (h=MovimientoX[f]) AND (g=MovimientoY[f]) THEN Q$=Q$+"*" ELSE IF (h=0) AND (g=0) THEN Q$=Q$+"X" ELSE IF (h=MovimientoX[(f+4) MOD 8]) AND (g=MovimientoY[(f+4) MOD 8]) THEN Q$=Q$+"@" ELSE Q$=Q$+" " END IF END IF END IF Q$=Q$+"|" NEXT h PRINT Q$ Q$="-" FOR h=-2 TO 2 Q$=Q$+"--" NEXT PRINT Q$ NEXT g PRINT PRINT f X$=INLINE$(X$) NEXT f END FUNCTION ' ' ' ####################### ' ##### Matriz () ##### ' ####################### ' FUNCTION SBYTE Matriz (SSHORT X, SSHORT Y) SHARED SBYTE VengoDe[] IF X<0 THEN RETURN -2 IF X>=8 THEN RETURN -2 IF Y<0 THEN RETURN -2 IF Y>=8 THEN RETURN -2 'PRINT Y*8+X;"=>"; 'PRINT VengoDe[Y*8+X] RETURN (VengoDe[Y*8+X]) END FUNCTION ' ' ' ######################################### ' ##### RecorrerInversoEImprimir () ##### ' ######################################### ' FUNCTION RecorrerInversoEImprimir (SSHORT X, SSHORT Y) SHARED SBYTE MovimientoX[] SHARED SBYTE MovimientoY[] ofile=OPEN ("SALTOSCABALLO.TXT",$$RW) SEEK (ofile,LOF(ofile)) P$="" Direc=Matriz(X,Y) DO WHILE Direc>=0 P$=STR$(Direc)+P$ X=X+MovimientoX[(Direc+4) MOD 8] Y=Y+MovimientoY[(Direc+4) MOD 8] Direc=Matriz(X,Y) LOOP PRINT P$ PRINT [ofile],P$ CLOSE (ofile) ' Des-comentar para mostrar la solucion en un tablero. ' MostrarSolucion(Solu1$) END FUNCTION ' ' ' ################################ ' ##### MostrarSolucion () ##### ' ################################ ' FUNCTION MostrarSolucion (S$) SHARED SBYTE MovimientoX[] SHARED SBYTE MovimientoY[] SBYTE Mat[8,8] SBYTE Dir SBYTE X SBYTE Y UBYTE P Tablero$="" X=0:Y=0:P=0 FOR f=1 TO LEN(S$) STEP 2 Mat[X,Y]=P P=P+1 Dir=SBYTE(MID$(S$,f,2)) X=X+MovimientoX[Dir] Y=Y+MovimientoY[Dir] NEXT f Mat[X,Y]=P FOR X=0 TO 7 L1$="" L2$="" FOR Y=0 TO 7 L1$=L1$+RIGHT$(STR$(Mat[X,Y]),2)+"|" L2$=L2$+"---" NEXT Y Tablero$=Tablero$+L1$+"\n"+L2$+"\n" NEXT X PRINT Tablero$ END FUNCTION ' ' ' ############################### ' ##### Cargarsolucion () ##### ' ############################### ' FUNCTION USHORT Cargarsolucion () SHARED SBYTE VengoDe[] SHARED SBYTE MovimientoX[] SHARED SBYTE MovimientoY[] SBYTE Dir SHARED SBYTE Puntero AUTO SBYTE X AUTO SBYTE Y SSHORT ifile ifile=OPEN ("SALTOSCABALLO.TXT",$$RD) IF ifile=-1 THEN RETURN -1 longitud=LOF(ifile) IF longitud=0 THEN CLOSE (ifile) XstDeleteFile("SALTOSCABALLO.TXT") RETURN -1 END IF PRINT "RECUPERANDO ULTIMA POSICION DESDE FICHERO" Line1$="" DO Line2$=Line1$ Line1$=INFILE$(ifile) LOOP WHILE NOT EOF(ifile) X=0:Y=0:Dir=0:Puntero=0 FOR f=1 TO LEN(Line2$) STEP 2 IF Matriz(X,Y)<>-3 THEN PRINT "ERROR -- FICHERO O DATOS INVALIDOS" GOSUB VaciaTablero RETURN -1 END IF VengoDe[Y*8+X]=Dir Puntero=Puntero+1 Dir=SBYTE(MID$(Line2$,f,2)) X=X+MovimientoX[Dir] Y=Y+MovimientoY[Dir] NEXT f VengoDe[Y*8+X]=Dir PRINT "Datos cargados" RETURN Y*8+X SUB VaciaTablero FOR f=0 TO 63 VengoDe[f]=-3 NEXT f END SUB END FUNCTION END PROGRAM
'Probando el programa xbasic del salto del caballo. Direcciones: DATA 1,-2: '0 - a la una DATA 2,-1: '1 - a las dos DATA 2,1: '2 - a las cuatro DATA 1,2: '3 - a las cinco DATA -1,2: '4- a las siete DATA -2,1: '5- a las ocho DATA -2,-1: '6 - a las diez DATA -1,-2: '7- A las 11 Saltos: 'Importados desde saltoscaballo.txt generado por xbasic DATA 2,1,2,3,4,3,6,0: ' DATA 0,5,2,4,5,0,0,0: ' DATA 5,0,5,2,0,5,4,4: ' DATA 1,2,4,6,5,6,0,0: ' DATA 0,3,0,5,6,4,2,7: ' DATA 4,3,4,1,0,6,7,1: ' DATA 4,4,3,2,0,7,4,4: ' DATA 7,1,0,3,4,2,1: ' DIM movimientox(0 TO 7) DIM movimientoy(0 TO 7) RESTORE Direcciones FOR f = 0 TO 7 READ movimientox(f), movimientoy(f) NEXT CLS FOR x = 0 TO 7 FOR y = 0 TO 7 LOCATE y * 2 + 1, x * 3 + 1 PRINT " |" LOCATE y * 2 + 2, x * 3 + 1 PRINT "---" NEXT y NEXT x RESTORE Saltos x = 0: y = 0 FOR f = 0 TO 63 LOCATE y * 2 + 1, x * 3 + 1 PRINT USING "##|"; f LOCATE y * 2 + 2, x * 3 + 1 PRINT "---" IF f < 63 THEN READ salto x = x + movimientox(salto) y = y + movimientoy(salto) SLEEP 0 NEXT f