My oldest child, Katie, is 3. She absolutely loves playing on the computer, and she's starting to learn her ABC's and 123's. My wife and I get her set up on either Disney's, Sprout's or Noggin's (parents with young children know what I'm talking about) websites, but they just don't seem too navigable for kids, especially at Katie's age.
She just wants to point and click, without any real context as to what she is doing.
I thought I would take her love of computers (and mine too!), and my desire for her to learn, so I built an app called "Katie's Learning Wiindow" that would randomly display randomly colored letters or numbers on the screen, and provide her feedback when she clicks on one of them. Future iterations (perpetual BETA, baby!) of this app may pompt her to locate a letter or a number and reward her on a correct answer, but, considering I put an hour into this while my wife was at Wal-Mart, this is a pretty good V1.0 release.
Here's how it works (for the most part):
- A panel control on the window is loaded with a bunch of label controls of fixed width and height, and the label text is set to a fixed font size. Each label control effectively become a "cell" on the panel.
- By determining the width and height of the panel, I can calculate the number of horizontal and vertical cells that will fit in the space, and those cells are loaded into a 2-dimensional array.
- I either loop through a collection of random letters, or randomly select a number from 1 to [max], and add them to another collection, guaranteeing uniqueness as I add.
- I then randomly calculate the X and Y coordinates, finding a random cell in the "grid", if you will. I make sure there's not already a label control in there, and add a label control with the random character information to that cell in the array.
- Once I've looped through my collection of random letters (or I've reached my [max] number count), I add the label controls (and click event handlers) to the panel's Controls collection.
- To finish it all off, I added two buttons below the panel that switch between ALPHA and NUMERIC modes, and resets and redraws the label controls.
- When the form is resized, resize the panel control so that, on a subsequent click of either button, the number of cells on the panel and the random location of label controls in each cell is recalcuated.
Here's a screen cap of the application:
Here's the code (I like #regions):
BTW, this was built with Microsoft Visual Studio 2003. I haven't had a chance to install 2005 on my home PC yet. Instead of using Collections (like I did), you may want to use Generics to manage the objects in the code below.
#Region "-- Win32 API declaration --"
' declare the Win32 API call
Private Declare Auto Function PlaySound Lib "winmm.dll" _
(ByVal lpszSoundName As String, ByVal hModule As Integer, _
ByVal dwFlags As Integer) As Integer
#End Region
#Region "-- Private variables and Enums --"
Private collLabels As Collection
Private collColors As Collection
Private _displayMode As Integer
Private Enum CharacterTypes
ALPHA = 0
NUMERIC = 1
End Enum
#End Region
#Region "-- Constant declarations --"
Private Const SND_FILENAME As Integer = &H20000
Private Const ALPHABET As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Private Const FONT_SIZE As Int16 = 30
Private Const MAX_ALPHA_CHARS As Int16 = 26
Private Const MAX_NUMERIC_CHARS As Int16 = 30
Private Const ALPHA_CELL_WIDTH As Int16 = 48
Private Const ALPHA_CELL_HEIGHT As Int16 = 48
Private Const NUMERIC_CELL_WIDTH As Int16 = 96
Private Const NUMERIC_CELL_HEIGHT As Int16 = 48
#End Region
#Region "-- Window event handlers --"
#Region "-- LearningWindow_Load --"
Private Sub LearningWindow_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' instantiate the collections
collLabels = New Collection
collColors = New Collection
' add some colors to the colors collection
collColors.Add(System.Drawing.Color.Red)
collColors.Add(System.Drawing.Color.Blue)
collColors.Add(System.Drawing.Color.Green)
collColors.Add(System.Drawing.Color.Yellow)
RedrawLabels(CharacterTypes.ALPHA, MAX_ALPHA_CHARS)
End Sub
#End Region
#Region "-- Generic label click event handler --"
Private Sub LabelClick(ByVal sender As Object, ByVal e As EventArgs)
' UNCOMMENT THIS ONCE YOU HAVE SOME WAV FILES TO PLAY
'PlayWav(CType(sender, Label).Text & ".wav")
'MsgBox(CType(sender, Label).Text & " was clicked.")
End Sub
#End Region
#Region "-- LearningWindow_Resize --"
Private Sub LearningWindow_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
pnlMain.Width = Me.Width
pnlMain.Height = Me.Height - 120
btnAlphabet.Top = Me.Height - 64
btnNumeric.Top = Me.Height - 64
End Sub
#End Region
#Region "-- btnAlphabet_Click --"
Private Sub btnAlphabet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlphabet.Click
RedrawLabels(CharacterTypes.ALPHA, 26)
End Sub
#End Region
#Region "-- btnNumeric_Click --"
Private Sub btnNumeric_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNumeric.Click
RedrawLabels(CharacterTypes.NUMERIC, 30)
End Sub
#End Region
#Region "-- pnlMain_Click --"
Private Sub pnlMain_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles pnlMain.Click
' UNCOMMENT THE BELOW CODE ONCE YOU HAVE WAV FILES RECORDED
'If _displayMode = CharacterTypes.ALPHA Then
' PlayWav("click_a_letter.wav")
'ElseIf _displayMode = CharacterTypes.NUMERIC Then
' PlayWav("click_a_number.wav")
'End If
End Sub
#End Region
#End Region ' Window event handlers
#Region "-- RedrawLabels --"
Private Sub RedrawLabels(ByVal characterType As Integer, ByVal maxChars As Integer)
Dim cellWidth As Int16
Dim cellHeight As Int16
Dim character As String
Dim aCell As Cell
Dim bFound As Boolean = False
Dim panelWidth As Integer = pnlMain.Width
Dim panelHeight = pnlMain.Height
' set the module-level display mode for when it's used from other control event handlers
_displayMode = characterType
' set the desired cell width for ALPHA or NUMERIC characters
If characterType = CharacterTypes.ALPHA Then
cellWidth = ALPHA_CELL_WIDTH
cellHeight = ALPHA_CELL_HEIGHT
ElseIf characterType = CharacterTypes.NUMERIC Then
cellWidth = NUMERIC_CELL_WIDTH
cellHeight = NUMERIC_CELL_HEIGHT
End If
' determine how many "cells" will fit in the given screen size, rounded to the nearest integer
Dim hCells As Integer = panelWidth / cellWidth
Dim vCells As Integer = panelHeight / cellHeight
' prepare a 2-dimensional array to contain the cells
Dim arCells(hCells, vCells) As Cell
Dim randomCellX As Integer, randomCellY As Integer
' remove all labels from the panel
pnlMain.Controls.Clear()
collLabels = New Collection
' randomly add unique characters to the collection
While collLabels.Count < maxChars
bFound = False
Select Case characterType
Case CharacterTypes.ALPHA
' get a random letter
character = CType(ALPHABET.Substring(RandomNumber(0, (maxChars - 1)), 1), String)
Case CharacterTypes.NUMERIC
' get a random number
character = RandomNumber(1, maxChars)
End Select
' add the first character to the collection
If collLabels.Count = 0 Then collLabels.Add(character)
For lcvLabels As Integer = 1 To collLabels.Count
If collLabels.Item(lcvLabels) = character Then
bFound = True
Exit For
End If
Next
If Not bFound Then collLabels.Add(character)
End While
' randomly add characters to the "cells" in the array
For lcvCharacter As Integer = 1 To collLabels.Count
Do
' get random (X,Y) coordinates for placement in the array
randomCellX = RandomNumber(0, hCells - 2)
randomCellY = RandomNumber(0, vCells - 2)
If arCells(randomCellX, randomCellY) Is Nothing Then
' populate and add the cell at the random position in the array
aCell = New Cell
aCell.Left = randomCellX * cellWidth
aCell.Top = randomCellY * cellHeight
aCell.Character = collLabels(lcvCharacter)
arCells(randomCellX, randomCellY) = aCell
Exit Do
End If
Loop
Next
' now go through the array, build label controls, and add them to the panel in their appropriate cells
For lcvCellsX As Integer = 0 To hCells
For lcvCellsY As Integer = 0 To vCells
If Not arCells(lcvCellsX, lcvCellsY) Is Nothing Then
aCell = arCells(lcvCellsX, lcvCellsY)
lbl = New Label
Dim fnt As Font
Dim siz As Size
fnt = lbl.Font
siz = lbl.Size
lbl.Font = New Font(fnt.Name, FONT_SIZE, FontStyle.Bold)
lbl.Size = New Size(cellWidth, cellHeight)
lbl.ForeColor = collColors.Item(RandomNumber(1, collColors.Count))
lbl.Top = aCell.Top
lbl.Left = aCell.Left
lbl.Text = aCell.Character
lbl.Name = "lbl" & aCell.Character
pnlMain.Controls.Add(lbl)
AddHandler lbl.Click, AddressOf LabelClick
End If
Next
Next
End Sub
#End Region
#Region "-- Helper functions --"
#Region "-- PlayWav --"
Public Function PlayWav(ByVal fileFullPath As String) As Boolean
' this will look in the \bin directory for .wav files named 1.wav, or a.wav, etc. I hope you have a good recording voice.
' return true if successful, false if otherwise
Dim iRet As Integer = 0
Try
iRet = PlaySound(fileFullPath, 0, SND_FILENAME)
Catch
End Try
Return iRet
End Function
#End Region
#Region "-- RandomNumber --"
Public Function RandomNumber(ByVal low As Int32, ByVal high As Int32) As Integer
Static RandomNumGen As New System.Random
Return RandomNumGen.Next(low, high + 1)
End Function
#End Region
#End Region
End Class
#Region "-- Cell class --"
Friend Class Cell
Public Top As Integer
Public Left As Integer
Public Character As String
End Class
#End Region
Please feel free to contact me, or post a comment, if you have any questions on anything.
Doug