2014-12-19 5 views
1

저는 프로그래밍에있어 C# newbie_and입니다. 카운트 다운 타이머로 수학 퀴즈 앱을 만들려고합니다.C# 카운트 다운 타이머 재설정 - DispatcherTimer- 창문에 앱 저장

나는 사용자가 시작 버튼을 클릭 할 때마다 방정식을 생성하고 응답하는데 최대 60 초를줍니다. 사용자는 자신의 대답이 틀리거나 옳지 않은지에 대한 답변을하고 새로운 방정식을 위해 다시 클릭 할 수 있습니다. 그래서 사용자가 새로운 임의의 방정식을 볼 때마다 타이머를 재설정하고 싶습니다. 지금까지는 60 초의 시간 간격이 경과했을 때만 재설정 할 수 있었지만 제대로 작동하지 않는 경우도 있었으며 때로는 60 초 대신 59 초 또는 58 초를 표시하는 경우도있었습니다.

지금까지 다른 질문을 읽지 않았 으면 많은 도움이되지 못했습니다. 타이머가 나를 혼란스럽게한다. 또한 코드를 더 간단하고 우아하게 만들기위한 제안을 수락합니다. 당신이 여기에 적어도 두 가지 중요한 문제가 나에게 보인다

EquationView.xaml.cs

public sealed partial class EquationView : Page 
    { 
     DispatcherTimer timer = new DispatcherTimer(); 
     int tick = 60; 
     int result; 

     public EquationView() 
     { 
      this.NavigationCacheMode = NavigationCacheMode.Enabled; 
      this.InitializeComponent(); 
     } 

     private void startButton_Click(object sender, RoutedEventArgs e) 
     { 
      // Once clicked then disabled 
      startButton.IsEnabled = false; 

      // Enable buttons required for answering 
      resultTextBox.IsEnabled = true; 
      submitButton.IsEnabled = true; 

      var viewModel = App.equation.GenerateEquation(); 
      this.DataContext = viewModel; 
      result = App.equation.GetResult(viewModel); 

      timer.Interval = new TimeSpan(0, 0, 0, 1); 
      //timer.Tick += new EventHandler(timer_Tick); 
      timer.Tick += timer_Tick; 
      timer.Start(); 
      DateTime startTime = DateTime.Now; 

      // Reset message label 
      if (message.Text.Length > 0) 
      { 
       message.Text = ""; 
      } 

      // Reset result text box 
      if (resultTextBox.Text.Length > 0) 
      { 
       resultTextBox.Text = ""; 
      } 
     } 

     private void timer_Tick(object sender, object e) 
     { 
      Countdown.Text = tick + " second(s) "; 
      if (tick > 0) 
       tick--; 
      else 
      { 
       Countdown.Text = "Times Up"; 
       timer.Stop(); 
       submitButton.IsEnabled = false; 
       resultTextBox.IsEnabled = false; 
       startButton.IsEnabled = true; 
       tick = 60; 
      } 

     } 

     private void submitButton_Click(object sender, RoutedEventArgs e) 
     { 
      timer.Stop(); 
      submitButton.IsEnabled = false; 
      resultTextBox.IsEnabled = false; 

      if (System.Text.RegularExpressions.Regex.IsMatch(resultTextBox.Text, "[^0-9]")) 
      { 
       MessageDialog msgDialog = new MessageDialog("Please enter only numbers."); 
       msgDialog.ShowAsync(); 

       resultTextBox.Text.Remove(resultTextBox.Text.Length - 1); 

       //Reset buttons to answer again 
       submitButton.IsEnabled = true; 
       resultTextBox.IsEnabled = true; 
       timer.Start(); 
      } 
      else 
      { 
       try 
       { 
        int userinput = Int32.Parse(resultTextBox.Text); 

        if (userinput == result) 
        { 
         message.Text = "Bingo!"; 
         App.player.UpdateScore(); 
         startButton.IsEnabled = true; 
        } 
        else 
        { 
         message.Text = "Wrong, sorry..."; 
         startButton.IsEnabled = true; 
        } 
       } 
       catch (Exception ex) 
       { 
        MessageDialog msgDialog = new MessageDialog(ex.Message); 
        msgDialog.ShowAsync(); 
        submitButton.IsEnabled = true; 
        resultTextBox.IsEnabled = true; 
        timer.Start(); 
       } 


      } 
     } 
+0

방금 ​​방정식을 생성하기 전에 Timer.Stop을 넣으십시오. –

답변

2

:

여기 내 코드입니다. 하나는 Windows 스레드 스케줄러의 부정확성으로 인해 타이머가 사용자에게 60 초 이상을 제공 할 가능성이 높다는 것입니다 (즉, 각 틱은 1 초보다 약간 간격으로 발생합니다). 다른 (귀하의 질문에 더 관련이있다)은 타이머가 경과 한 경우를 제외하고는 tick 값을 60으로 재설정하지 않는다는 것입니다.

후자의 문제에 대해서는 타이머를 시작했을 때 단순히 카운트 다운 값을 재설정하는 것이 좋습니다. 타이머를 중지하는 모든 곳을 기억하려고하는 것이 아닙니다.

는 문제를 해결하려면 첫 번째 문제는 전부 tick 필드를 제거하고 더 같은보고 코드를 변경 :

static readonly TimeSpan duration = TimeSpan.FromSeconds(60); 
    System.Diagnostics.Stopwatch sw; 

    private void startButton_Click(object sender, RoutedEventArgs e) 
    { 
     // Once clicked then disabled 
     startButton.IsEnabled = false; 

     // Enable buttons required for answering 
     resultTextBox.IsEnabled = true; 
     submitButton.IsEnabled = true; 

     var viewModel = App.equation.GenerateEquation(); 
     this.DataContext = viewModel; 
     result = App.equation.GetResult(viewModel); 

     sw = System.Diagnostics.Stopwatch.StartNew(); 
     timer.Interval = new TimeSpan(0, 0, 0, 1); 
     timer.Tick += timer_Tick; 
     timer.Start(); 

     // Reset message label 
     if (message.Text.Length > 0) 
     { 
      message.Text = ""; 
     } 

     // Reset result text box 
     if (resultTextBox.Text.Length > 0) 
     { 
      resultTextBox.Text = ""; 
     } 
    } 

    private void timer_Tick(object sender, object e) 
    { 
     if (sw.Elapsed < duration) 
     { 
      Countdown.Text = (int)(duration - sw.Elapsed).TotalSeconds + " second(s) "; 
     } 
     else 
     { 
      Countdown.Text = "Times Up"; 
      timer.Stop(); 
      submitButton.IsEnabled = false; 
      resultTextBox.IsEnabled = false; 
      startButton.IsEnabled = true; 
     } 
    } 

이 방법, 그것은 중요하지 않습니다를 정확히 틱 이벤트가 발생하면 코드는 여전히 실제 남은 시간을 계산하고이를 디스플레이에 사용하고 시간이 끝났는지 여부를 알 수 있습니다.

+0

피터 감사합니다! 그러나 startButton을 클릭하면 2-3 초의 지연이 있습니다. 어떻게 향상시킬 수 있습니까? – D3v

+0

잘 모르겠습니다. 어떤 타이밍 관련 코드도 거의 지연을 일으키지 않습니다. 2-3 초를 신경 쓰지 마십시오. 따라서 지연이있는 경우, 그것은'App.equation' 객체에서 가장 가능성이 높습니다. 기본 타이머 문제가 해결되었으므로 지연 관련 새로운 질문을 게시 할 수 있습니다. 문제의 범위를 좁히고 문제를 신뢰할 수있는 좋은 코드 예제를 제공하십시오. –