Självstudie: Lägga till en timer i en WinForms-app för matematikquiz

I den här serien med fyra självstudier skapar du ett matematiskt test. Testet innehåller fyra slumpmässiga matematiska problem som en testtagare försöker besvara inom en angiven tid.

I frågesporten används en timerfunktion. Koden bakom den här kontrollen spårar den förflutna tiden och kontrollerar frågetesttagarens svar.

I den här tredje självstudien lär du dig att:

  • Lägg till en Timer-kontroll.
  • Lägg till en händelsehanterare för timern.
  • Skriv kod för att kontrollera användarens svar, visa meddelanden och fyll i rätt svar.

Förutsättningar

Den här självstudien bygger på tidigare självstudier, som börjar med Skapa en WinForms-app för matematikquiz. Om du inte har slutfört dessa självstudier, se till att göra dem först.

Lägga till en timer för nedräkning

Om du vill hålla reda på tiden under testet använder du en timerkomponent. Du behöver också en variabel för att lagra den tid som är kvar.

  1. Lägg till en heltalsvariabel med namnet timeLeft på samma sätt som du deklarerade variabler i tidigare handledningar. Placera timeLeft-deklaration direkt efter de andra deklarationerna. Koden bör se ut som i följande exempel.

    public partial class Form1 : Form
    {
        // Create a Random object called randomizer 
        // to generate random numbers.
        Random randomizer = new Random();
    
        // These integer variables store the numbers 
        // for the addition problem. 
        int addend1;
        int addend2;
    
        // These integer variables store the numbers 
        // for the subtraction problem. 
        int minuend;
        int subtrahend;
    
        // These integer variables store the numbers 
        // for the multiplication problem. 
        int multiplicand;
        int multiplier;
    
        // These integer variables store the numbers 
        // for the division problem. 
        int dividend;
        int divisor;
    
        // This integer variable keeps track of the 
        // remaining time.
        int timeLeft;
    

  1. I Windows Forms Designerflyttar du en Timer-kontroll från kategorin Components i Toolbox- till formuläret. Kontrollen visas i det grå området längst ned i designfönstret.

  2. I formuläret väljer du ikonen timer1 som du nyss lade till och anger egenskapen Intervall till 1 000. Eftersom det här intervallet är i millisekunder gör ett värde på 1 000 att timern genererar en Tick händelse varje sekund.

Kontrollera svaren

Eftersom timern genererar en Tick-händelse varje sekund är det klokt att kontrollera den förflutna tiden i en Tick-händelsehanterare. Det är också praktiskt att kontrollera svaren i händelsehanteraren. Om tiden har tagit slut, eller om svaren är korrekta, bör frågesporten avslutas.

Innan du skriver händelsehanteraren lägger du till en metod med namnet CheckTheAnswer() för att avgöra om svaren på matematiska problem är korrekta. Den här metoden bör vara i linje med de andra metoderna, till exempel StartTheQuiz(). Koden bör se ut som i följande exempel.

/// <summary>
/// Check the answers to see if the user got everything right.
/// </summary>
/// <returns>True if the answer's correct, false otherwise.</returns>
private bool CheckTheAnswer()
{
    if ((addend1 + addend2 == sum.Value)
        && (minuend - subtrahend == difference.Value)
        && (multiplicand * multiplier == product.Value)
        && (dividend / divisor == quotient.Value))
        return true;
    else
        return false;
}

Den här metoden bestämmer svaren på matematiska problem och jämför resultatet med värdena i NumericUpDown kontroller. I den här koden:

  • Visual Basic-versionen använder nyckelordet Function i stället för det vanliga Sub nyckelordet eftersom den här metoden returnerar ett värde.

  • Du kan inte enkelt ange multiplikationstecknet (×) och divisionstecknet (÷) med hjälp av tangentbordet, så C# och Visual Basic accepterar en asterisk (*) för multiplikation och ett snedstreck (/) för division.

  • I C# är && operatorn logical and. I Visual Basic är motsvarande operator AndAlso. Du använder operatorn logical and för att kontrollera om mer än ett villkor är sant. Om värdena i det här fallet är korrekta returnerar metoden värdet true. Annars returnerar metoden värdet false.

  • if-instruktionen använder egenskapen Value för en NumericUpDown-kontroll för att få åtkomst till kontrollens aktuella värde. I nästa avsnitt använder du samma egenskap för att visa rätt svar i varje kontroll.

Lägga till en händelsehanterare i timern

Nu när du har ett sätt att kontrollera svaren kan du skriva koden för händelsehanteraren Tick. Den här koden körs varje sekund efter att timern genererar en Tick-händelse. Den här händelsehanteraren kontrollerar frågetesttagarens svar genom att anropa CheckTheAnswer(). Den kontrollerar också hur lång tid som har förflutit i frågesporten.

  1. Dubbelklicka på kontrollen Timer i formuläret eller välj den och välj sedan Ange. De här åtgärderna lägger till en Tick-händelsehanterare. Kodredigeraren visas och visar tick-hanterarens metod.

    För C#lägger den till en kodrad i Form1.Designer.cs kodfil som kopplar ihop händelsehanteraren:

    timer1.Tick += new EventHandler(timer1_Tick);
    

    (För Visual Basic finns det inget behov av den raden, men händelsehanteraren innehåller en handles Timer1.Tick som gör samma sak.)

  2. Lägg till följande instruktioner i den nya händelsehanterarmetoden.

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (CheckTheAnswer())
        {
            // If CheckTheAnswer() returns true, then the user 
            // got the answer right. Stop the timer  
            // and show a MessageBox.
            timer1.Stop();
            MessageBox.Show("You got all the answers right!",
                            "Congratulations!");
            startButton.Enabled = true;
        }
        else if (timeLeft > 0)
        {
            // If CheckTheAnswer() returns false, keep counting
            // down. Decrease the time left by one second and 
            // display the new time left by updating the 
            // Time Left label.
            timeLeft = timeLeft - 1;
            timeLabel.Text = timeLeft + " seconds";
        }
        else
        {
            // If the user ran out of time, stop the timer, show
            // a MessageBox, and fill in the answers.
            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;
        }
    }
    

