Apagada docs

Aprendiendo a programar el pasado

Herramientas de usuario

Herramientas del sitio


es:basic:gwbasic:3enraya

Tres en raya para basic (Gwbasic, compatible con qbasic y qb64)

El tres en raya es un juego cuyo análisis es muy simple; por eso fue uno de los primeros (y casi el único) para los que me sentí capaz de elaborar un “autómata” capaz de jugar contra el humano.

Estrategia del jugador robot

El “cerebro” del juego, en las líneas 400-750, se puede dividir en dos partes:

  • En primer lugar (líneas 440-460), el ordenador “suma” el número de piezas en cada una de las líneas. La ubicación de cada una de las tres casillas de cada línea ha sido previamente recuperada de unas instrucciones DATA en 1000-1080 y almacenada en la matriz LINEAS. La primera dimensión representa el número de línea (ocho en total), la segunda indica la casilla (primera, segunda o tercera) de la línea y la tercera indica si estamos pidiendo la coordenada X o Y.
  • En segundo lugar, el ordenador “sube” o “baja” el valor de cada casilla de la línea según el número de piezas en la línea:
    • Si hay dos piezas del ordenador (-2), se asigna un valor muy alto (+85) a las casillas de la línea, pues “ganar” es mejor que “evitar perder”.
    • Si hay dos piezas del humano (2), se asigna un valor alto (+21), para que “evitemos perder”.
    • Si hay una pieza nuestra, y ninguna del humano, en la línea, (-1), se asigna un valor alto (+5), pero no tanto como para que una pieza con tres líneas vacías a su alrededor valga más que una amenaza real del jugador humano.
    • Por último, si hay una pieza del humano aislada en una línea, reducimos el valor de esa casilla (-1), pero no tanto como para disimular una amenaza real en esa casilla.

Ejemplos prácticos (O=humano, X=ordenador)

A B C
1 O -1 X
2 -1 O X
3 -1 -1 106
  • C3 vale 85+21+0=106, porque la columna C1..C3 tiene dos fichas del ordenador (+85), hay una amenaza humana en la diagonal (+21), y no hay fichas en la fila C3:C3 .
A B C
1 O 4 X
2 O X 5
3 105 O 4
  • A3 vale 85+21-1=105, porque la línea diagonal tiene dos fichas del ordenador (+85), hay una amenaza human en la columna A1:A3 (+21), y hay la fila horizontal A3:C3 solo está ocupada por una ficha humana.
  • C2 vale 5+0=5. La columna C1:C2 tiene solo una ficha del ordenador (+5), y hay tanto una ficha del ordenador como una humana en la fila A2:C2 (+0).
  • C3 vale 5-1=0. Está en la misma columna que C2 (+5), pero la presencia de una pieza humana solitaria en la fila A3:C3 reduce su valor (-1).

Nota: este archivo usa la página de códigos 850, “MS-DOS Europeo occidental”.

