Microsoft & .NET.NETRandom Numbers and Tic Tac Toe with Visual Basic .NET

Random Numbers and Tic Tac Toe with Visual Basic .NET

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

If you are a little like I am you will be doing something with your computer even during the holidays. (More than likely I will be playing Red Alert 2 with the kids, but I may sneak in a little writing.) For you workaholics, I have included a little holiday fare. This way you will be able to do something constructive, yet be able to tear yourself away when company comes knocking on the door.

Random numbers are commonly employed in applications for a wide variety of reasons. In this week’s letter let’s take a quick look at the Random class in the Common Language Runtime.

The System Namespace

The System namespace is a root namespace in the Common Language Runtime (CLR). One of the classes in the System namespace is the Random class. (That’s right! Random numbers are encapsulated in a class in .NET.) Like VB6 random numbers are based on a mathematical algorithm from a finite set of numbers. The result is that you get pseudo-random numbers, but these numbers are random enough for many practical purposes (just not the lottery).

Random numbers in VB.NET can be initialized with or without a seed value and can be constrained to a range of numbers. If the same seed is used then the generated number sequence will be identical. A good strategy is to seed the random numbers using a unique value like the time. Table 1 describes the members of the Random class and is followed by some code examples demonstrating how to use the Random class.

Members of the System.Random class.

Member Name Description
New()
Constructs instance of Random Class.
New(ByVal Seed As Integer)
Constructs instance of Random class using Seed value.
Next() As Integer
Returns next integer in the random number sequence.
Next(ByVal maxValue As Integer) As Integer
Returns a positive integer less than maxValue.
Next(ByVal minValue As Integer,
ByVal maxValue As Integer) As Integer
Returns a number greater than or equal to minValue and less than or maxValue.
NextBytes(ByVal buffer() As Byte)
Returns an array of random bytes greater than or equal to 0 and less than Byte.MaxValue.
NextDouble() As Double
Returns a random Double between 0.0 and 1.0.

The basic use of the Random class is to create an instance of the class and use the Random.Next method to acquire subsequent random numbers. You do not have to re-create the Random object each time you want a random number. The following fragments demonstrate several examples of creating Random objects and getting random numbers.

The first example creates a Random object and displays the first random number in a message box.

Dim R As New Random()
MsgBox(R.Next().ToString())

The second example creates an instance of the Random class with a seed value of 100.

Dim R As New Random(100)
Dim I As Integer = R.Next()

The third example creates a Random object, seeding the object from a time-related value and requests a number between 1 and 100, excluding the value 100.

Dim R As New Random(Now.Millisecond)
R.Next(1, 100)

A simple Tic-Tac-Toe game is provided in the listing below, providing some more examples of using the Random class.

TicTacToe: Random Number Example

In keeping with the theme of this article, listing 1 contains a prototype of a Tic-Tac-Toe game (see figure). Just in case someone has forgotten, Tic-Tac-Toe is a simple game where players alternate turns, each player marking an empty square until all squares are marked or someone has three consecutive horizontal, vertical, or diagonal squares marked. If no player has three consecutive squares then the game is a Cats game.

The code is all implemented in a Windows application on a form. The computer player is as random as it can be (so everyone has a really good chance of winning).

Figure 1: Tic-Tac-Toe against a Random computer player.

Listing 1: Computer uses Random numbers to determine where to place “O”.

