Apagada docs

Aprendiendo a programar el pasado

Herramientas de usuario

Herramientas del sitio


en:basic:gwbasic:tic-tac-toe

Tic-tac-toe in basic (Gwbasic, qbasic and qb64 compatible)

Tic-tac-toe is a game with a simple logic; there are winner and loser positions. This is the reason I felt myself able to make an “AI player” able to play against a human player.

Robot strategy

The “brain” of the robot is in 400-750, an can be split in two parts:

  • First, (lines 440-460), computer “sums” the number of pieces in each row. The position of each tile in each row has been previously obtained from DATA instructions in lines 1000-1080 and stored in the LINEAS (=“ROWS”) matrix. The first dimension represents number of row (up to eight possible rows in the nine tiles board), the second position represents the tile (first, middle or last) in the row, and the third differences between X and Y coordinates.
  • Second, computer “raises” or “lowers” the value of each tile according to the number of pieces on its row:
    • If there are two computer pieces, (-2), the empty tile in the row get a high value (+85), since “winning” is better than “avoiding to lose”.
    • If there are two human pieces (2), the empty tile gets a high value (+21), so we “avoid to lose”.
    • If there is a computer piece and no human piece in the row (-1), the value given to the tile is high (+5), but not so high to choose a tile were we have three different choices to put the second piece of our row instead of stop a real threat from human player.
    • Last, if there is a lonely human piece in a row, the value of the tiles around it is lowered, (-1), but not so much to hide a real threat from near rows with has two human pieces.

Examples: (O=human, X=computer)

A B C
1 O -1 X
2 -1 O X
3 -1 -1 106
  • C3 gets 85+21+0=106, since C1..C3 vertical row has two computer pieces (+85), there is a human threat in the diagonal line (+21), and no pieces on the horizontal row.
A B C
1 O 4 X
2 O X 5
3 105 O 4
  • A3 gets 85+21-1=105, since diagonal row has two computer pieces (+85), there is a human threat in the A1:A3 vertical line (+21), and there is a lonely human piece the A3:C3 horizontal row.
  • C2 gets 5+0=5. Vertical row C1:C2 has a lonely computer piece (+5), and there are both a human and a computer piece (+0) in the horizontal row A2:C2.
  • C3 gets 5-1=0. It is the same vertical row as C2, but the presence of a lonely human in horizontal row A3:C3 is reducing its value (-1).
