
Task

Play a game of tic-tac-toe.

Ensure that legal moves are played and that a winning position is notified.


Tic-tac-toe   is also known as:

   naughts and crosses 
   tic tac toe 
   tick tack toe 
   three in a row 
   tres en rayo       and
   Xs  and  Os


See also
   MathWorld™, Tic-Tac-Toe game.
   Wikipedia tic-tac-toe.


!--------------------------------------------
! TRIS.R : gioca a tris contro l'operatore
!--------------------------------------------

PROGRAM TRIS

DIM TRIS%[9],T1%[9],PIECES$[3]

!$SEGMENT=$B800

!$INCLUDE="PC.LIB"

PROCEDURE DELAY(COUNT%)
  FOR Z%=1 TO COUNT DO
  END FOR
END PROCEDURE

PROCEDURE SET_BOARD
!
! Disegna lo schema del gioco
!
  CLS
  BLOAD("TRIS.BLD",0)
!$KEY
END PROCEDURE

PROCEDURE PUT_PIECES
!
! Pone i pezzi sulla scacchiera
!
  Z%=0
  FOR ROW%=6 TO 12 STEP 3 DO     ! posizioni assolute sullo schermo
    FOR COL%=32 TO 48 STEP 8 DO
      LOCATE(ROW%+1,COL%+1)
      Z%=Z%+1
      PRINT(PIECES$[TRIS%[Z%]])
    END FOR
  END FOR
END PROCEDURE

PROCEDURE COMPUTE_MOVE(A%)
  CASE A% OF
    2-> C1%=C1%+1            END ->
    4-> C2%=C2%+1            END ->
    8-> S1%=TRUE  S2%=TRUE   END ->
    3-> N1%=N1%+1            END ->
    9-> N2%=N2%+1            END ->
   27-> S1%=FALSE S2%=FALSE  END ->
 END CASE
END PROCEDURE

PROCEDURE PREPAREMOVE(T1%[],I%->M%)
!
! Prepara la mossa del calcolatore
!
   T1%[I%]=2
   C1%=0
   C2%=0
   N1%=0
   N2%=0
   FOR K%=0 TO 2 DO
     COMPUTE_MOVE(T1%[3*K%+1]*T1%[3*K%+2]*T1%[3*K%+3])
     COMPUTE_MOVE(T1%[K%+1]*T1%[K%+4]*T1%[K%+7])
   END FOR
   COMPUTE_MOVE(T1%[1]*T1%[5]*T1%[9])
   COMPUTE_MOVE(T1%[3]*T1%[5]*T1%[7])
   M%=-63*N2%+31*C2%-15*N1%+7*C1%
END PROCEDURE

PROCEDURE COMPUTER_MOVE
!
! Coordina le mosse del calcolatore
!
  MAXSCORE%=-1000
  FOR I%=1 TO 9 DO
    IF TRIS%[I%]=1
      THEN
       PREPAREMOVE(TRIS%[],I%->MV%)
       EXIT IF S2% AND NOT S1%
       IF S1% AND S2%
         THEN
          TRIS%[I%]=2
          DIARY$=DIARY$+"c"+MID$(STR$(I%),2)+"*"
          PUT_PIECES
          EXIT
       END IF
       IF MV%=0
         THEN
          MOVE%=I%
          EXIT
       END IF
       IF MV%>MAXSCORE%
         THEN
          MOVE%=I%
          MAXSCORE%=MV%
       END IF
    END IF
  END FOR
  IF NOT S2%
    THEN
     TRIS%[MOVE%]=2
     DIARY$=DIARY$+"c"+MID$(STR$(MOVE%),2)+";"
     PUT_PIECES
     NMOVE%=NMOVE%-1
     S1%=(NMOVE%=0)
  END IF
END PROCEDURE

PROCEDURE PLAYER_MOVE
!
! Gioca l'avversario umano usando i tasti cursore per lo spostamento
!
  LOCATE(19,13)
  PRINT("Tocca a te ....                  ")
  REPEAT
    ROW%=7
    COL%=32
    LOCATE(ROW%+1,COL%+1)
    PRINT("Ü")
    REPEAT
      GET(B$)
      IF LEN(B$)=2 THEN
        CASE ASC(RIGHT$(B$,1)+CHR$(0)) OF
          77-> ! codice tastiera per CRSR =>
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             COL%=-(COL%+8)*(COL%<=40)-32*(COL%>40)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          75-> ! codice tastiera per CRSR <=
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             COL%=-(COL%-8)*(COL%>=40)-48*(COL%<40)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          80-> ! codice tastiera per CRSR DOWN
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             ROW%=-(ROW%+3)*(ROW%<=10)-7*(ROW%>10)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          72-> ! codice tastiera per CRSR UP
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             ROW%=-(ROW%-3)*(ROW%>=10)-13*(ROW%<10)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
       END CASE
      END IF
     UNTIL B$=CHR$(13)
     MM%=ROW%+COL%/8-10 ! da coordinate schermo a coordinate scacchiera
   UNTIL TRIS%[MM%]=1
  TRIS%[MM%]=3
  LOCATE(ROW%+1,COL%+1)
  PRINT(" ")
  DIARY$=DIARY$+"p"+MID$(STR$(MM%),2)+";"
  PUT_PIECES
  NMOVE%=NMOVE%-1
  S1%=(NMOVE%=0)
  LOCATE(19,13)
  PRINT(STRING$(45," "))
END PROCEDURE

BEGIN
  DATA(" ","+","o")
  SET_BOARD
  REPEAT
    S1%=FALSE    S2%=FALSE   ! determinano lo stato della partita
    NMOVE%=9
    FOR Z%=1 TO 3 DO
       READ(PIECES$[Z%])
    END FOR
    FOR Z%=1 TO 9 DO
        TRIS%[Z%]=1
    END FOR
    LOCATE(19,13)
    PRINT("Giochi per primo ?")
    REPEAT
      GET(A$)
    UNTIL A$="S" OR A$="s" OR A$="N" OR A$="n"
    PUT_PIECES
    FOR INDICE%=1 TO 9 DO
      IF A$="s" OR A$="S"
        THEN
          PLAYER_MOVE
          EXIT IF S1% OR S2%
          COMPUTER_MOVE
          EXIT IF S1% OR S2%
        ELSE
          COMPUTER_MOVE
          EXIT IF S1% OR S2%
          PLAYER_MOVE
          EXIT IF S1% OR S2%
      END IF
   END FOR
   LOCATE(19,13)
   CASE TRUE OF
     (S1% AND NOT S2%)->
        PRINT("E' finita pari !!!     ")
     END ->
     (S2% AND NOT S1%)->
        PRINT("HAI VINTO !!!          ")
     END ->
     (S1% AND S2%)->
        PRINT("HO VINTO IO !!!        ")
     END ->
   END CASE
   DELAY(500)
   LOCATE(19,13)
   PRINT(DIARY$)
   DELAY(500)
   LOCATE(19,13)
   PRINT("Vuoi giocare ancora ?       ")
   REPEAT
     GET(A$)
   UNTIL A$="S" OR A$="s" OR A$="N" OR A$="n"
 UNTIL A$="N" OR A$="n"
END PROGRAM
