A Tic-Tac-Toe board

This is a program to provide a board for two human players to use for the game of Tic-Tac-Toe.

It does not actualy play the game, but it does detect a victory, and it prints out some information at each move.

The board is represented as a 2-dimensional array of Character, and a 3-dimensional array of Integer is used to keep track of the various ways to have 3 in a row.


! This program provides a board for two humans to play the game of
! Tic-Tac-Toe.

Program Tictac2
  Implicit None
  Character :: Board(3, 3)
  Integer :: I, J, Row, Column, MoveX, MoveY
  Integer :: Counter = 1
  Character :: WhoseMove = 'X'
  Logical :: Win, WinInOne

  Integer :: Ways(8, 3, 2)

  Ways(1, 1, 1) = 1
  Ways(1, 1, 2) = 1
  Ways(1, 2, 1) = 1
  Ways(1, 2, 2) = 2
  Ways(1, 3, 1) = 1
  Ways(1, 3, 2) = 3

  Ways(2, 1, 1) = 2
  Ways(2, 1, 2) = 1
  Ways(2, 2, 1) = 2
  Ways(2, 2, 2) = 2
  Ways(2, 3, 1) = 2
  Ways(2, 3, 2) = 3

  Ways(3, 1, 1) = 3
  Ways(3, 1, 2) = 1
  Ways(3, 2, 1) = 3
  Ways(3, 2, 2) = 2
  Ways(3, 3, 1) = 3
  Ways(3, 3, 2) = 3

  Ways(4, 1, 1) = 1
  Ways(4, 1, 2) = 1
  Ways(4, 2, 1) = 2
  Ways(4, 2, 2) = 1
  Ways(4, 3, 1) = 3
  Ways(4, 3, 2) = 1

  Ways(5, 1, 1) = 1
  Ways(5, 1, 2) = 2
  Ways(5, 2, 1) = 2
  Ways(5, 2, 2) = 2
  Ways(5, 3, 1) = 3
  Ways(5, 3, 2) = 2

  Ways(6, 1, 1) = 1
  Ways(6, 1, 2) = 3
  Ways(6, 2, 1) = 2
  Ways(6, 2, 2) = 3
  Ways(6, 3, 1) = 3
  Ways(6, 3, 2) = 3

  Ways(7, 1, 1) = 1
  Ways(7, 1, 2) = 1
  Ways(7, 2, 1) = 2
  Ways(7, 2, 2) = 2
  Ways(7, 3, 1) = 3
  Ways(7, 3, 2) = 3

  Ways(8, 1, 1) = 1
  Ways(8, 1, 2) = 3
  Ways(8, 2, 1) = 2
  Ways(8, 2, 2) = 2
  Ways(8, 3, 1) = 3
  Ways(8, 3, 2) = 1

  Do I= 1, 3
    Do J = 1, 3
      Board(I, J) = ' '
    End Do
  End Do

40  Format(3A)
  Print 40, 'We are going to play Tic-Tac-Toe.'
  Print 40, 'Two human players can play X and O alternately.'

  Do While ((Counter < 10) .AND. (Win(Board, 'X', Ways) .Eqv. .False.) .AND. &
            (Win(Board, 'O', Ways) .Eqv. .False.))
    Call PrintBoard(Board)
    Print *

    If (Counter > 1) Then
50    Format(A, I1, A, I1, A)
      Print 50, 'The chosen move is at (', Row, ', ', Column, ').'
      Print 50, 'We will now make that move.'
    End If

    If (WinInOne(Board, 'X', Ways, MoveX, MoveY)) Then
100   Format(1X, /, A, I1, A, I1, A) 
      Print 100, 'There is a win for X in 1 move at (', MoveX, &
               ', ', MoveY, ')'
    End If

    If (WinInOne(Board, 'O', Ways, MoveX, MoveY)) Then
      Print 100, 'There is a win for O in 1 move at (', MoveX, &
               ', ', MoveY, ')'
    End If

    If (Counter == 1) Then
      Print 40, 'What is the first move?  X moves first.'
    Else
      Print *
      Print 40, 'What is the next move for ', WhoseMove, '?'
    End If
    Print 40, 'Specify the row and column, each a number 1 to 3.'
    Read *, Row, Column

    Do While ((Row < 1) .Or. (Row > 3) .Or. (Column < 1) .Or. &
              (Column > 3) .Or. (Board(Row, Column) /= ' '))
      Print *, 'Try again.'  
      Read *, Row, Column
    End Do

    Board(Row, Column) = WhoseMove

    Counter = Counter + 1

    If (WhoseMove == 'X') Then
      WhoseMove = 'O'
    Else
      WhoseMove = 'X'
    End If

  End Do

  Print 50, 'The chosen move is at (', Row, ', ', Column, ').'
  Print 50, 'We will now make that move.'

  Print *
  Print 40, 'The final position is:'
  Call PrintBoard(Board)

  If ((Win(Board, 'X', Ways)) .Or. (Win(Board, 'O', Ways))) Then
    Print 40, 'We have a winner!'
  Else
    Print 40, 'There is no winner.'
  End If

