Programming Tic-Tac-Toe In Visual Basic.NET

Written By: Kevin Jordan

- 10 Feb 2006 -

Description: We'll start by using the visual editor to set up our interface and take it all the way into programming the artificial intelligence of the computer opponent.

  1. Creating the User Interface
  2. Starting a Game and Making a Menu
  3. Programming the Game Logic
  4. An Intelligent Opponent

Programming the AI

The intelligence was probably the most difficult part of programming the game. You have to learn how to win at tic-tac-toe, every time. Since I decided that our program was going to have 3 different difficulty settings: easy, medium, and hard, I had to decide what strategy each of these opponents would use. For E-Z mode, the program will just place Xs randomly (not much strategy at all). For the mid-level difficulty, it'll be able to know when it's about to win and lose and play accordingly (this is how most people actually play tic-tac-toe). For hard difficulty, it'll know the best way to play during any situation. A draw with this opponent is considered a perfect game (this is how experts play).

Private Sub AIMove()
        Dim intRandomX As Integer = RandomNumber(3, 0)
        Dim intRandomY As Integer = RandomNumber(3, 0)
 
        Select Case intAIDifficulty
                Case Difficulty.Easy
 
                Case Difficulty.Medium
 
                Case Difficulty.Hard
 
        End Select
End Sub ' AIMove 

I created a subroutine with a case statement for each difficulty. Since Easy is going to be completely random I created a couple variables to store a random horizontal position and a random vertical position.

E-Z Mode

Public Function RandomNumber(ByVal MaxNumber _
As Integer, ByVal MinNumber As Integer)
        Dim r As New Random(System.DateTime.Now.Millisecond)
        Return r.Next(MinNumber, MaxNumber)
End Function ' RandomNumber 

Here's the RandomNumber function. It uses the built in random class to generate a value between the numbers supplied, in our case 0, 1, or 2.

While arrGrid(intRandomX, intRandomY) <> 0
        intRandomX = RandomNumber(3, 0)
        intRandomY = RandomNumber(3, 0)
End While
Call GridClick(intRandomX, intRandomY)

The easy strategy looks like this. It gets a random position over and over until a blank spot is found. The other difficulty settings will also use this strategy after the programmed intelligence is exhausted.

Programming An Intermediate Opponent

' Check to see if it can win
For i As Integer = 0 To 2
        For j As Integer = 0 To 2
                If arrGrid(i, j) = 0 Then
                        arrGrid(i, j) = 2
 
                        Call CheckWinLose()
                        If intWhosWinner = 2 Then
                                intWhosWinner = 0
                                arrGrid(i, j) = 0
                                GridClick(i, j)
                                Return
                        Else
                                arrGrid(i, j) = 0
                        End If
                End If
        Next
Next

The first thing the medium opponent should do is see if it has a chance to win. It accomplishes this by placing a hypothetical move for every open position on the board. It then calls the CheckWinLose subroutine. If the move results in a win then it goes ahead and takes that move, otherwise, it'll set that spot back to empty move to the next space.

' Check to see if it will lose
For i As Integer = 0 To 2
        For j As Integer = 0 To 2
                If arrGrid(i, j) = 0 Then
                        arrGrid(i, j) = 1
 
                        Call CheckWinLose()
                        If intWhosWinner = 1 Then
                                intWhosWinner = 0
                                arrGrid(i, j) = 0
                                GridClick(i, j)
                                Return
                        Else
                                intWhosWinner = 0
                                arrGrid(i, j) = 0
                        End If
                End If
        Next
Next

If it's not possible for the computer to win, then it'll need to make sure that it won't lose on the players next turn. It accomplishes this in much the same manner as when it checked for winning conditions. A hypothetical move is made, but this time as the player. If the player would win based on this move, then the computer will move there instead. If the computer opponent can't win or lose in the next move, then it'll just play randomly.

The Game That Knew Too Much

The hard difficulty is where it gets tough. I read a tic-tac-toe strategy manual (how lame is that) and found out that the game is decided in the first 4 moves, everything after that can be won (or tied) by playing like the medium difficulty opponent. So what I needed to do was count have many moves had been made. Based on this and the position of the Xs and Os, the program knows how to move accordingly.

Dim intSquaresUsed As Integer = 0
For i As Integer = 0 To 2
        For j As Integer = 0 To 2
                If arrGrid(i, j) <> 0 Then
                        intSquaresUsed += 1
                End If
        Next
Next
 
Select Case intSquaresUsed
        Case 0
        Case 1
        Case 2
        Case 3
        Case 4
        Case Is > 4
End Select

While I'm not going to go into all the possible moves (you can read the strategy guide if you're that interested), I'll cover the basic structure. First it'll go through each spot on the grid to see how many are filled. This will let us know what move the game is on and let us pick the appropriate strategy. After the fourth move, then it'll just play using the same strategy as the medium difficulty opponent.

The End

Put all this together and you've programmed a game that will be fun for almost five minutes. But hopefully you learned some useful Visual Basic.NET programming in the process.

<< Previous