3enraya_bas_cp850.txt
5 RANDOMIZE VAL(MID$(TIME$, 7))
10 REM ***** Tres en raya ***** 
20 CLS: SCREEN 1
30 DIM TABLERO(3, 3): DIM VALORCASILLA(3, 3)
40 DIM LINEAS(8, 3, 2): DIM MEJORMOVIMIENTO(9, 2)
50 RESTORE 1000
60 FOR A = 1 TO 8: FOR B = 1 TO 3
70 READ LINEAS(A, B, 1), LINEAS(A, B, 2)
80 NEXT: NEXT
90 LINE (150, 20)-(150, 80): LINE (170, 20)-(170, 80): LINE (130, 40)-(190, 40): LINE (190, 60)-(130, 60)
100 REM ***** Inicio del juego ***** 
110 MOVIMIENTOS = 0
120 VIEW PRINT 16 TO 24: CLS 2: GOTO 5000
200 REM ***** Movimiento del jugador humano ***** 
210 VIEW PRINT 16 TO 24: CLS 2
220 LOCATE 16, 1: INPUT "¨D¢nde mueves? (Se¤ala con una letra la columna)"; A$
230 IF LEN(A$) <> 2 THEN PRINT "Coordenadas no v lidas": GOTO 210
240 A1$ = MID$(A$, 1, 1)
250 IF A1$ > "Z" THEN A1$ = CHR$(ASC(A1$) - 32)
260 IF A1$ > "C" OR A1$ < "A" THEN PRINT "Coordenadas horizontales v lidas de A a C": GOTO 210
270 X = ASC(A1$) + 1 - ASC("A")
280 A2$ = MID$(A$, 2, 1)
290 IF A2$ < "1" OR A2$ > "3" THEN PRINT "Coordenadas verticales v lidas de 1 a 3": GOTO 210
300 Y = VAL(A2$)
310 IF TABLERO(X, Y) <> 0 THEN PRINT "La casilla est  ocupada": GOTO 210
320 JUGADOR = 1: GOSUB 2000
330 TABLERO(X, Y) = 1
340 GOSUB 3000
350 MOVIMIENTOS = MOVIMIENTOS + 1: IF MOVIMIENTOS >= 9 THEN GOTO 4010
400 REM ***** movimiento del ordenador *****
410 REM ***** Valoración de las líneas *****
420 FOR F=1 TO 3:FOR G=1 TO 3:VALORCASILLA(F,G)=0:NEXT :NEXT
430 FOR A=1 TO 8:LINLLENA=0
440 FOR B=1 TO 3
450 LINLLENA=LINLLENA+TABLERO(LINEAS(A,B,1),LINEAS(A,B,2))
460 NEXT
470 FOR B=1 TO 3
480 XL=LINEAS(A,B,1):YL=LINEAS(A,B,2)
490 IF LINLLENA=1 THEN VALORCASILLA(XL,YL)=VALORCASILLA(XL,YL)+1
500 IF LINLLENA=-1 THEN VALORCASILLA(XL,YL)=VALORCASILLA(XL,YL)+5
510 IF LINLLENA=2 THEN VALORCASILLA(XL,YL)=VALORCASILLA(XL,YL)+21
520 IF LINLLENA=-2 THEN VALORCASILLA(XL,YL)=VALORCASILLA(XL,YL)+85
530 NEXT
540 NEXT
550 MAXIMO=0:FOR A=1 TO 3:FOR B=1 TO 3
560 IF TABLERO(A,B)<>0 THEN VALORCASILLA(A,B)=-1
570 IF VALORCASILLA(A,B)>MAXIMO THEN MAXIMO=VALORCASILLA(A,B)
580 NEXT :NEXT
590 NUMMEJORES=0
600 FOR A=1 TO 3:FOR B=1 TO 3
610 IF VALORCASILLA(A,B)=MAXIMO THEN NUMMEJORES=NUMMEJORES+1:MEJORMOVIMIENTO(NUMMEJORES,1)=A:MEJORMOVIMIENTO(NUMMEJORES,2)=B
620 NEXT :NEXT
630 MOVIMIENTO=INT(RND*NUMMEJORES-1)+1
640 IF MOVIMIENTO=0 THEN PRINT"ERROR: Movimiento=0":MOVIMIENTO=1
650 IF MOVIMIENTO>9 THEN PRINT"ERROR: Movimiento>9":MOVIMIENTO=9
660 X=MEJORMOVIMIENTO(MOVIMIENTO,1)
670 Y=MEJORMOVIMIENTO(MOVIMIENTO,2)
680 IF MAXIMO<=4 AND TABLERO(2,2)=0 THEN X=2:Y=2
690 PRINT"Mi movimiento: ";CHR$(ASC("A")+X-1);Y
700 IF TABLERO(X,Y)<>0 THEN PRINT"Casilla ocupada":GOTO 630
710 JUGADOR =2 :GOSUB 2000
720 TABLERO(X,Y)=-1
730 GOSUB 3000
740 MOVIMIENTOS=MOVIMIENTOS+1:IF MOVIMIENTOS>=9 THEN GOTO 4010
750 GOTO 210
1000 REM datos de las lineas posibles 
1010 DATA 1,1,1,2,1,3: REM horiz. 1 
1020 DATA 2,1,2,2,2,3: REM horiz. 2 
1030 DATA 3,1,3,2,3,3: REM horiz. 3 
1040 DATA 1,1,2,1,3,1: REM vert. 1 
1050 DATA 1,2,2,2,3,2: REM vert. 2 
1060 DATA 1,3,2,3,3,3: REM vert. 3 
1070 DATA 1,1,2,2,3,3: REM diag. 1 
1080 DATA 3,1,2,2,1,3: REM diag. 2 
2000 REM poner cruz/poner circulo 
2010 IF JUGADOR = 1 THEN GOTO 2040
2020 CIRCLE (120 + 20 * X, 10 + 20 * Y), 10, 1
2030 RETURN
2040 LINE (110 + 20 * X, 20 * Y)-(130 + 20 * X, 20 + 20 * Y), 2
2050 LINE (110 + 20 * X, 20 + 20 * Y)-(130 + 20 * X, 20 * Y), 2
2060 RETURN
3000 REM ***** ¨Es tres en raya? ***** 
3010 FOR A = 1 TO 8
    3020 LINLLENA = 0: FOR B = 1 TO 3
        3030 LINLLENA = LINLLENA + TABLERO(LINEAS(A, B, 1), LINEAS(A, B, 2))
    3040 NEXT
    3050 IF LINLLENA = 3 THEN PRINT "Haces tres en raya": GOTO 4010
    3060 IF LINLLENA = -3 THEN PRINT "Hago tres en raya": GOTO 4010
3070 NEXT
3080 RETURN
4000 REM ***** ¨Volver a jugar? ***** 
4010 INPUT "¨Quieres volver a jugar?"; A$
4020 IF MID$(A$, 1, 1) = "S" OR MID$(A$, 1, 1) = "s" THEN RUN
4030 IF MID$(A$, 1, 1) = "N" OR MID$(A$, 1, 1) = "n" THEN END
4040 PRINT "Responde 'S' o 'N'": GOTO 4010
5000 REM ***** Decidir qui‚n comienza ***** 
5010 INPUT "1- Comienzo yo     2- Comienzas t£"; N
5020 IF N = 1 THEN GOTO 400
5030 IF N = 2 THEN GOTO 200
5040 GOTO 5000
Este sitio web utiliza cookies. Al utilizar el sitio web, usted acepta almacenar cookies en su computadora. También reconoce que ha leído y entendido nuestra Política de privacidad. Si no está de acuerdo abandone el sitio web.Más información
es/basic/gwbasic/3enraya.txt · Última modificación: 2018/01/04 08:27 por nepenthes