News


Add to Technorati Favorites

My Stats

  • Posts - 53
  • Comments - 439
  • Trackbacks - 20

Twitter












Tag Cloud


Recent Comments


Recent Posts


Archives


Post Categories


Image Galleries


Blogs I read


Company Links


Fun Stuff


Kansas City User Groups


My CMS Projects



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:
Katie's Learning Window

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

Comments

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: