Vb.Net - Hidden words
Overview
This is a word find game. All of the words used are eight to ten characters in length. The clues are (eight to ten) national flags. Identify the nation from its flag, and that will give you one letter in the word you're searching for. If you can't identify a flag, you can either guess the remaining letters in the word you're searching for, or right click the flag for assistance with identifying the flag.
The GUI consists of a Form, two Buttons, a DataGridView, ten PictureBoxes, a ContextMenuStrip, and ten Labels...
The Game Class
The Game Class contains one Public Method and two Private Functions, which are used to fit between eight and ten nation names, centred in a 35 column by 10 row String array. As the random number of countries are selected in the newGame method, the flag is displayed in the correct PictureBox, and the cell address for the label is recorded in another array.
These two arrays are all of the information the GUI needs to render the DataGridView for a new game.
The newGame Sub-procedure
This is the only Public method in the Game Class. The two Functions are helper methods...
Public Sub newGame(ByVal r As Random, ByVal wordLength As Integer, ByVal words() As String,
ByRef wordToFind As String, ByRef column As Integer, ByVal flagnames() As String,
ByVal gridArray(,) As String, ByVal pictureboxes() As PictureBox, ByVal labelIndices() As Integer)
Dim subset() As String = words.Where(Function(s) s.Length = wordLength).ToArray
wordToFind = subset(r. Next (0, subset.Length))
column = r. Next (6, 28)
Dim countriesUsed(wordLength - 1) As String
Dim indexUsed(wordLength - 1) As Integer
nearX = 35
farX = 0
Do
ReDim countriesUsed(wordLength - 1)
For y2 = 0 To wordLength - 1
Dim tempLetter As String = wordToFind(y2)
Dim tempColumn As Integer = column
Dim countries() As String = flagnames.Where(Function(c) isFit(c, tempLetter, tempColumn) And Not countriesUsed.Contains(c)).ToArray
If countries.Length = 0 Then Continue Do
Dim chosen As String = countries(r.Next(0, countries.Length))
indexUsed(y2) = -1
fitCountryClue(r, chosen, wordToFind(y2), column, y2, False , indexUsed(y2), pictureboxes, gridArray)
countriesUsed(y2) = chosen
If y2 = wordLength - 1 Then Exit Do
Next
Loop
Dim half As Integer = (nearX + (34 - farX)) \ 2
If nearX >= half Then
column -= (nearX - half)
ElseIf farX >= half Then
column += ((34 - farX) - half)
End If
For x2 As Integer = 0 To 34
For y2 = 0 To 9
gridArray(x2, y2) = ""
Next
Next
For y2 = 0 To wordLength - 1
Dim chosen As String = countriesUsed(y2)
labelIndices(y2) = fitCountryClue(r, chosen, wordToFind(y2), column, y2, True , indexUsed(y2), pictureboxes, gridArray)
Next
End Sub
The isFit Function
This is used within a Lambda Function to get an array of all countries which could be used at that row in the array.
Private Function isFit(ByVal country As String, ByVal letter As String, ByVal insertAt As Integer) As Boolean
Dim indices As New List(Of Integer)
For x As Integer = 0 To country.Length - 1
If country(x) = letter Then
indices.Add(x)
End If
Next
Return indices.Where(Function(x) insertAt - x > 0 And insertAt + (country.Length - x) <= 34).Count > 0
End Function
The fitCountryClue Function
This is used to find the best fit in the array. Country names often have more than one instance of a character, and the first instance isn't always the instance placed within the hidden word in this game.
Private Function fitCountryClue(ByVal r As Random, ByVal country As String, ByVal letter As String, ByVal insertAt As Integer,
ByVal row As Integer, ByVal doLabels As Boolean, ByRef indexUsed As Integer, ByVal pictureboxes() As
PictureBox, ByVal gridArray(,) As String) As Integer
Dim indices As New List(Of Integer)
For x As Integer = 0 To country.Length - 1
If country(x) = letter Then
If insertAt - x > 0 And insertAt + (country.Length - x) <= 34 Then
indices.Add(x)
End If
End If
Next
If indexUsed = -1 Then
indexUsed = indices(r. Next (0, indices.Count))
pictureboxes(row).Image = DirectCast (My.Resources.ResourceManager.GetObject(country), Bitmap)
End If
Dim startIndex As Integer = insertAt - indexUsed
country = country.Replace( "_d_" , " d'" ).Replace( "___" , " & " ).Replace( "_" , " " )
pictureboxes(row).Tag = country
If startIndex < nearX Then nearX = startIndex
If startIndex + country.Length - 1 > farX Then farX = startIndex + country.Length - 1
For x As Integer = 0 To country.Length - 1
gridArray(startIndex + x, row) = UCase(country(x))
Next
If doLabels Then
Return startIndex - 1
End If
Return -1
End Function
Conclusion
This is another example of how to create simple games using regular Controls in a WinForms application in VB.Net. Control Properties can be set in unorthodox ways to create a Control that isn't easily identified as the actual Control it is. In this way it's possible to use regular Controls to create a variety of differing games, each with a unique look.
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#
TicTacToe - 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#