tictactoe.bas
5 RANDOMIZE VAL(MID$(TIME$, 7))
10 REM ***** Tic-tac-toe ***** 
20 CLS: SCREEN 1
30 DIM BOARD(3, 3): DIM TILEVALUE(3, 3)
40 DIM ROWS(8, 3, 2): DIM BESTMOVE(9, 2)
50 RESTORE 1000
60 FOR A = 1 TO 8: FOR B = 1 TO 3
70 READ ROWS(A, B, 1), ROWS(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 ***** Beginning of game ***** 
110 TURNS = 0
120 VIEW PRINT 16 TO 24: CLS 2: GOTO 5000
200 REM ***** Human moves ***** 
210 VIEW PRINT 16 TO 24: CLS 2
220 LOCATE 16, 1: INPUT "Where do you want to move? (Use letter for column, number for row)"; A$
230 IF LEN(A$) <> 2 THEN PRINT "Invalid coordinates": 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 "Please input a valid column: from A to 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 "Please input a valid row: from 1 to 3.": GOTO 210
300 Y = VAL(A2$)
310 IF BOARD(X, Y) <> 0 THEN PRINT "Tile is already full.": GOTO 210
320 PLAYER = 1: GOSUB 2000
330 BOARD(X, Y) = 1
340 GOSUB 3000
350 TURNS = TURNS + 1: IF TURNS >= 9 THEN GOTO 4010
400 REM ***** Computer moves *****
410 REM ***** Row appraisal *****
420 FOR F=1 TO 3:FOR G=1 TO 3:TILEVALUE(F,G)=0:NEXT :NEXT
430 FOR A=1 TO 8:FULLLINE=0
440 FOR B=1 TO 3
450 FULLLINE=FULLLINE+BOARD(ROWS(A,B,1),ROWS(A,B,2))
460 NEXT
470 FOR B=1 TO 3
480 XL=ROWS(A,B,1):YL=ROWS(A,B,2)
490 IF FULLLINE=1 THEN TILEVALUE(XL,YL)=TILEVALUE(XL,YL)+1
500 IF FULLLINE=-1 THEN TILEVALUE(XL,YL)=TILEVALUE(XL,YL)+5
510 IF FULLLINE=2 THEN TILEVALUE(XL,YL)=TILEVALUE(XL,YL)+21
520 IF FULLLINE=-2 THEN TILEVALUE(XL,YL)=TILEVALUE(XL,YL)+85
530 NEXT
540 NEXT
550 MAXIMUM=0:FOR A=1 TO 3:FOR B=1 TO 3
560 IF BOARD(A,B)<>0 THEN TILEVALUE(A,B)=-1
570 IF TILEVALUE(A,B)>MAXIMUM THEN MAXIMUM=TILEVALUE(A,B)
580 NEXT :NEXT
590 BESTCOUNT=0
600 FOR A=1 TO 3:FOR B=1 TO 3
610 IF TILEVALUE(A,B)=MAXIMUM THEN BESTCOUNT=BESTCOUNT+1:BESTMOVE(BESTCOUNT,1)=A:BESTMOVE(BESTCOUNT,2)=B
620 NEXT :NEXT
630 MYMOVE=INT(RND*BESTCOUNT-1)+1
640 IF MYMOVE=0 THEN PRINT "ERROR: MYMOVE=0":MYMOVE=1
650 IF MYMOVE>9 THEN PRINT "ERROR: MYMOVE>9":MYMOVE=9
660 X=BESTMOVE(MYMOVE,1)
670 Y=BESTMOVE(MYMOVE,2)
680 IF MAXIMUM<=4 AND BOARD(2,2)=0 THEN X=2:Y=2
690 PRINT "My move:";CHR$(ASC("A")+X-1);Y
700 IF BOARD(X,Y)<>0 THEN PRINT "Tile already full":GOTO 630
710 PLAYER =2 :GOSUB 2000
720 BOARD(X,Y)=-1
730 GOSUB 3000
740 TURNS=TURNS+1:IF TURNS>=9 THEN GOTO 4010
750 GOTO 210
1000 REM Store data for the 9 possible rows
1010 DATA 1,1,1,2,1,3: REM row 1 
1020 DATA 2,1,2,2,2,3: REM row 2 
1030 DATA 3,1,3,2,3,3: REM row 3 
1040 DATA 1,1,2,1,3,1: REM column 1 
1050 DATA 1,2,2,2,3,2: REM column 2 
1060 DATA 1,3,2,3,3,3: REM column 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 Draw cross or circle
2010 IF PLAYER = 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 ***** Three in a row? ***** 
3010 FOR A = 1 TO 8
    3020 FULLLINE = 0: FOR B = 1 TO 3
        3030 FULLLINE = FULLLINE + BOARD(ROWS(A, B, 1), ROWS(A, B, 2))
    3040 NEXT
    3050 IF FULLLINE = 3 THEN PRINT "Tic tac toe! You won!": GOTO 4010
    3060 IF FULLLINE = -3 THEN PRINT "Tic tac toe! I won!": GOTO 4010
3070 NEXT
3080 RETURN
4000 REM ***** Play again? ***** 
4010 INPUT "Do you want to play again?"; A$
4020 IF MID$(A$, 1, 1) = "Y" OR MID$(A$, 1, 1) = "y" THEN RUN
4030 IF MID$(A$, 1, 1) = "N" OR MID$(A$, 1, 1) = "n" THEN END
4040 PRINT "Please input 'Y' for 'yes', 'N' for 'no'": GOTO 4010
5000 REM ***** Decide starting player ***** 
5010 INPUT "1- I start     2- You start"; 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
en/basic/gwbasic/tic-tac-toe.txt · Última modificación: 2018/01/04 08:16 por nepenthes