Overview

 


Tictactoe (also known as noughts and crosses) is a two player game, in this case you versus your computer. In this version there are no levels of difficulty, and it is very tough to beat.
I originally wrote this game in Java, but I decided to convert it to C# and then to VB.Net, to share it here on MSDN. The Java code is very similar to very simple C#, so it was fairly easily converted, but it is simple C# (and VB), containing no LINQ, and as such it will, within my knowledge, work in any version of VS from 2005-13 (and probably earlier too).
To play, you just click a cell. When it is the computer’s turn to play, the game grid is strategically assessed and each cell is assigned a priority value according to its strategic value in the game. After rating all of the cells, the computer plays either the highest rated cell, or in the case of jointly rated cells, a random cell chosen from the joint highest rated cells. The used cells will never be chosen in this decision making algorithm as they are always assigned a rating of -1 which will always make them the lowest rated cells.
This has been a fun program to write, and converting between languages always leads to greater understanding and programming knowledge.












The code –The Form

 


The form code is very simple. Just a Button_Click event is handled...

 



Public Class game
  
    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        Grid1.newGame()
    End Sub
  
End Class

 
 

The code – cell Class


 
The cell Class is again very simple, just holding 3 member variables...
 






Public Class cell
    Public display As Char = " "c
    Public color As Color = Color.Black
    Public priority As Integer = -1
End Class

 
 


The code –grid Class

 



The grid Class inherits from Panel – it is an extended Panel. It holds some Class level variables that are used throughout the Class during game play...
 


Private matrix As cell()() = New cell(2)() {}
Private first As Char = "X"c
Private current As Char = "X"c
Private gameOver As Boolean = False
Private moveCounter As Integer = 0

 


Sub new sets the size of the Panel and initializes the matrix array...



 
Public Sub New()
    Me.Size = New Size(210, 210)
    For r As Integer = 0 To 2
        matrix(r) = New cell(2) {}
    Next
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            matrix(r)(c) = New cell()
            matrix(r)(c).display = " "c
            matrix(r)(c).color = Color.Black
        Next
    Next
End Sub

 


There are two overridden events handled in the extended Panel Class. These are the MouseClick event and the Paint event...
 



Protected Overrides Sub OnMouseClick(e As System.Windows.Forms.MouseEventArgs)
    If Not gameOver Then
        Dim r As Integer = CInt(Math.Floor(CDbl(e.Y) / 70))
        Dim c As Integer = CInt(Math.Floor(CDbl(e.X) / 70))
        If matrix(r)(c).display = " "c Then
            matrix(r)(c).display = current
            current = "0"c
            Me.Invalidate()
            moveCounter += 1
            gameOver = checkLines()
            If Not gameOver AndAlso moveCounter < 9 Then
                playMove()
                moveCounter += 1
            End If
        End If
    End If
    MyBase.OnMouseClick(e)
End Sub
  
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(e)
    e.Graphics.DrawLine(Pens.Black, 70, 0, 70, 210)
    e.Graphics.DrawLine(Pens.Black, 140, 0, 140, 210)
    e.Graphics.DrawLine(Pens.Black, 0, 70, 210, 70)
    e.Graphics.DrawLine(Pens.Black, 0, 140, 210, 140)
  
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            If matrix(r)(c).display <> " "c Then
                e.Graphics.DrawString(matrix(r)(c).display.ToString(), New Font("Times New Roman", 20, FontStyle.Bold), New SolidBrush(matrix(r)(c).color), CSng((c * 70) + 25), CSng((r * 70) + 25))
            End If
        Next
    Next
End Sub



 
The newGame procedure resets the Class level variables for a new game...



 
Public Sub newGame()
    gameOver = False
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            matrix(r)(c).display = " "c
            matrix(r)(c).color = Color.Black
        Next
    Next
    first = If((first = "X"c), "0"c, "X"c)
    current = first
    Me.Invalidate()
    moveCounter = 0
    If current = "0"c Then
        playMove()
    End If
End Sub

 
 

The playMove procedure is the AI part of this program, where the computer chooses its move...

 


