Excel VBA: Wordsearch Creator
Overview
This is an Excel/VBA game that creates wordsearch games in either 10*10, 15*15, or 20*20 format. To create a wordsearch, you just need to enter a list of words to use, then click the New Game button. Your new random wordsearch will be displayed as well as a list of words used and statistics about the number of horizontal, vertical, and diagonal words fitted into your wordsearch game. Sometimes you might get disappointing results with only a few words fitted, or uneven spread in the statistics. This is due to the random nature of the game, and you should get better results if you click the New Game button again.
Using the Developer Tools in an Excel Workbook, it's possible to add Controls, such as the Buttons used in this game. It's also possible to add VBA Macros to your Workbook. VBA the language used in Macros is very similar to classic VB, and fairly easily used. Macros add additional functionality to your Workbook. A combination of Formulas, Conditional Formatting, and Macros are used in this game.
10*10 Wordsearch
15*15 Wordsearch
20*20 Wordsearch
The code parts
Part 1 - Reading words
Here, the words entered are read into an ArrayList
Part 2 - Setting up the allCells array
The allCells array is a 2D grid array of type gridcell...
Public Type gridcell
aline(3) As Integer
available(3) As Boolean
text As String
index As Integer
End Type
Each cell contains a four element integer array, which stores the grid lines it belongs to (Horizontal, vertical, and 2 * diagonal).
These grid lines are used for fitting words in the allCells array.
Each cell also contains a four element boolean array, which stores four values indicating which (if any) direction a cell is available for use.
Also stored is the text of the cell and the index (1 to w*h) which is used for transposing between arrays.
This part sets up each cell of the allCells array with the default values
Part 3 - Fitting words in allCells array
Here the code attempts to fit all of the words to be used into the allCells array. These words can be fitted horizontally, vertically, or diagonally either in a forward or reversed arrangement. This part works recursively, with a timeout for when no solution is possible. Due to the random nature of this game, sometimes the macro needs to be run two or three times to get reasonable results, both in words used and words stats...
Part 4 - Writing values to a worksheet
Here the values determined in part 3 are written to the activesheet.
The Macro for creating 10*10 Wordsearches
This is annotated with part numbers which relate to the descriptions above...
Sub newGame()
Dim words As Object, spaces As Object, wordsUsed As Object
Dim allcells(9, 9) As gridcell
Dim rng As Range, cell As Range
Dim wordCounter As Integer
Dim charCounter As Integer
Dim errorCounter As Integer
wordCounter = 0
charCounter = 0
errorCounter = 0
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Part 1 - Reading words
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Set words = CreateObject("System.Collections.ArrayList") 'Create the ArrayList
Set rng = Range("C3:C17")
For Each cell In rng
If (Len(CStr(cell.value))) > 0 And (Len(CStr(cell.value))) <= 10 Then
If charCounter + Len(CStr(cell.value)) <= 100 Then
words.Add (UCase(CStr(cell.value)))
End If
End If
Next cell
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'/Part 1
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Part 2 - Setting up allCells array
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
For r = 1 To 10
For c = 1 To 10
Dim grcell As gridcell
For y = 0 To 3
grcell.aline(y) = 0
grcell.available(y) = True
Next y
grcell.text = ""
grcell.index = (r - 1) * 10 + c
allcells(r - 1, c - 1) = grcell
Next c
Next r
ActiveSheet.Unprotect "p455w0rd"
Set boardRng = Range("F5:O14")
boardRng.ClearContents
ActiveSheet.Protect "p455w0rd", True, True
' 1 to 20
For r = 1 To 10
For c = 1 To 10
allcells(r - 1, c - 1).aline(0) = r
allcells(r - 1, c - 1).aline(1) = c + 10
Next c
Next r
Dim rowCounter As Integer
rowCounter = 21
' 21 to 27
For r = 3 To 9
c = 0
For r2 = r To 0 Step -1
allcells(r2, c).aline(2) = rowCounter
c = c + 1
Next r2
rowCounter = rowCounter + 1
Next r
rowCounter = 28
' 28 to 33
For c = 1 To 6
r = 9
For c2 = c To 9
allcells(r, c2).aline(2) = rowCounter
r = r - 1
Next c2
rowCounter = rowCounter + 1
Next c
rowCounter = 34
' 34 to 40
For c = 6 To 0 Step -1
c2 = c
For r2 = 0 To 9 - c
allcells(r2, c2).aline(3) = rowCounter
c2 = c2 + 1
Next r2
rowCounter = rowCounter + 1
Next c
rowCounter = 41
' 41 to 46
For r = 1 To 6
r2 = r
For c2 = 0 To 9 - r
allcells(r2, c2).aline(3) = rowCounter
r2 = r2 + 1
Next c2
rowCounter = rowCounter + 1
Next r
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'/Part 2
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Part 3 - Fitting words in allCells array
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Randomize
Dim w As Integer
Dim h, v, d1, d2 As Integer
h = 0
v = 0
d1 = 0
d2 = 0
Set wordsUsed = CreateObject("System.Collections.ArrayList") 'Create the ArrayList
For w = 0 To words.Count - 1
Dim word As String
word = CStr(words(w))
continueFor:
errorCounter = errorCounter + 1
If errorCounter > 2048 Then Exit For
Dim lineIndex As Integer
lineIndex = (Int(46 - 1 + 1) * Rnd + 1)
Dim lineCells() As gridcell
lineCells = getLine(10, lineIndex, allcells)
On Error Resume Next
bempty = Not IsNumeric(UBound(lineCells))
If Err Then GoTo continueFor
Dim reversed As Boolean
reversed = CBool(Int(2 * Rnd + 1) - 1)
'MsgBox reversed
Select Case lineIndex
Case 11 To 20
If Not reversed Then
Call BubbleSort(lineCells, 0)
Else
Call ReverseBubbleSort(lineCells, 0)
End If
Case Else
If Not reversed Then
Call BubbleSort(lineCells, 1)
Else
Call ReverseBubbleSort(lineCells, 1)
End If
End Select
Dim availableIndex As Integer
Select Case lineIndex
Case 1 To 10
availableIndex = 0
Case 11 To 20
availableIndex = 1
Case 21 To 33
availableIndex = 2
Case 34 To 46
availableIndex = 3
Case Else
availableIndex = -1
End Select
Dim noSpace As Boolean
'noSpace = False
Dim startAt As Integer
startAt = 0
If Not lineCells(0).available(availableIndex) Then
For x = 1 To UBound(lineCells)
If lineCells(x).available(availableIndex) Then
startAt = x
Exit For
End If
Next
If startAt = 0 Then GoTo continueFor
End If
'If noSpace Then
Set spaces = CreateObject("Scripting.Dictionary")
spaces.Add startAt, 1
For x = startAt To UBound(lineCells)
If lineCells(x).available(availableIndex) Then
spaces(startAt) = spaces(startAt) + 1
Else
For x2 = x + 1 To UBound(lineCells)
If lineCells(x2).available(availableIndex) Then
startAt = x2
spaces.Add startAt, 1
x = x2 + 1
Exit For
End If
Next
End If
Next
Dim max As Integer
max = 0
For Each Key In spaces.Keys
If spaces(Key) > max Then
max = spaces(Key)
startAt = Key
End If
Next
If UBound(lineCells) >= startAt + Len(word) - 1 Then
If Len(word) <= max Then
'Stop
Do
Dim match As Boolean
match = True
For x = startAt To startAt + Len(word) - 1
If Mid(word, (x - startAt) + 1, 1) <> lineCells(x).text And lineCells(x).text <> "" Then
match = False
End If
Next
If match Then
wordCounter = wordCounter + 1
wordsUsed.Add word
Select Case lineIndex
Case 1 To 10
h = h + 1
Case 11 To 20
v = v + 1
Case 21 To 33
d1 = d1 + 1
Case 34 To 46
d2 = d2 + 1
End Select
For x = startAt To startAt + Len(word) - 1
lineCells(x).text = Mid(word, (x - startAt) + 1, 1)
lineCells(x).available(availableIndex) = False
Next
If startAt > 0 Then
lineCells(startAt - 1).available(availableIndex) = False
End If
If startAt + Len(word) - 1 < UBound(lineCells) Then
lineCells(startAt + Len(word)).available(availableIndex) = False
End If
Exit Do
Else
If UBound(lineCells) >= startAt + Len(word) Then
If startAt + Len(word) < max Then
startAt = startAt + 1
Else
GoTo continueFor
End If
Else
GoTo continueFor
End If
End If
Loop
End If
Else
GoTo continueFor
End If
If Not wordsUsed.contains(word) Then GoTo continueFor
For i1 = 0 To UBound(lineCells)
For r = 1 To 10
For c = 1 To 10
If lineCells(i1).index = allcells(r - 1, c - 1).index Then
For y2 = 0 To 3
allcells(r - 1, c - 1).available(y2) = lineCells(i1).available(y2)
Next
If allcells(r - 1, c - 1).text = "" Then
allcells(r - 1, c - 1).text = lineCells(i1).text
End If
Exit For
End If
Next c
Next r
Next i1
'Set spaces = Nothing
Next
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'/Part 3
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Part 4 - Writing values to worksheet
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ActiveSheet.Unprotect "p455w0rd"
Set wordsRng = Range("T3:T17")
wordsRng.ClearContents
If wordsUsed.Count > 0 Then
x = 0
For Each cell In wordsRng
cell.value = wordsUsed(x)
x = x + 1
If x = wordsUsed.Count Then Exit For
Next
End If
For r = 1 To 10
For c = 1 To 10
If allcells(r - 1, c - 1).text <> "" Then
ActiveSheet.cells(r + 4, c + 5).value = allcells(r - 1, c - 1).text
Else
Dim value As Integer
value = 65 + Int(26 * Rnd + 1) - 1
ActiveSheet.cells(r + 4, c + 5).value = Chr(value)
End If
Next c
Next r
Range("V3").value = "horizontal:"
Range("W3").value = h
Range("V4").value = "vertical:"
Range("W4").value = v
Range("V5").value = "diagonal/:"
Range("W5").value = d1
Range("V6").value = "diagonal\:"
Range("W6").value = d2
ActiveSheet.Protect "p455w0rd", True, True
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'/Part 4
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
End Sub
Conclusion
Microsoft Office is a versatile valid programming tool for the office developer. This example focuses on game programming, but these tools can be used to create some fairly advanced office software.
Requirements
Download
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#
- VB.Net - Three-card Monte
- VB.Net - Pascal's Pyramid
- VB.Net - Split Decisions
- VB.Net - Random Maze Games
- VB.Net - Event Driven Programming - LockWords Game
- C# - Crack the Lock