Tic-Tac-Toe

10  REM A BASIC program to play Tic-Tac-Toe.
20  REM Copyright 2012 by Stephen Beitzel sbeitzel@pobox.com
30  REM Released under the Perl Artistic License 2.0
40  REM See http://www.perlfoundation.org/artistic_license_2_0
50  REM Set up the board
51  GOSUB 200
60  REM Display the board
61  GOSUB 500
65  REM Choose who goes first
66  GOSUB 300
67  p = 1
70  REM If game is over, print the game over message
71  GOSUB 5000
72  IF w = 1 OR w = 2 THEN
73  PRINT "Player ";w;" wins!"
74  GOTO 120
75  END IF
76  IF os = 0 THEN
77  PRINT "It's a tie!"
78  GOTO 120
79  END IF
80  REM Get move from the current player
81  IF p = cp THEN
82  GOSUB 2000
83  ELSE
84  GOSUB 1000
85  END IF
90  REM 1) record the move, 2) switch current player
91  board%(m) = p
92  p = 3 - p
100 REM Display the board
110 GOSUB 500
115 GOTO 70
120 PRINT "Game over!"
130 END
200 REM Subroutine to set up the board
210 DIM board%(8)
220 LOCAL i
230 FOR i=0 TO 8
240 board%(i) = 0
250 NEXT i
260 RETURN
300 REM Subroutine to choose whether the computer goes first or second
310 PRINT "Does the computer go first or second? To have the computer"
311 PRINT "go first, type a '1'. To have the computer go second, type"
312 PRINT "a '2'."
313 input cp$
320 IF left$(cp$,1)="1" THEN
330 cp = 1
340 ELSE
350 cp = 2
360 END IF
370 RETURN
500 REM Subroutine to draw the board
510 PRINT ""
520 PRINT "  A   B   C "
530 LOCAL i, line$
540 FOR i=1 to 3
550 line$ = str$(i)+" "
560 for j=0 to 2
565 x = (i-1)*3 + j
570 if (board%(x) = 0) then
580 line$ = line$+"  "
590 ELSE
600 IF (board%(x) = 1) THEN
610 line$ = line$+"X "
620 ELSE
630 line$ = line$+"O "
640 END IF
650 END IF
660 IF j < 2 THEN
670 line$ = line$+"| "
680 END IF
690 NEXT j
700 PRINT line$
710 IF i < 3 THEN
720 PRINT " ---+---+---"
730 END IF
740 NEXT i
750 PRINT ""
760 RETURN
1000 REM Get a move from the keyboard
1004 PRINT "Choose a spot. Specify the column first and then the row"
1005 input m$
1010 m$ = lcase$(m$)
1020 REM m$ will be of the form /[abc][123]/
1030 c$ = left$(m$,1)
1035 r$ = mid$(m$, 2, 1)
1040 IF r$ = "1" THEN
1050 i = 0
1060 ELSE
1070 IF r$ = "2" THEN
1080 i=1
1090 ELSE
1100 IF r$ = '3' THEN i=2 ELSE i=9
1110 END IF
1120 END IF
1130 IF c$ = "a" THEN
1140 j = 0
1150 ELSE
1160 IF c$ = "b" THEN
1170 j = 1
1180 ELSE
1190 IF c$ = "c" THEN j = 2 ELSE j = 9
1200 END IF
1210 END IF
1230 m = (i*3)+j
1240 REM We need to be sure it's a legal move before we return.
1250 IF m < 0 OR m > 8 THEN 1260
1255 IF (board%(m) <> 0) THEN 1260
1256 RETURN
1260 PRINT "That is not a valid spot. Please try again."
1270 GOTO 1005
2000 REM The computer chooses a move
2001 REM First, look to see if we're about to win. If so, play to win.
2002 DIM wins(8, 3)
2010 wins(1, 1) = 0
2011 wins(1, 2) = 1
2012 wins(1, 3) = 2
2013 wins(2, 1) = 3
2014 wins(2, 2) = 4
2015 wins(2, 3) = 5
2016 wins(3, 1) = 6
2017 wins(3, 2) = 7
2018 wins(3, 3) = 8
2019 wins(4, 1) = 0
2020 wins(4, 2) = 3
2021 wins(4, 3) = 6
2022 wins(5, 1) = 1
2023 wins(5, 2) = 4
2024 wins(5, 3) = 7
2025 wins(6, 1) = 2
2026 wins(6, 2) = 5
2027 wins(6, 3) = 8
2028 wins(7, 1) = 0
2029 wins(7, 2) = 4
2030 wins(7, 3) = 8
2031 wins(8, 1) = 2
2032 wins(8, 2) = 4
2033 wins(8, 3) = 6
2040 FOR w=1 to 8
2050 ix = checkForWin(cp, wins(w, 1), wins(w, 2), wins(w, 3))
2060 IF ix <> -1
2070 m = wins%(w, ix)
2080 RETURN
2090 EXIT FOR
2100 END IF
2110 NEXT w
2351 REM Next, look to see if the opponent is about to win. If so, we need to play to block.
2360 FOR w=1 to 8
2370 ix = checkForWin(3-cp, wins(w, 1), wins(w, 2), wins(w, 3))
2380 IF ix <> -1
2390 m = wins(w, ix)
2400 RETURN
2410 EXIT FOR
2420 END IF
2430 NEXT w
2800 REM Finally, play in an open square. Center, corners, sides
2810 IF board%(4) = 0
2811 m = 4
2812 RETURN
2813 END IF
2820 IF board%(0) = 0
2821 m = 0
2822 RETURN
2823 END IF
2830 IF board%(8) = 0
2831 m = 8
2832 RETURN
2833 END IF
2840 IF board%(6) = 0
2841 m = 6
2842 RETURN
2843 END IF
2850 IF board%(2) = 0
2851 m = 2
2852 RETURN
2853 END IF
2860 IF board%(1) = 0
2861 m = 1
2862 RETURN
2863 END IF
2870 IF board%(3) = 0
2871 m = 3
2872 RETURN
2873 END IF
2880 IF board%(5) = 0
2881 m = 5
2882 RETURN
2883 END IF
2890 IF board%(7) = 0
2891 m = 7
2892 RETURN
2893 END IF
2999 RETURN
4000 SUB checkForWin( player, a, b, c)
4001 REM If two of the three values are marked by player and the third value is unmarked
4002 REM then return the index of the unmarked value (1, 2, or 3). If not, return -1.
4010 rv = -1
4020 IF board%(a)=board%(b) AND board%(a)=player AND board%(c)=0 THEN
4021 rv = 3
4022 GOTO 4990
4025 END IF
4030 IF board%(a)=board%(c) AND board%(a)=player AND board%(b)=0 THEN
4031 rv = 2
4032 GOTO 4990
4035 END IF
4040 IF board%(b)=board%(c) AND board%(b)=player AND board%(a)=0 THEN
4041 rv = 1
4042 GOTO 4990
4045 END IF
4990 checkForWin = rv 
4999 END SUB
5000 REM Subroutine to analyze the board. If there are no moves available
5001 REM or if one player has won, then go to the "game over" line,
5002 REM otherwise we just return.
5005 os = 0
5010 FOR i=0 to 8
5020 IF board%(i) = 0 THEN os = 1
5030 NEXT i
5040 IF os THEN
5050 REM there is at least one open spot. Check for a win.
5051 REM There are only 8 possible wins.
5060 w = 0
5070 if (board%(0) = board%(1) and board%(1) = board%(2) and board%(0) <> 0) THEN w = board%(0)
5075 if w <> 0 then return
5080 if (board%(3) = board%(4) and board%(4) = board%(5) and board%(3) <> 0) THEN w = board%(3)
5085 if w <> 0 then return
5090 if (board%(6) = board%(7) and board%(7) = board%(8) and board%(6) <> 0) THEN w = board%(6)
5095 if w <> 0 then return
5100 if (board%(0) = board%(3) and board%(3) = board%(6) and board%(0) <> 0) THEN w = board%(0)
5105 if w <> 0 then return
5110 if (board%(1) = board%(4) and board%(4) = board%(7) and board%(1) <> 0) THEN w = board%(1)
5115 if w <> 0 then return
5120 if (board%(2) = board%(5) and board%(5) = board%(8) and board%(2) <> 0) THEN w = board%(2)
5125 if w <> 0 then return
5130 if (board%(0) = board%(4) and board%(4) = board%(8) and board%(0) <> 0) THEN w = board%(0)
5135 if w <> 0 then return
5140 if (board%(2) = board%(4) and board%(4) = board%(6) and board%(2) <> 0) THEN w = board%(2)
5145 if w <> 0 then return
5150 END IF
5160 REM If we're here, it means that there's no winner and there is an open spot.
5170 RETURN

One thought on “Tic-Tac-Toe

Leave a Reply