다음을 통해 공유


VB.Net - OOP Sudoku


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


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
VB.Net - Totris