Create your own typing tutor!

Here’s an idea to teach somebody the positions of the letters on the keyboard: letters fly in randomly from the right for 30 seconds. Hit the letter on the keyboard for points. Miss and lose points. As time goes on, the letters move faster and there are more of them. More points are earned for faster typists. Points are deducted for misses. Can anyone beat my high score of 3760?

#define MAXLETS 10

PUBLIC ox

ox=CREATEOBJECT("Letters")

ox.show()

DEFINE CLASS Letters as Form

      left=200

      width=600

      height=300

      backcolor=-1

      nScore=0

      nTicks=0

      nHighScore=0

      nInterval=100 && # of msecs per tick

      DIMENSION aLets[MAXLETS]

      allowoutput=.f.

      nMaxSecs=30

      ADD OBJECT MyTimer as timer

      PROCEDURE init

            FOR i = 1 TO MAXLETS

                  thisform.AddObject("thisform.aLets["+trans(i)+"]","MyLabel")

            ENDFOR

            DECLARE integer Beep IN WIN32API integer Freq, integer DurationMs

            this.mytimer.interval=thisform.nInterval

            IF FILE("letters.txt")

                  this.nHighScore=INT(VAL(FILETOSTR("letters.txt")))

            ENDIF

      PROCEDURE keypress(nKeyCode, nShiftAltCtrl)

            IF nKeyCode=27 && Escape

                  thisform.Release

            ELSE

                  oGotone = .null.

                  FOR i = 1 TO MAXLETS

                        WITH thisform.aLets[i] as Label

                              IF .Visible AND .Caption = UPPER(CHR(nKeyCode))

                                    IF ISNULL(oGotone) OR .Left < oGotone.left && get leftmost

                                          oGotone = thisform.aLets[i]

                                    ENDIF

                              ENDIF

                        ENDWITH

                  ENDFOR

                  IF ISNULL(oGotone)

                        thisform.BadOne(50)

                  ELSE

                        oGotone.visible = .f.

                        thisform.nScore=thisform.nScore+ INT(oGotone.left/10) && higher score for rightmost

                  ENDIF

            ENDIF

      PROCEDURE BadOne(nHowBad)

            thisform.nScore=MAX(0,thisform.nScore-nHowBad)

            beep(2000,20)

      PROCEDURE MyTimer.timer

            thisform.nTicks=thisform.nTicks+1

            nSecs=thisform.nTicks*this.interval/1000

            IF nSecs > thisform.nMaxSecs && out of time?

                  FOR i = 1 TO MAXLETS

                        thisform.aLets[i].Visible=.f. && hide all letters

                  ENDFOR

                  IF thisform.nHighScore < thisform.nScore

                        MESSAGEBOX("New High Score: "+TRANSFORM(thisform.nScore)+"! Old = "+TRANSFORM(thisform.nHighScore),48)

                        thisform.nHighScore=thisform.nScore

                        STRTOFILE(TRANSFORM(thisform.nScore),"letters.txt") && record high score

                  ELSE

                        MESSAGEBOX("Your Score: "+TRANSFORM(thisform.nScore)+" High Score = "+TRANSFORM(thisform.nHighScore))

                  ENDIF

                  thisform.nScore=0 && Restart

                  thisform.nTicks=0

            ELSE

                  thisform.Caption = TRANSFORM(thisform.nScore) + " "+TRANSFORM(INT((thisform.nMaxSecs- nSecs)))

                  FOR i = 1 TO MAXLETS

                        WITH thisform.aLets[i] as Label

                              IF .Visible

                                    .Left = .Left - .dx

                                    IF .Left <= 0

                                          .Visible=.f.

                                          thisform.BadOne(100)

                                    ENDIF

                              ELSE

                                    nFactor = nSecs /thisform.nMaxSecs && 0-1

                                    IF RAND() < .5*nFactor && gradually increase # of letters

                                          .dx = 1+RAND() * 15 * nFactor && gradually accelerate

                                          .Left=thisform.Width - .dx

                                          .ForeColor=0xffffff-MOD(thisform.nTicks*100,256^3)

                                          .Top = .9 * (RAND() * thisform.Height)

                                          .Caption = CHR(65+RAND()*26)

                                          .Visible= 1

                                    ENDIF

                              ENDIF

                        ENDWITH

                  ENDFOR

            ENDIF

ENDDEFINE

DEFINE CLASS MyLabel as Label

      Fontsize=20

      FontBold=1

      FontName="Verdana"

      BackStyle=0 && transparent

      dx=1

      Height = 32

      Width = 26

ENDDEFINE