Varje sekund av testet körs den här metoden. Koden kontrollerar först värdet som CheckTheAnswer() returnerar.

  • Om alla svar är korrekta är det värdet trueoch frågesporten avslutas:

    • Timern stannar.
    • Ett gratulationsmeddelande visas.
    • Egenskapen Aktiverad för kontrollen startButton är inställd på true så att testdeltagaren kan starta ett nytt test.
  • Om CheckTheAnswer() returnerar falsekontrollerar koden värdet för timeLeft:

    • Om den här variabeln är större än 0 subtraherar timern 1 från timeLeft-. Den uppdaterar också egenskapen Text för timeLabel-kontrollen för att visa testtagaren hur många sekunder som återstår.
    • Om ingen tid återstår stoppas timern och ändrar timeLabel text till Time's up! En meddelanderuta meddelar att frågesporten är över och svaren avslöjas. Startknappen blir tillgänglig igen.

Starta timern

Om du vill starta timern när testet startar lägger du till tre rader i slutet av StartTheQuiz()-metoden, som följande exempel visar.

/// <summary>
/// Start the quiz by filling in all of the problem 
/// values and starting the timer. 
/// </summary>
public void StartTheQuiz()
{
    // Fill in the addition problem.
    // Generate two random numbers to add.
    // Store the values in the variables 'addend1' and 'addend2'.
    addend1 = randomizer.Next(51);
    addend2 = randomizer.Next(51);

    // Convert the two randomly generated numbers
    // into strings so that they can be displayed
    // in the label controls.
    plusLeftLabel.Text = addend1.ToString();
    plusRightLabel.Text = addend2.ToString();

    // 'sum' is the name of the NumericUpDown control.
    // This step makes sure its value is zero before
    // adding any values to it.
    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);
    int temporaryQuotient = 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();
}

När testet startar anger den här koden variabeln timeLeft till 30 och egenskapen Text för kontrolelementet timeLabel till 30 sekunder. Sedan startar Start()-metoden för Timer-kontrollen nedräkningen.

Kör din app

  1. Spara programmet och kör det.

  2. Välj Starta frågesporten. Timern börjar räknas ned. När tiden tar slut avslutas frågesporten och svaren visas.

  3. Starta ett nytt test och ge rätt svar på matematiska problem. När du svarar korrekt inom tidsgränsen öppnas en meddelanderuta, startknappen blir tillgänglig och timern stoppas.

    Skärmbild som visar ett slutfört test med 19 sekunder kvar. Knappen Starta frågesporten är tillgänglig.

Nästa steg

Gå vidare till nästa handledning för att lära dig hur du anpassar din mattequiz.