End Program Tictac2


! This subroutine prints the current state of the board.
Subroutine PrintBoard(B)
    Implicit None
    Character :: B(3, 3)
    Integer :: I

    Print *
100 Format(T21, A)
    Print 100, 'Columns'
110 Format(T18, A1, T24, A1, T30, A1)
    Print 110, '1', '2', '3'
    Print *
120 Format(T16, A17)
    Print 120, '     |     |     '
    Do I = 1, 3
130   Format(T8, A3, 1X, I1, T18, A1, T21, A1, T24, A1, &
             T27, A1, T30, A1)
      Print 130, 'Row', I, B(I, 1), '|', B(I, 2), &
                 '|', B(I,3)
      If (I < 3) Then
        Print 120, '     |     |     '
        Print 120, '-----+-----+-----'
      End If
      Print 120, '     |     |     '
    End Do
End Subroutine

! This function returns .True. if the Player has won the game and
! returns .False. otherwise.
Logical Function Win(B, Player, Ways)
  Implicit None
  Character :: B(3, 3)
  Character :: Player
  Logical :: FoundWin = .False.
  Integer :: Ways(8, 3, 2)
  Integer :: I
                 
  I = 1
  Do While ((I <= 8) .AND. (FoundWin .EQV. .False.))
    If ((B(Ways(I, 1, 1), Ways(I, 1, 2)) == Player) .AND. &
        (B(Ways(I, 2, 1), Ways(I, 2, 2)) == Player) .AND. &
        (B(Ways(I, 3, 1), Ways(I, 3, 2)) == Player)) FoundWin = .True.
    I = I + 1
  End Do

  Win = FoundWin

End Function Win

Logical Function WinInOne(B, Player, Ways, MoveX, MoveY)
  Implicit None
  Character :: B(3, 3)
  Character :: Player
  Integer :: Ways(8, 3, 2), MoveX, MoveY
  Integer :: I

  MoveX = 0
  MoveY = 0

  I = 1

  Do While ((I <= 8) .AND. (MoveX == 0) .AND. (MoveY == 0))

    If ((B(Ways(I, 1, 1), Ways(I, 1, 2)) == Player) .AND. &
        (B(Ways(I, 2, 1), Ways(I, 2, 2)) == Player) .AND. &
        (B(Ways(I, 3, 1), Ways(I, 3, 2)) == ' ')) Then
      MoveX = Ways(I, 3, 1)
      MoveY = Ways(I, 3, 2)
    Else
      If ((B(Ways(I, 2, 1), Ways(I, 2, 2)) == Player) .AND. &
          (B(Ways(I, 3, 1), Ways(I, 3, 2)) == Player) .AND. &
          (B(Ways(I, 1, 1), Ways(I, 1, 2)) == ' ')) Then
        MoveX = Ways(I, 1, 1)
        MoveY = Ways(I, 1, 2)
      Else
        If ((B(Ways(I, 3, 1), Ways(I, 3, 2)) == Player) .AND. &
            (B(Ways(I, 1, 1), Ways(I, 1, 2)) == Player) .AND. &
            (B(Ways(I, 2, 1), Ways(I, 2, 2)) == ' ')) Then
          MoveX = Ways(I, 2, 1)
          MoveY = Ways(I, 2, 2)
        End If
      End If
    End If

    I = I + 1

  End Do
         
  WinInOne = ((MoveX /= 0) .AND. (MoveY /= 0))

End Function WinInOne


What does the board look like?

Here is the output from a sample run of the program.

We are going to play Tic-Tac-Toe.
Two human players can play X and O alternately.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2        |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |     |   
                    |     |     

What is the first move?  X moves first.
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2        |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |   
                    |     |     

The chosen move is at (3, 2).
We will now make that move.

What is the next move for O?
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |   
                    |     |     

The chosen move is at (2, 1).
We will now make that move.

What is the next move for X?
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |  X
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |   
                    |     |     

The chosen move is at (1, 3).
We will now make that move.

What is the next move for O?
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |  X
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |     |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |  O
                    |     |     

The chosen move is at (3, 3).
We will now make that move.

What is the next move for X?
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |     |  X
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |  X  |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |  O
                    |     |     

The chosen move is at (2, 2).
We will now make that move.

There is a win for X in 1 move at (1, 2)

What is the next move for O?
Specify the row and column, each a number 1 to 3.

                    Columns
                 1     2     3

                    |     |     
       Row 1        |  O  |  X
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |  X  |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3        |  X  |  O
                    |     |     

The chosen move is at (1, 2).
We will now make that move.

There is a win for X in 1 move at (3, 1)

What is the next move for X?
Specify the row and column, each a number 1 to 3.
The chosen move is at (3, 1).
We will now make that move.

The final position is:

                    Columns
                 1     2     3

                    |     |     
       Row 1        |  O  |  X
                    |     |     
               -----+-----+-----
                    |     |     
       Row 2     O  |  X  |   
                    |     |     
               -----+-----+-----
                    |     |     
       Row 3     X  |  X  |  O
                    |     |     
We have a winner!