我的C#(Windows窗体)反应时测试有问题

我的C#(Windows窗体)反应时测试有问题,c#,winforms,C#,Winforms,我对C#比较陌生,从一月份起才真正开始使用这种语言进行编码。对于我的课程作业,我必须创建一个包含反应时测试的程序。我花了大约一周的时间来完全理解代码应该如何工作,这就是我迄今为止所做的: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text;

我对C#比较陌生,从一月份起才真正开始使用这种语言进行编码。对于我的课程作业,我必须创建一个包含反应时测试的程序。我花了大约一周的时间来完全理解代码应该如何工作,这就是我迄今为止所做的:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
using System.Threading;
using System.Diagnostics;

namespace WonderWallsApplication
{
    public partial class ReactionTimeTestForm : Form
    {
        Random random = new Random();
        Stopwatch stopwatch = new Stopwatch();
        int TimesTested = 0;
        int ReactionTime1 = 0;
        int ReactionTime2 = 0;
        int ReactionTime3 = 0;
        bool ButtonPressed = false;
        int ReactionTime { get; set; }

        public ReactionTimeTestForm()
        {
            InitializeComponent();
            btnReactionButton.BackColor = Color.Red;

        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        public void button1_Click_1(object sender, EventArgs e)
        {

            if (TimesTested == 0)
            {
                ReactionTest();
                if (ButtonPressed == true)
                {
                    ReactionTime1 = ReactionTime;
                    TimesTested = TimesTested + 1;
                    ButtonPressed = false;
                }
                else
                {

                }
            }
            else if (TimesTested == 1)
            {
                ReactionTest();
                if (ButtonPressed == true)
                {
                    ReactionTime2 = ReactionTime;
                    TimesTested = TimesTested + 1;
                    ButtonPressed = false;
                }
                else
                {

                }
            }
            else if (TimesTested == 2)
            {
                ReactionTest();
                if (ButtonPressed == true)
                {
                    ReactionTime3 = ReactionTime;
                    TimesTested = TimesTested + 1;
                    ButtonPressed = false;
                }
                else
                {

                }

            }
            else if (TimesTested == 3)
            {
                MessageBox.Show("Your times were: " + Convert.ToString(ReactionTime1) + ", " + Convert.ToString(ReactionTime2) + ", " + Convert.ToString(ReactionTime3));
            }
            else
            {

            }



        }


        public void btnReactionButton_Click(object sender, EventArgs e)
        { 
            stopwatch.Stop();
            btnReactionButton.BackColor = Color.Red;
            btnReactionButton.Text = "Your time was " + stopwatch.ElapsedMilliseconds+ "ms milliseconds";
            ReactionTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);
            ButtonPressed = true;


        }

        public void ReactionTest()
        {
            stopwatch.Reset();
            btnReactionButton.Text = "3";
            Task.Delay(1000).Wait();
            btnReactionButton.Text = "2";
            Task.Delay(1000).Wait();
            btnReactionButton.Text = "1";
            Task.Delay(1000).Wait();
            btnReactionButton.Text = "0";
            Task.Delay(1000).Wait();
            btnReactionButton.Text = "Press this button when it turns green";
            Task.Delay(random.Next(3000, 10000)).Wait();
            btnReactionButton.Visible = true;
            stopwatch.Start();
            btnReactionButton.BackColor = Color.Green;
            btnReactionButton.Text = "Click Now!";

        }
    }
    }
我的问题是,当我运行代码时,它会运行反应时测试4次,而不是3次。它确实记录了所有前3个值,但出于某种原因,我写了一些东西,可能会导致它再次运行。调试程序时,我认为它与第一次有关,它会记录时间,但不会将其算作一次按下。我真的不知道如何解决这个问题。希望你们中的一个能。我对每个if语句进行了修改,添加了一个timetested语句。例如:

if (TimesTested == 0)
        {
            ReactionTest();
            TimesTested = TimesTested + 1;
            if (ButtonPressed == true)
            {
                ReactionTime1 = ReactionTime;
                ButtonPressed = false;

            }
            else
            {

            }
        }

但所有这些都是它执行了3次测试,但它输出“你的次数是0,x,x”。X只是记录的反应速度的一个数字

我很难理解你的逻辑。下面是一个更简单的代码版本:

Random random = new Random();
Stopwatch stopwatch = new Stopwatch();
List<long> timesTested = new List<long>();

private void buttonStart_Click(object sender, EventArgs e) {     
  stopwatch.Reset();
  for (int i = 4; i > 0; --i) {
    btnReactionButton.Text = i.ToString();
    Task.Delay(500).Wait();
    btnReactionButton.Invalidate();
  }
  btnReactionButton.Text = "Press this button when it turns green";
  Task.Delay(random.Next(3000, 5000)).Wait();
  stopwatch.Start();
  btnReactionButton.BackColor = Color.Green;
  btnReactionButton.Text = "Click Now!";   
}

