4章:チュートリアル 3: 計算クイズの作成

    作成2013.02.23

  1. チュートリアル 3: 計算クイズの完成ファイル
     チュートリアル 3: 計算クイズの作成の解説とおりに作業を実施すると、プロジェクトファイル群が完成します。
     完成ファイルは以下からダウンロードできます。
     ダウンロード後は解凍してから使用してください。
     
    [チュートリアル 3の完成ファイル]をダウンロードする。
     解凍すると「Math Quiz」フォルダーがあります。 注(1)「Math Quiz」フォルダーのMath Quiz.sln」ファイルをダブルクリックすると「Microsoft Visual Basic 2010 Express」が起動します。
    注(2)メニューの「ウインド」_「ウインドレイアウトのリセット」で標準に戻ります。
    注(3)「ソリューションエクスプローラ」ウインドウ内の「Form1.vb」をダブルクリックすると「デザイン」が表示されます。
    注(4)メニューの「表示」_「コード」を選択するとコードが表示されます。


  2. Math Quizの実行
    (1)「Microsoft Visual Basic 2010 Express」のデバッグ機能を使用します。
    (2)「デバッグ」_「デバッグ開始」を選択します。
    (3)クイズスタート前の画面が表示されます。
    (4)Start the quizボタンを押すと問題と残り時間が表示されます。
    (5)+解答欄にカーソルを移し、値をキーボード入力して、リターンします。
    (6)次に-、×、÷の順で解答します。
    (7)制限時間内の全問正解すれば成功です。
    (8)クローズボックスでプログラムを終了します。


  3. 新規プロジェクトの作成
    (1)新規プロジェクト
     新規プロジェクトを作成すると「デザイナー」にはForm1が自動生成されます。Math Quizでは(Name)=Form1、Size=550、400 、Text=Math Quizとしています。

    (2) Formコード
    Public Class Form1
    End Class
    が自動生成されます。


  4. 各種パーツの設定
    (1) パーツレイアウト
     Form1にLabel、NumericUpDown、Button、Timerをツールボックスから設定します。(設定方法はチュートリアル 3: 計算クイズの作成に詳しく説明があります。)


  5. Public Class Form1の全コード
    Public Class Form1
        Dim randomizer As New Random
        Dim addend1 As Integer
        Dim addend2 As Integer
        Dim minuend As Integer
        Dim subtrahend As Integer
        Dim multiplicand As Integer
        Dim multiplier As Integer
        Dim dividend As Integer
        Dim divisor As Integer
        Dim timeLeft As Integer
    
        Public Function CheckTheAnswer() As Boolean
            If ((addend1 + addend2 = sum.Value) AndAlso (minuend - subtrahend = difference.Value) AndAlso (multiplicand * multiplier = product.Value) AndAlso (dividend / divisor = quotient.Value)) Then
                Return True
            Else
                Return False
            End If
        End Function
    
        Private Sub startButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles startButton.Click
            startButton.Enabled = False
            StartTheQuiz()
        End Sub
    
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If CheckTheAnswer() Then
                Timer1.Stop()
                MessageBox.Show("You got all of the answers right!", "Congratulations!")
                startButton.Enabled = True
            ElseIf timeLeft > 0 Then
                timeLeft = timeLeft - 1
                timeLabel.Text = timeLeft & " seconds"
            Else
                Timer1.Stop()
                timeLabel.Text = "Time's up!"
                MessageBox.Show("You didn't finish in time.", "Sorry")
                sum.Value = addend1 + addend2
                difference.Value = minuend - subtrahend
                product.Value = multiplicand * multiplier
                quotient.Value = dividend / divisor
                startButton.Enabled = True
            End If
        End Sub
    
        Public Sub StartTheQuiz()
            ' Fill in the addition problem.
            addend1 = randomizer.Next(51)
            addend2 = randomizer.Next(51)
            plusLeftLabel.Text = addend1.ToString
            plusRightLabel.Text = addend2.ToString
            sum.Value = 0
            ' Fill in the subtraction problem.
            minuend = randomizer.Next(1, 101)
            subtrahend = randomizer.Next(1, minuend)
            minusLeftLabel.Text = minuend.ToString
            minusRightLabel.Text = subtrahend.ToString
            difference.Value = 0
            ' Fill in the multiplication problem.
            multiplicand = randomizer.Next(2, 11)
            multiplier = randomizer.Next(2, 11)
            timesLeftLabel.Text = multiplicand.ToString
            timesRightLabel.Text = multiplier.ToString
            product.Value = 0
            ' Fill in the division problem.
            divisor = randomizer.Next(2, 11)
            Dim temporaryQuotient As Integer = randomizer.Next(2, 11)
            dividend = divisor * temporaryQuotient
            dividedLeftLabel.Text = dividend.ToString
            dividedRightLabel.Text = divisor.ToString
            quotient.Value = 0
            ' Start the timer.
            timeLeft = 30
            timeLabel.Text = "30 seconds"
            Timer1.Start()
        End Sub
    
        '   Private Sub answer_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles sum.Enter, difference.Enter, product.Enter, quotient.Enter
        '       Dim answerBox As NumericUpDown = TryCast(sender, NumericUpDown)
        '       If answerBox IsNot Nothing Then
        '           Dim lengthOfAnswer As Integer = answerBox.Value.ToString().Length
        '       answerBox.Select(0, lengthOfAnswer)
        '       End If
        '    End Sub
    End Class
    
    


  6. 変数設定の解説
        Dim randomizer As New Random
        Dim addend1 As Integer
        Dim addend2 As Integer
        Dim minuend As Integer
        Dim subtrahend As Integer
        Dim multiplicand As Integer
        Dim multiplier As Integer
        Dim dividend As Integer
        Dim divisor As Integer
        Dim timeLeft As Integer
    
    (1)Dim randomizer As New RandomはRandomクラスのオブジェクトrandomizerを生成します。
    (2)通常変数の型では、Newが不要ですが、クラスのオブジェクト生成では必要なようです。(なぜ?Newが必要なのか?なくても良いような気がしますが、Newがないとエラーになります。)
    (3)その他の変数は全て、出題のための変数であり、整数型です。


  7. Private Sub startButton_Clickの解説
        Private Sub startButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles startButton.Click
            startButton.Enabled = False
            StartTheQuiz()
        End Sub
    
    (1) Private Sub startButton_Clickメソッドはデザイナーから自動生成したイベント処理ルーチンです。
    (2) startButton.Clicイベントが発生した時、システムから呼び出されます。
    (3)startButton.Enabled = FalseはstartButtonを無効にします。
    (4)StartTheQuiz()はStartTheQuiz()メソッドを実行します。


  8. Public Sub StartTheQuiz()の解説
        Public Sub StartTheQuiz()
            ' Fill in the addition problem.
            addend1 = randomizer.Next(51)
            addend2 = randomizer.Next(51)
            plusLeftLabel.Text = addend1.ToString
            plusRightLabel.Text = addend2.ToString
            sum.Value = 0
            ' Fill in the subtraction problem.
            minuend = randomizer.Next(1, 101)
            subtrahend = randomizer.Next(1, minuend)
            minusLeftLabel.Text = minuend.ToString
            minusRightLabel.Text = subtrahend.ToString
            difference.Value = 0
            ' Fill in the multiplication problem.
            multiplicand = randomizer.Next(2, 11)
            multiplier = randomizer.Next(2, 11)
            timesLeftLabel.Text = multiplicand.ToString
            timesRightLabel.Text = multiplier.ToString
            product.Value = 0
            ' Fill in the division problem.
            divisor = randomizer.Next(2, 11)
            Dim temporaryQuotient As Integer = randomizer.Next(2, 11)
            dividend = divisor * temporaryQuotient
            dividedLeftLabel.Text = dividend.ToString
            dividedRightLabel.Text = divisor.ToString
            quotient.Value = 0
            ' Start the timer.
            timeLeft = 30
            timeLabel.Text = "30 seconds"
            Timer1.Start()
        End Sub
    
    (1)saddend1 = randomizer.Next(51)はsaddend1に0から50の整数型乱数を代入します。
    (2)Random.Next (Int32) は指定した最大値より小さい 0 以上の整数の乱数を返します。Int32は32ビット符号付整数です。
    (3)plusLeftLabel.Text = addend1.ToStringは addend1の値を文字にして、plusLeftLabel.Textに代入します。
    (4)Object.ToString メソッドは現在の Object を表す String を返します。
    (5)addend1はInteger型として定義されていますが、ToString メソッド等を含むクラスとして定義しているようです。
    (6)では、Randomクラスを定義するのにNewが必要で、Integerクラスを定義するのにNewが不要なのか?(若干の矛盾を含んでいるような気がします。)
    (7) minuend = randomizer.Next(1, 101)は minuendに1から100の整数型乱数を代入します。
    (8)subtrahend = randomizer.Next(1, minuend)はsubtrahendに1からminuendの整数型乱数を代入します。
    (9) multiplicand = randomizer.Next(2, 11)はmultiplicandに2から10の整数型乱数を代入します。
    (10)timeLeft = 30はtimeLeftを30にします。
    (11)timeLabel.Text = "30 seconds"はtimeLabel.Textに "30 seconds"を設定します。
    (12)Timer1.Start()はTimer1をスタートします。

  9. Private Sub answer_Enterの解説
        '   Private Sub answer_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles sum.Enter, difference.Enter, product.Enter, quotient.Enter
        '       Dim answerBox As NumericUpDown = TryCast(sender, NumericUpDown)
        '       If answerBox IsNot Nothing Then
        '           Dim lengthOfAnswer As Integer = answerBox.Value.ToString().Length
        '       answerBox.Select(0, lengthOfAnswer)
        '       End If
        '    End Sub
    
    (1)このルーチンは結果的に何も変化しないルーチンであり、不要なルーチンです。
    (2)このルーチンは高度な関数を使用しており、かなり理解の難しいルーチンです。
    (3)Dim answerBox As NumericUpDown = TryCast(sender, NumericUpDown)は新たにanswerBoxを NumericUpDownクラスを構築し、イベントが発生したNumericUpDownの内容をコピーします。
    (4)TryCast(sender, NumericUpDown)はSystem.Object型変数senderをNumericUpDown型変数に変換します。
    (5)System.Object型変数senderは総組図の図番のようなもので、総組図に関連したNumericUpDownユニットの図番に変換すると考えればわかりやすいかもしれません。(TryCastはかなり高度な関数です。)
    (6) If answerBox IsNot Nothing ThenはanswerBoxに値があれば以下を実行します。
    (7)Dim lengthOfAnswer As Integer = answerBox.Value.ToString().LengthはlengthOfAnswerにanswerBoxの値を文字列に変換し、文字数を代入します。
    (8)answerBox.Select(0, lengthOfAnswer)は選択する対象の文字の開始位置と文字数を指定する、スピン ボックス (アップダウン コントロール) のテキストの範囲を選択します。
    (9)上記の操作はプログラム全体からみると何の影響もありません。
    (10)このルーチンは、このような高度の処理も可能であることを示していますが、プログラム学習初心者にとっては混乱をあたえないだろうか?


  10. Public Function CheckTheAnswer() As Booleanの解説
         Public Function CheckTheAnswer() As Boolean
            If ((addend1 + addend2 = sum.Value) AndAlso (minuend - subtrahend = difference.Value) AndAlso (multiplicand * multiplier = product.Value) AndAlso (dividend / divisor = quotient.Value)) Then
                Return True
            Else
                Return False
            End If
        End Function
    
    (1)Public Function CheckTheAnswer() As BooleanはTrueまたはFalseをかえす関数です。
    (2) If ((addend1 + addend2 = sum.Value) AndAlso (minuend - subtrahend = difference.Value) AndAlso (multiplicand * multiplier = product.Value) AndAlso (dividend / divisor = quotient.Value)) Thenは足し算と引き算と掛け算と割り算の全て正しいときTrueをかえし、そうでないときFalseをかえします。


  11. Private Sub Timer1_Tickの解説
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If CheckTheAnswer() Then
                Timer1.Stop()
                MessageBox.Show("You got all of the answers right!", "Congratulations!")
                startButton.Enabled = True
            ElseIf timeLeft > 0 Then
                timeLeft = timeLeft - 1
                timeLabel.Text = timeLeft & " seconds"
            Else
                Timer1.Stop()
                timeLabel.Text = "Time's up!"
                MessageBox.Show("You didn't finish in time.", "Sorry")
                sum.Value = addend1 + addend2
                difference.Value = minuend - subtrahend
                product.Value = multiplicand * multiplier
                quotient.Value = dividend / divisor
                startButton.Enabled = True
            End If
        End Sub
    
    (1)Private Sub Timer1_Tickはデザイナーから自動生成されます。
    (2)Timer1.Tickイベントで呼び出されます。(指定したタイマの間隔が経過し、タイマが有効である場合に発生します。 )
    (3) If CheckTheAnswer() ThenはCheckTheAnswer()の戻り値がTrueの場合とFalseの場合で処理を分岐します。
    (4)Trueの場合Timer1.Stop()を実行します。
    (5)そして MessageBox.Show("You got all of the answers right!", "Congratulations!")では MessageBoxのTextに"You got all of the answers right!"が表示され、Captionに"Congratulations!"が表示されます。
    (6) startButton.Enabled = Trueを設定します。
    (7)Falseの場合ElseIf timeLeft > 0 Thenの判定をします。
    (8)残り時間がある場合、 timeLeft = timeLeft - 1とします。
    (9) timeLabel.Text = timeLeft & " seconds"を実行します。
    (10)時間きれの場合、Timer1.Stop()とします。
    (11)timeLabel.Text = "Time's up!"を実行します。
    (12) MessageBox.Show("You didn't finish in time.", "Sorry")を実行します。
    (13)正解値を表示します。
    (14)startButton.Enabled = Trueを設定します。


    感想: Private Sub answer_Enterのコードは難解で苦戦しました。やっと解読してみると不要であることがわかりました。Visual Basic 2010 Expressにおいては、全ての変数型がクラスとして定義されているのではないか?そんな気がします。歴史的にみると変数は整数型、実数型、文字型等の型があったのは当初からです。そして複数の変数をグループ化した変数がくわわり、さらに複数の変数と複数のメソッドをグループ化したクラスに変化しました。
     クラスは整数型等の変数の拡張形と考えることもできます。だとしたら定義の書式も統一できるのは?







5章:チュートリアル 4: 絵合わせゲームの作成に行く。

トップページに戻る。