|
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
|