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.
- Creating the User Interface
- Starting a Game and Making a Menu
- Programming the Game Logic
- 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.