private void btnReactionButton_Click(object sender, EventArgs e) {
  if (stopwatch.IsRunning) {
    stopwatch.Stop();
    timesTested.Add(stopwatch.ElapsedMilliseconds);
    btnReactionButton.BackColor = Color.Red;
    btnReactionButton.Text = string.Format("Your time was {0} milliseconds",
                                           timesTested[timesTested.Count - 1]);
    if (timesTested.Count == 3) {
      MessageBox.Show("Your times were: " + String.Join(", ", timesTested.ToArray()));
    }
  }
}
Random Random=new Random();
秒表秒表=新秒表();
List timesTested=新列表();
私有无效按钮开始单击(对象发送者,事件参数e){
秒表复位();
对于(int i=4;i>0;--i){
btnReactionButton.Text=i.ToString();
Task.Delay(500.Wait();
btnReactionButton.Invalidate();
}
btnReactionButton.Text=“当按钮变绿时按下此按钮”;
Task.Delay(random.Next(30005000)).Wait();
秒表。开始();
btnReactionButton.BackColor=Color.Green;
btnReactionButton.Text=“立即单击!”;
}
私有void btnReactionButton_单击(对象发送者,事件参数e){
if(秒表正在运行){
秒表;
timesTested.Add(秒表时间延迟毫秒);
btnReactionButton.BackColor=Color.Red;
btnReactionButton.Text=string.Format(“您的时间为{0}毫秒”,
timesTested[timesTested.Count-1]);
如果(timesTested.Count==3){
Show(“您的时间是:”+String.Join(“,”,timesTested.ToArray());
}
}
}
不过,您的程序确实存在一个重大缺陷。用户可以在停止按钮变为绿色之前单击它,当按钮变为绿色时,它将记录先前的鼠标单击。您应该隐藏按钮或禁用按钮,直到反应准备就绪。

ReactionTest()
方法在按钮背景变为绿色且标签更改为“立即单击”后立即返回。在第一次调用
ReactionTest()
之后,在第一次检查
ButtonPressed
标志之前,用户没有机会单击按钮,因为检查是在不等待(用户输入)的情况下进行的。所以你是对的,第一次点击不算在内。这就是为什么允许再尝试3次

简单的解决方案是将大部分代码从
button1\u Click\u 1()
移动到
btnReactionButton\u Click()
,并将
async/wait
添加到
ReactionTest()
以防止它阻塞UI并将
btnReactionButton
单击事件排队,当
ReactionTest()
返回时,这些事件将错误地算作有效的单击<代码>按钮按下标志是不必要的

    public void button1_Click_1(object sender, EventArgs e)
    {
        if (TimesTested < 3)
        {
            ReactionTest();
        }
        else
        {
            MessageBox.Show("Your times were: " + Convert.ToString(ReactionTime1) + ", " + Convert.ToString(ReactionTime2) + ", " + Convert.ToString(ReactionTime3));
        }
    }

    public void btnReactionButton_Click(object sender, EventArgs e)
    {
        btnReactionButton.Enabled = false;

        stopwatch.Stop();
        btnReactionButton.BackColor = Color.Red;
        btnReactionButton.Text = "Your time was " + stopwatch.ElapsedMilliseconds + "ms milliseconds";
        ReactionTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);

        if (TimesTested == 0)
        {
            ReactionTime1 = ReactionTime;
            TimesTested = TimesTested + 1;
        }
        else if (TimesTested == 1)
        {
            ReactionTime2 = ReactionTime;
            TimesTested = TimesTested + 1;
        }
        else if (TimesTested == 2)
        {
            ReactionTime3 = ReactionTime;
            TimesTested = TimesTested + 1;
        }
    }

    public async void ReactionTest()
    {
        stopwatch.Reset();
        btnReactionButton.Text = "3";
        await Task.Delay(1000);
        btnReactionButton.Text = "2";
        await Task.Delay(1000);
        btnReactionButton.Text = "1";
        await Task.Delay(1000);
        btnReactionButton.Text = "0";
        await Task.Delay(1000);
        btnReactionButton.Text = "Press this button when it turns green";
        await Task.Delay(random.Next(3000, 10000));
        btnReactionButton.Visible = true;
        stopwatch.Start();
        btnReactionButton.BackColor = Color.Green;
        btnReactionButton.Text = "Click Now!";
        btnReactionButton.Enabled = true;
    }
public void按钮1\u单击1(对象发送者,事件参数e)
{
如果(测试时间<3)
{
反应测试();
}
其他的
{
MessageBox.Show(“您的时间是:“+Convert.ToString(ReactionTime1)+”,“+Convert.ToString(ReactionTime2)+”,“+Convert.ToString(ReactionTime3));
}
}
public void btnReactionButton\单击(对象发送者,事件参数e)
{
btnReactionButton.Enabled=false;
秒表;
btnReactionButton.BackColor=Color.Red;
btnReactionButton.Text=“您的时间为”+stopwatch.elapsedmillesons+“毫秒”;
反应时间=转换为32(秒表时间为毫秒);
如果(测试时间==0)
{
反应时间1=反应时间;
测试时间=测试时间+1;
}
否则如果(测试时间==1)
{
反应时间2=反应时间;
测试时间=测试时间+1;
}
否则如果(测试时间==2)
{
反应时间3=反应时间;
测试时间=测试时间+1;
}
}
公共异步void ReactionTest()
{
秒表复位();
btnReactionButton.Text=“3”;
等待任务。延迟(1000);
btnReactionButton.Text=“2”;
等待任务。延迟(1000);
btnReactionButton.Text=“1”;
等待任务。延迟(1000);
btnReactionButton.Text=“0”;
等待任务。延迟(1000);
btnReactionButton.Text=“当按钮变绿时按下此按钮”;
等待任务。延迟(随机。下一步(3000,10000));
btnReactionButton.Visible=true;
秒表。开始();
btnReactionButton.BackColor=Color.Green;
btnReactionButton.Text=“立即单击!”;
btnReactionButton.Enabled=true;
}

根据@LarsTech给出的提示,我添加了在适当的时候禁用按钮的功能。

事件处理程序被触发4次的原因是,当窗体首次初始化时,它第一次在WinForms中被调用。您可以通过遵循以下解决方案来抑制额外的调用:我应该遵循哪种解决方案,因为此线程上有许多答案。而且,我不是最能理解你所说的话的人。你能更详细地向我解释一下发生了什么事吗。干杯