1:  Public Class Form1
2:      Inherits System.Windows.Forms.Form
3:  
4:  [ Windows Form Designer generated code ]
5:  
6:    Private Sub Button2_Click(ByVal sender As System.Object, _
7:    ByVal e As System.EventArgs) Handles Button2.Click
8:    Close()
9:   End Sub
10: 
11:  Private Sub Initialize()
12: 
13:   Dim I As Integer
14:   For I = 0 To Me.Controls.Count - 1
15:    If (TypeOf Controls(I) Is Label) Then
16:     Dim L As Label = Controls(I)
17:     If (L.Tag <> Nothing) Then
18:      L.Text = ""
19:      Squares(L.Tag) = L
20:     End If
21:    End If
22:   Next
23: 
24:  End Sub
25: 
26:  Private Random As System.Random
27:  Private Turns As Integer = 0
28:  Private Squares(8) As Label
29:  Private UserTurn As Boolean = False
30: 
31:  Private Sub NewGame()
32: 
33:   Static UserFirst As Boolean = False
34:   UserFirst = Not UserFirst
35:   Initialize()
36:   Random = New Random(Now.Millisecond)
37:   Turns = 0
38: 
39:   If (UserFirst) Then
40:    UserTurn = True
41:   Else
42:    UserTurn = False
43:    ComputerTurn()
44:   End If
45:  End Sub
46: 
47:  Private Sub Button1_Click(ByVal sender As System.Object, _
48:   ByVal e As System.EventArgs) Handles Button1.Click
49:   NewGame()
50:  End Sub
51: 
52: 
53:  Private Sub Form1_Load(ByVal sender As System.Object, _
54:   ByVal e As System.EventArgs) Handles MyBase.Load
55: 
56:   NewGame()
57: 
58:  End Sub
59: 
60:  Private Sub Label9_Click(ByVal sender As System.Object, _
61:   ByVal e As System.EventArgs) Handles Label1.Click, _
62:   Label2.Click, Label3.Click, Label4.Click, Label5.Click, _
63:   Label6.Click, Label7.Click, Label8.Click, Label9.Click
64: 
65:   If (Not UserTurn Or IsGameOver()) Then Exit Sub
66: 
67:   With CType(sender, Label)
68:    If (.Text = "") Then
69:     .Text = "X"
70:     Turns += 1
71: 
72:     If (Not IsGameOver()) Then
73:      UserTurn = False
74:      ComputerTurn()
75:     End If
76:    Else
77:     Beep()
78:    End If
79:   End With
80: 
81: 
82:  End Sub
83: 
84:  Private Function TakeTurn(ByVal Turn As Integer) As Boolean
85:   If (Squares(Turn).Text = "") Then
86:    Squares(Turn).Text = "O"
87:    Return True
88:   Else
89:    Return False
90:   End If
91:  End Function
92: 
93:  Private Sub ComputerTurn()
94:   Dim Turn As Integer = Random.Next(0, 9)
95: 
96:   While (True)
97:    If (TakeTurn(Turn)) Then Exit While
98:    Application.DoEvents()
99:    Turn = Random.Next(1, 9)
100:   End While
101: 
102:   Turns += 1
103:   IsGameOver()
104:   UserTurn = True
105: 
106:  End Sub
107: 
108:  Private Overloads Function SquaresEqual( _
109:   ByVal First As Integer, _
110:   ByVal Second As Integer, _
111:   ByVal Third As Integer) As Boolean
112: 
113:   Return Squares(First).Text = Squares(Second).Text _
114:    And Squares(Second).Text = Squares(Third).Text _
115:    And Squares(First).Text <> ""
116: 
117:  End Function
118: 
119:  Private Overloads Function SquaresEqual(ByVal First As Integer, _
120:   ByVal Second As Integer, ByVal Third As Integer, _
121:   ByRef Value As String) As Boolean
122: 
123: 
124:   Dim Result As Boolean
125:   Result = SquaresEqual(First, Second, Third)
126: 
127:   If (Result) Then
128:    Value = Squares(First).Text
129:   End If
130: 
131:   Return Result
132:  End Function
133: 
134: 
135:  Private Function IsWinner( _
136:   Optional ByRef Value As String = "") As Boolean
137: 
138:   Return SquaresEqual(0, 1, 2, Value) Or _
139:     SquaresEqual(0, 3, 6, Value) Or _
140:     SquaresEqual(0, 4, 8, Value) Or _
141:     SquaresEqual(1, 4, 7, Value) Or _
142:     SquaresEqual(2, 5, 8, Value) Or _
143:     SquaresEqual(2, 4, 6, Value) Or _
144:     SquaresEqual(3, 4, 5, Value) Or _
145:     SquaresEqual(6, 7, 8, Value)
146: 
147:  End Function
148: 
149:  Private Sub ScoreGame()
150:   Dim Value As String = ""
151:   If (IsWinner(Value)) Then
152:    MsgBox(Value & " is the winner!")
153:   Else
154:    MsgBox("Cats Game!")
155:   End If
156:  End Sub
157: 
158:  Private Function IsGameOver() As Boolean
159: 
160:   If (Turns >= 9 Or IsWinner()) Then
161:    ScoreGame()
162:    Return True
163:   Else
164:    Return False
165:   End If
166: 
167:  End Function
168: 
169: End Class

Line 26 declares an uninitialized Random member named Random. Line 36 constructs a Random object, seeding with the number of milliseconds for the current time value, every time a new game is started. Line 94 requests a random number between 0 and 9, including 0 and excluding 9. This represents the 9 possible spaces on the Tic-Tac-Toe board. Line 94 is included in the ComputerTurn method. The computer tries random numbers between 0 and 9 until it finds an empty square to place it’s O. After each player’s turn the game checks to see if the game is over. If all squares are marked or a player has won then the game is scored.

About the Author


Paul Kimmel is a freelance writer for Developer.com and CodeGuru.com. Look for cool Visual Basic .Net topics in his upcoming book Visual Basic .Net Unleashed available in January of 2002.

Paul founded Software Conceptions, Inc. in 1990. Contact Paul Kimmel at pkimmel@softconcepts.com for help building VB.NET applications or migrating VB6 applications to .NET.

# # #

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories