【问题标题】:Struggling to implement a timer to my C# CONSOLE Typing Game努力为我的 C# CONSOLE 打字游戏实现计时器
【发布时间】:2019-06-08 22:50:54
【问题描述】:

我当前的打字游戏功能(代码如下)的目标是从 10(困难)、20(中等)或 30(简单)开始倒计时,这取决于游戏开始后用户的难度选择。一旦倒计时达到零或用户用完生命,游戏就结束了(这会停止倒计时)。游戏正常启动,显示用户输入的第一个单词,并从 10 开始倒计时。我目前的问题是我无法弄清楚如何停止计时器从 0 倒计时。我尝试使用 t .Change(Timeout.Infinite , Timeout.Infinite) 并检查 timeLeft == 0 时没有占上风。我真的觉得我想得太多了(或想得不够),非常感谢一些帮助或朝着正确方向轻推!

我的代码如下:

    class Program
{
    // List of words to be typed
    public static string[] words = { "some", "side", "add", "another", "would", "book" ,"water", "came" ,"your" ,"big","both", "from", "learn", "been", "me" ,"school" ,"land", "took", "place",
            "try", "line", "tell", "earth", "can", "do","children", "without", "my", "must", "take", "follow", "year", "is", "being", "different", "miss", "could", "on", "he", "open", "night", "were",
            "line","said", "around", "an", "plant", "know", "set","been", "life","young","of", "face", "we", "hand", "while", "is", "white", "call", "live","may", "study","after" ,"down", "him", "now", "different",
            "could", "over", "work","all", "mean","begin","go","fall", "really", "oil", "before","into","one","name","has","a", "well", "got","something","turn" };
    // Keeps track of words array
    public static int numWords = 88;
    public static int correctWords = 0;
    // Initialize our random number generator
    public static Random rand = new Random();
    // Handles user input
    public static string userInput = "";
    public static string endGameChoice = "";
    // Handles gamestate variables
    public static bool gameActive = false;
    public static int numLives = 0;
    public static int timeLeft;
    public static System.Threading.Timer t;


    // Entry Point
    static void Main(string[] args)
    {
        // Start the game
        Start();
    }

    // Handles gameplay
    static void Play()
    {
        // Assigns the current word to any random word in
        // the words array
        string currentWord = words[rand.Next(0, 88)];
        // Print the current word separated by lines
        Console.WriteLine("********");
        Console.WriteLine(currentWord);
        Console.WriteLine("********");
        // While the answser is incorrect/empty
        while (!userInput.Equals("exit"))
        {
            // Reads user input
            userInput = Console.ReadLine();
            if (userInput.Equals(""))
            {
                Play();
            }
            // Checks if userInput is equal to current word
            if (!(userInput.Equals(currentWord)))
            {
                // If incorrect, display loss of life
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Incorrect!!!");
                Console.WriteLine("Lives: " + numLives);
                numLives--; // Take a life away
                Console.ResetColor();

            }
            if (numLives == -1)
            {
                outOfLives();
            }
            if (userInput.Equals(currentWord))
            {
                correctWords++;
                Play();
            }
        }
        if (userInput.Equals("exit"))
        {
            Environment.Exit(0);
        }

    }
    // Function for running out of lives
    private static void outOfLives()
    {
        Console.WriteLine("Game over! You typed " + correctWords + " words correctly!");
        Console.WriteLine("Type anything and press enter to retry, Press Escape to Quit!");

        var endGameKey = Console.ReadKey();

        if (endGameKey.Key == ConsoleKey.Escape)
        {
            Environment.Exit(0);
        }
        if (endGameKey.Key == ConsoleKey.Enter)
        {
            restartGame();
        }
        else
        {
            outOfLives();

        }

    }
    // Function for running out of time
    private static void outOfTime()
    {
        Console.WriteLine("Out of time! You typed " + correctWords + " words correctly!");
        Console.WriteLine("Type anything and press enter to retry, Press Escape to Quit!");

        var endGameKey = Console.ReadKey();

        if (endGameKey.Key == ConsoleKey.Escape)
        {
            Environment.Exit(0);
        }
        if (endGameKey.Key == ConsoleKey.Enter)
        {
            restartGame();
        }
        else
        {
            outOfTime();
        }

    }

    // Prompts user for input for difficulty along with game instructions
    static void StartMessage()
    {
        Console.WriteLine("Welcome to my Typing Practice App!");
        Console.WriteLine("Type the word displayed as fast as you can");

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("Difficulties are listed from hardest to easiest");
        Console.WriteLine();
        Console.WriteLine("Select a difficulty( 1 ,2 , or 3 ): ");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.WriteLine("-- Press ENTER --");
        Console.WriteLine("***  Satan Himself  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("-- Type 1 --)");
        Console.WriteLine("***  Software Engineer  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("-- Type 2 --)");
        Console.WriteLine("***  Social Media Fanatic  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("-- Type 3 --)");
        Console.WriteLine("*** Filthy Peasant ***");
        Console.WriteLine();
        Console.ResetColor();

        string difficultyChoice = Console.ReadLine();
        switch (difficultyChoice)
        {
            case "1":
                numLives = 1;
                Console.WriteLine("You have 2 lives! Good luck!");
                timeLeft = 10;
                break;
            case "2":
                numLives = 3;
                Console.WriteLine("You have 4 lives! Good luck!");
                timeLeft = 20;
                break;
            case "3":
                numLives = 5;
                Console.WriteLine("You have 6 lives! Good luck!");
                timeLeft = 30;
                break;

            default:
                numLives = 0;
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.WriteLine("Miss one and you're done!!!!!");
                Console.ResetColor();
                timeLeft = 10;
                break;
        }
    }
    public static void restartGame()
    {
        Console.Clear();
        //numLives = 5;
        numWords = words.Length;
        correctWords = 0;
        Start();
    }

    public static void SetTimer(Object o)
    {
        timeLeft--;
        Thread.Sleep(1000);
        Console.WriteLine(timeLeft);
        if (timeLeft == 0)
        {
            outOfTime();
        }

    }


    public static void Start()
    {
        // Display start message
        StartMessage();
        gameActive = true;
        t = new System.Threading.Timer(SetTimer, null, 0, 1250);
        // While user wants to play
        while (!userInput.Equals("exit"))
        {
            // While the game is active
            while (gameActive == true)
            {
                // Start the game
                Play();
            }
        }
        if (userInput.Equals("exit"))
        {
            Environment.Exit(0);
        }

    }
}

}

【问题讨论】:

  • 我在 SetTimer 方法中看到了这个:Console.WriteLine(timeLeft) - 你看到输出了吗?
  • 你为什么在回调中调用Thread.Sleep(1000);?你也不会在任何地方停止它
  • @toni 我得到了一个正常的倒计时显示,直到它达到 0,这就是它进入负数的时候。我正在用它来测试倒计时
  • @TheGeneral 好点,之前的尝试忽略了这一点。我删除了它
  • 也许将一个对象传递给 SetTimer,并将 timeLeft 作为属性 - 这可能是一个上下文/范围问题,虽然很奇怪,因为 timeLeft 被声明为静态。

标签: c# .net


【解决方案1】:

您不需要程序计时器或线程来拥有游戏计时器。只记录游戏开始的时间:

//During initialization
var startTime = DateTime.Now;

任何时候你想显示或使用计时器,计算它:

var timerValue = DateTime.Now - startTime;
Console.WriteLine("Time elapsed: {0} seconds", timerValue.Seconds);

【讨论】:

  • 这不会中断游戏循环 (Console.ReadLine())。
  • 计时器也不会。当定时器中断主线程时,控制台仍然会完成原始ReadLine的数据输入。在此期间,定时器代码将阻塞。试试吧。 OP 将需要忍受这一点,或者在主线程中使用非阻塞调用重新设计。
  • 嗯。好点子。超时过后,您至少可以半优雅地处理响应。但最终同意。需要重新设计。
  • @JohnWu 谢谢你的回复,我一定会试试的。
【解决方案2】:

尝试使用this。如果你能让协程工作,协程应该可以解决你的问题。

【讨论】:

  • YESSSSS 谢谢!我不知道为什么我没想到!我现在尝试实现协程
  • 这是一个相当低质量的答案,它本质上只是一个链接,没有解释它们是什么或如何解决问题,也没有解释当前问题可能是什么跨度>
【解决方案3】:

你可以这样使用Timer。

它适合你

var timer2 = new Timer();
timer2.Elapsed += (o, e) =>
{
    Console.WriteLine("Time Elapsed {0}", e.SignalTime);
    timer2.Stop();
};
timer2.Interval = 1000;
timer2.Start();

【讨论】:

  • 非常感谢您的回复,我一定会试试这个方法
【解决方案4】:

作为对出现的问题的直接修复(计时器低于 0),您需要在不再需要计时器时停止它。为此,请使用以下行:

t.Change(Timeout.Infinite, Timeout.Infinite);

您可以将此行添加到 outOfLivesoutOfTime 方法的开头:

private static void outOfLives()
{
    t.Change(Timeout.Infinite, Timeout.Infinite);
    Console.WriteLine("Game over! You typed " + correctWords + " words correctly!");
    ...

还有……

private static void outOfTime()
{
    t.Change(Timeout.Infinite, Timeout.Infinite);
    Console.WriteLine("Out of time! You typed " + correctWords + " words correctly!");
    ...

编辑:对不起。只需重新阅读您的问题并意识到您已经尝试过这条线。你把它放在正确的地方了吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2023-03-29
    • 1970-01-01
    • 2020-01-31
    • 2018-01-19
    • 1970-01-01
    相关资源
    最近更新 更多