Jonathan's Blog

Real Situations Solved in Visual Basic.NET and C#

Creating a Sudoku Program (Part 2)

Posted by Jonathan on August 9, 2010

In the last post, I explained how to draw the lines for a grid. Keep in mind we are currently building just one section of the sudoku puzzle; this is so we can learn to make reusable code.

On the designer portion of the custom control, I just dragged nine labels into the view. It’s kind of messy:

Nine labels for nine numbers.

There are probably a few different ways to store these numbers, but instead of declaring nine different integers, I declared one single string. To make the code bigger, press Ctrl+Scroll Mouse Wheel Up

Private _AllNumbers As String = "123456789"
Public ReadOnly Property AllNumbers As String
Get
Return _AllNumbers
End Get
End Property

The property is for exposure outside the control. The only manipulation of the numbers will come from inside the control, and will edit the string directly. Since every square will have a single digit as a value, I decided to use the string’s array behavior to my advantage. The number at position one will be _AllNumbers(0), the second will be at position (1) and so on. I could have used an integer array, but then I would have had to use initialization code, and besides, an integer is 32 bits in size, while a single character is 8 bits. The total size of a string is 80 bits, while an integer array would have been 320 bits.

Now we need to link the values in the string to the values of the labels. We also need to position the labels using the same technique we used to position the strings; this involves measuring Me.Width and Me.Height.

For this, I added a few more lines to the OnPaint() sub:

        For Each ctrl As Control In Me.Controls

            Dim indivLabel As Label = TryCast(ctrl, Label)

            If Not IsNothing(indivLabel) And ctrl.Name.StartsWith("lbl") Then ' I use "lbl" at the beginning of every label's name

                Dim mySize As New System.Drawing.SizeF

                Dim myFont As New System.Drawing.Font(indivLabel.Font.FontFamily, indivLabel.Font.Size)

                mySize = e.Graphics.MeasureString(indivLabel.Text, myFont)

                indivLabel.Width = CType(Math.Round(mySize.Width, 0), Integer)

            End If

        Next

        lblTopLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, firstVerticalLinePositionY / 2 - 7)

        lblTopMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, firstVerticalLinePositionY / 2 - 7)

        lblTopRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, firstVerticalLinePositionY / 2 - 7)

        lblMiddleLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)

        lblMiddleMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)

        lblMiddleRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)

        lblBottomLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, (secondVerticalLinePositionY + Me.Height) / 2 - 7)

        lblBottomMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, (secondVerticalLinePositionY + Me.Height) / 2 - 7)

        lblBottomRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, (secondVerticalLinePositionY + Me.Height) / 2 - 7)
If this code doesn't show on your monitor, you can download it from the link at the end of this post.  It checks the size of the text in
a given label, then resizes the label based on that. This is useful if you decide to change the font of the text, I don't think Courier New
is going to be suitable in all cases. The code that relocates the labels uses the variables that were declared to draw the lines. Every
label is located at the average of one line and the next, or in other words "the middle."
The code to link the value in _AllNumbers with  the labels is pretty straightforward:
lblTopLeft.Text = _AllNumbers(0)
lblTopMiddle.Text = _AllNumbers(1)
lblTopRight.Text = _AllNumbers(2)
lblMiddleLeft.Text = _AllNumbers(3)
lblMiddleMiddle.Text = _AllNumbers(4)
lblMiddleRight.Text = _AllNumbers(5)
lblBottomLeft.Text = _AllNumbers(6)
lblBottomMiddle.Text = _AllNumbers(7)
lblBottomRight.Text = _AllNumbers(8)
Here is what the application will look like when you build it:
In the next post, we will look at using event handlers to change the value of the number when you click on it. We also might start into some Sudoku logic to check if any number is repeated within the control.
As always, you can download the source code here.

Posted in Uncategorized | Leave a Comment »

Creating a Sudoku Program (Part 1)

Posted by Jonathan on August 8, 2010

I don’t know how many parts this post will be, but here goes:

I once thought of going to Brigham Young University. I spoke with one of the professors, and he told me I could test out of his first class if I could write a Sudoku program in C++. Nothing fancy, just some console application. I didn’t end up going, and never made it past three lines in the program.  I haven’t made anything in C++ since I was 15, and it was a simple “find prime numbers” program. I think nerds have this obsession with prime numbers.

I could make a prime numbers program in .NET, probably in my sleep. So I am going to try making a Sudoku program; comments on my code are welcome, as are questions.

If you want to look up the rules to Sudoku, go to http://en.wikipedia.org/wiki/Sudoku. I won’t try to explain them here.

The first part of my project is making a single set of nine squares, just one section of the bigger puzzle. I plan on making it self-contained, but in a way that the program can create nine of these independently and still be able to compare them together.

I made a custom control, by right-clicking in the solution explorer and selecting Add->New Item. I picked “Custom Control.”

My first problem was how to make it draw lines. As far as I could tell there was no “line” control that could be dragged from the toolbox. Here is what I came up with:

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
  Dim firstVerticalLinePositionY As Integer = Me.Height / 3
  Dim secondVerticalLinePositionY As Integer = Me.Height * 2 / 3
  Dim firstHorizontalLinePositionX As Integer = Me.Width / 3
  Dim secondHorizontalLinePositionX As Integer = Me.Width * 2 / 3
  Dim myPen As New System.Drawing.Pen(System.Drawing.Color.Black)
  Dim formGraphics As System.Drawing.Graphics
  formGraphics = Me.CreateGraphics()
  formGraphics.DrawLine(myPen, 0, firstVerticalLinePositionY, Me.Width, firstVerticalLinePositionY)
  formGraphics.DrawLine(myPen, 0, secondVerticalLinePositionY, Me.Width, secondVerticalLinePositionY)
  formGraphics.DrawLine(myPen, firstHorizontalLinePositionX, 0, firstHorizontalLinePositionX, Me.Height)
  formGraphics.DrawLine(myPen, secondHorizontalLinePositionX, 0, secondHorizontalLinePositionX, Me.Height)
  myPen.Dispose()
  formGraphics.Dispose()
………….and here it ends.

Did you see what I did? In .NET (Visual Basic OR C#) you need to create a Pen and a Graphics object. The Pen object is initialized by passing in the color, the graphics is first declared, then initialized by the procedure:

Me.CreateGraphics()

You see I also had four lines declaring the X and Y coordinates of the lines to be drawn. I wanted the lines to be drawn correctly no matter what size the control is, so I used Me.Width and Me.Height as benchmarks. It’s pretty straightforward what is done: Whenever the pen is used, you need a starting (X,Y), and an ending (X,Y). I misnamed the variables, the vertical line positions actually serve the horizontal lines, but the X and Y are there to clear up the confusion.

So all this trouble to draw four lines! I am a little farther than this, and you can download the files from mediafire by clicking on http://www.mediafire.com/?9p267n73mew9ms5. I will explain the rest in upcoming posts.

Posted in Uncategorized | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.