Public Sub playMove()
  
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            If matrix(r)(c).display = " "c Then
                matrix(r)(c).priority = 0
            Else
                matrix(r)(c).priority = -1
            End If
        Next
    Next
  
    If matrix(1)(1).display = " "c Then
        matrix(1)(1).priority = 2
    End If
    If matrix(0)(0).display = " "c Then
        matrix(0)(0).priority = 1
    End If
    If matrix(0)(2).display = " "c Then
        matrix(0)(2).priority = 1
    End If
    If matrix(2)(0).display = " "c Then
        matrix(2)(0).priority = 1
    End If
    If matrix(2)(2).display = " "c Then
        matrix(2)(2).priority = 1
    End If
  
    For r As Integer = 0 To 2
        If matrix(r)(0).display <> " "c AndAlso matrix(r)(0).display = matrix(r)(1).display AndAlso matrix(r)(2).display = " "c Then
            matrix(r)(2).priority += 3
        End If
        If matrix(r)(0).display <> " "c AndAlso matrix(r)(0).display = matrix(r)(2).display AndAlso matrix(r)(1).display = " "c Then
            matrix(r)(1).priority += 3
        End If
        If matrix(r)(1).display <> " "c AndAlso matrix(r)(1).display = matrix(r)(2).display AndAlso matrix(r)(0).display = " "c Then
            matrix(r)(0).priority += 3
        End If
    Next
    For c As Integer = 0 To 2
        If matrix(0)(c).display <> " "c AndAlso matrix(0)(c).display = matrix(1)(c).display AndAlso matrix(2)(c).display = " "c Then
            matrix(2)(c).priority += 3
        End If
        If matrix(0)(c).display <> " "c AndAlso matrix(0)(c).display = matrix(2)(c).display AndAlso matrix(1)(c).display = " "c Then
            matrix(1)(c).priority += 3
        End If
        If matrix(1)(c).display <> " "c AndAlso matrix(1)(c).display = matrix(2)(c).display AndAlso matrix(0)(c).display = " "c Then
            matrix(0)(c).priority += 3
        End If
    Next
  
    If matrix(0)(0).display <> " "c AndAlso matrix(0)(0).display = matrix(1)(1).display AndAlso matrix(2)(2).display = " "c Then
        matrix(2)(2).priority += 3
    End If
    If matrix(0)(0).display <> " "c AndAlso matrix(0)(0).display = matrix(2)(2).display AndAlso matrix(1)(1).display = " "c Then
        matrix(1)(1).priority += 3
    End If
    If matrix(1)(1).display <> " "c AndAlso matrix(1)(1).display = matrix(2)(2).display AndAlso matrix(0)(0).display = " "c Then
        matrix(0)(0).priority += 3
    End If
    If matrix(0)(2).display <> " "c AndAlso matrix(0)(2).display = matrix(1)(1).display AndAlso matrix(2)(0).display = " "c Then
        matrix(2)(0).priority += 3
    End If
    If matrix(0)(2).display <> " "c AndAlso matrix(0)(2).display = matrix(2)(0).display AndAlso matrix(1)(1).display = " "c Then
        matrix(1)(1).priority += 3
    End If
    If matrix(1)(1).display <> " "c AndAlso matrix(1)(1).display = matrix(2)(0).display AndAlso matrix(0)(2).display = " "c Then
        matrix(0)(2).priority += 3
    End If
  
    'int maxC=-1;
    Dim maxC As New List(Of Integer)()
    'int maxR=-1;
    Dim maxR As New List(Of Integer)()
    Dim maxPriority As Integer = -1
  
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            If matrix(r)(c).priority > maxPriority Then
                maxPriority = matrix(r)(c).priority
            End If
        Next
    Next
  
    For r As Integer = 0 To 2
        For c As Integer = 0 To 2
            If matrix(r)(c).priority = maxPriority Then
                maxC.Add(c)
                maxR.Add(r)
            End If
        Next
    Next
  
    Dim rnd As New Random()
    Dim index As Integer = rnd.[Next](maxC.Count())
  
    matrix(maxR(index))(maxC(index)).display = "0"c
    current = "X"c
    gameOver = checkLines()
    Me.Invalidate()
End Sub

 


Finally the checkLines  Function, which checks for a win in any of the eight possible lines.
This returns a Boolean True or False depending on the state of play. Also any winning line is highlighted with red text...

 



Public Function checkLines() As Boolean
    For r As Integer = 0 To 2
        If matrix(r)(0).display <> " "c AndAlso matrix(r)(0).display = matrix(r)(1).display AndAlso matrix(r)(0).display = matrix(r)(2).display Then
            matrix(r)(0).color = Color.Red
            matrix(r)(1).color = Color.Red
            matrix(r)(2).color = Color.Red
            Return True
        End If
    Next
    For c As Integer = 0 To 2
        If matrix(0)(c).display <> " "c AndAlso matrix(0)(c).display = matrix(1)(c).display AndAlso matrix(0)(c).display = matrix(2)(c).display Then
            matrix(0)(c).color = Color.Red
            matrix(1)(c).color = Color.Red
            matrix(2)(c).color = Color.Red
            Return True
        End If
    Next
    If matrix(0)(0).display <> " "c AndAlso matrix(0)(0).display = matrix(1)(1).display AndAlso matrix(0)(0).display = matrix(2)(2).display Then
        matrix(0)(0).color = Color.Red
        matrix(1)(1).color = Color.Red
        matrix(2)(2).color = Color.Red
        Return True
    End If
    If matrix(0)(2).display <> " "c AndAlso matrix(0)(2).display = matrix(1)(1).display AndAlso matrix(0)(2).display = matrix(2)(0).display Then
        matrix(0)(2).color = Color.Red
        matrix(1)(1).color = Color.Red
        matrix(2)(0).color = Color.Red
        Return True
    End If
    Return False
End Function




See Also

Download: here
C# 2013 version​
Play online



Articles related to game programming



VB.Net - WordSearch
VB.Net - Vertex
VB.Net - Perspective
VB.Net - MasterMind
VB.Net - OOP BlackJack
VB.Net - Numbers Game
VB.Net - HangMan
Console BlackJack - VB.Net | C#
OOP Conway's Game of Life - VB.Net | C#
OOP Sudoku - VB.Net | C#
OctoWords VB.Net | C#
OOP Buttons Guessing Game VB.Net | C#
OOP Tangram Shapes Game VB.Net | C#
VB.Net - Three-card Monte
VB.Net - Split Decisions
VB.Net - Pascal's Pyramid
VB.Net - Random Maze Games
(Office) Wordsearch Creator
VB.Net - Event Driven Programming - LockWords Game
C# - Crack the Lock
VB.Net - Totris