Overview







Sudoku is a number puzzle game, played on a nine by nine cell grid. Within that grid there are nine sub-regions consisting of three cells by three cells. In this version there are three levels of difficulty, which are Most clues, Medium clues, and Least clues.

Most clues gives you five random numbers from each nine cell horizontal row.
Medium clues gives you four random numbers from each nine cell horizontal row.
Least clues gives you three random numbers from each nine cell horizontal row.

The object of the game is to fill the remaining cells with the integers one to nine. But each horizontal row can only contain one instance of each integer, and each vertical row can only contain one instance of each integer. There is also the further added constraint that each sub-region can also only contain one instance of each integer.

In a new game, the given numbers (clues) are rendered in red text. The numbers that you enter are rendered in black text. There is a Solution button, which when clicked, reveals the correct answer to the puzzle. Any numbers that you have added that are correctly placed, remain rendered with black text. Any cells that were empty or had an incorrect integer will display the correct integer rendered in blue text.

You have won the game if after clicking the Solution button all of the numbers are rendered in either black or red text.




Core Game class



The Game class is used throughout the duration of the application. It is the core of the application, where each new Sudoku puzzle is created.
Communication from the Game class to the GUI is via two custom Events...
It contains two Public methods, the NewGame method, and the showGridSolution method. These are the methods used to communicate with the class from the GUI.

Public Class Game
 
    Public Event ShowClues(ByVal grid()() As Integer)
    Public Event ShowSolution(ByVal grid()() As Integer)
 
    Private HRow(8) As List(Of Integer)
    Private VRow(8) As List(Of Integer)
    Private ThreeSquare(8) As List(Of Integer)
    Private grid(8)() As Integer
 
    Private r As Random
 
    Public Sub NewGame(ByVal rn As Random)
        Me.r = rn
        createNewGame()
    End Sub
 
    Private Sub initializeLists()
        For x As Integer = 0 To 8
            HRow(x) = New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9})
            VRow(x) = New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9})
            ThreeSquare(x) = New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9})
            Dim row(8) As Integer
            grid(x) = row
        Next
    End Sub
 
    Private Sub createNewGame()
        Do
            initializeLists()
            For y As Integer = 0 To 8
                For x As Integer = 0 To 8
                    grid(y)(x) = Nothing
                    Dim si As Integer = (y \ 3) * 3 + (x \ 3)
                    Dim useful() As Integer = HRow(y).Intersect(VRow(x)).Intersect(ThreeSquare(si)).ToArray
                    If useful.Count = 0 Then Continue Do
                    Dim randomNumber As Integer = useful(r.Next(0, useful.Count))
                    HRow(y).Remove(randomNumber)
                    VRow(x).Remove(randomNumber)
                    ThreeSquare(si).Remove(randomNumber)
                    grid(y)(x) = randomNumber
                    If y = 8 And x = 8 Then Exit Do
                Next
            Next
        Loop
 
        RaiseEvent ShowClues(grid)
 
    End Sub
 
    Public Sub showGridSolution()
 
        RaiseEvent ShowSolution(grid)
 
    End Sub
 
End Class




The GUI Form



The Form handles all of the Events, from the Controls it contains, and also the two custom Events raised by the Game class.
Extra lines are drawn on the DataGridView to separate the sub-regions in the grid.


Public Class Form1
 
    Private WithEvents game As New Game
    Private r As New Random
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        DataGridView1.Rows.Add(9)
        ComboBox1.SelectedIndex = 0
        btnNew.PerformClick()
    End Sub
 
    Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click
        game.NewGame(r)
    End Sub
 
    Private Sub DataGridView1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles DataGridView1.Paint
        e.Graphics.DrawLine(New Pen(Color.Black, 2), 75, 0, 75, 228)
        e.Graphics.DrawLine(New Pen(Color.Black, 2), 150, 0, 150, 228)
        e.Graphics.DrawLine(New Pen(Color.Black, 2), 0, 66, 228, 66)
        e.Graphics.DrawLine(New Pen(Color.Black, 2), 0, 132, 228, 132)
    End Sub
 
    Private Sub btnSolution_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSolution.Click
        game.showGridSolution()
    End Sub
 
    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        btnNew.PerformClick()
    End Sub
 
    Public Sub game_ShowClues(ByVal grid()() As Integer) Handles game.ShowClues
        For y As Integer = 0 To 8
            Dim cells As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9})
            For c As Integer = 1 To 9 - (5 - ComboBox1.SelectedIndex)
                Dim randomNumber As Integer = cells(r.Next(0, cells.Count))
                cells.Remove(randomNumber)
            Next
            For x As Integer = 0 To 8
                If cells.Contains(x + 1) Then
                    DataGridView1.Rows(y).Cells(x).Value = grid(y)(x)
                    DataGridView1.Rows(y).Cells(x).Style.ForeColor = Color.Red
                    DataGridView1.Rows(y).Cells(x).ReadOnly = True
                Else
                    DataGridView1.Rows(y).Cells(x).Value = ""
                    DataGridView1.Rows(y).Cells(x).Style.ForeColor = Color.Black
                    DataGridView1.Rows(y).Cells(x).ReadOnly = False
                End If
            Next
        Next
    End Sub
 
    Public Sub game_ShowSolution(ByVal grid()() As Integer) Handles game.ShowSolution
        For y As Integer = 0 To 8
            For x As Integer = 0 To 8
                If DataGridView1.Rows(y).Cells(x).Style.ForeColor = Color.Black Then
                    If DataGridView1.Rows(y).Cells(x).Value.ToString = "" Then
                        DataGridView1.Rows(y).Cells(x).Style.ForeColor = Color.Blue
                        DataGridView1.Rows(y).Cells(x).Value = grid(y)(x)
                    Else
                        If grid(y)(x).ToString <> DataGridView1.Rows(y).Cells(x).Value.ToString Then
                            DataGridView1.Rows(y).Cells(x).Style.ForeColor = Color.Blue
                            DataGridView1.Rows(y).Cells(x).Value = grid(y)(x)
                        End If
                    End If
                End If
            Next
        Next
    End Sub
     
End Class




Conclusion



This example shows how easy it is to create a simple desktop game using either VB.Net, or C# (see this C# version). Modern computers are ideal for creating this type of game, with each new game being random and unique. Using OOP techniques and principles in this game, results in simple readable and orderly code.




Downloads



Download here (VB.Net / C#)



See also



C# version
Online JavaScript version



Articles related to game programming



VB.Net - Perspective
VB.Net - Vertex
VB.Net - WordSearch
VB.Net - MasterMind
VB.Net - OOP BlackJack
VB.Net - Numbers Game
VB.Net - HangMan
Console BlackJack - VB.Net | C#
TicTacToe - VB.Net | C#
OOP Conway's Game of Life - 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