线程运行时C ++按下箭头键

时间:2018-08-17 20:12:53

标签: c++ multithreading

我正在尝试用C ++制作蛇游戏。我有一个线程,可按用户使用箭头键指定的方向移动蛇的头部。如果按向上箭头键,我需要头部向上移动并继续移动(这是通过线完成的),而无需按箭头键。

问题是我无法使键盘输入与线程一起工作,它的一个功能或另一个功能都不能工作,

键盘输入功能:

void moveSnake()
{
    while(true)
    {
        int key = getch();
        switch(key)
        {
        case 72:
        {
              //UP
              break;
        }
        case 80:
        {
              // DOWN
              break;
        }
        case 77:
        {
             // RIGHT
              break;
        }
        case 75:
        {
             // LEFT
              break;
        }
    }
}

线程功能:

void thread_handler()
{
    while(true)
    {
        // Move the snake
        Sleep(500);
    }
}

这是我创建线程并调用键盘功能的地方

int main()
{
    moveSnake();
    thread t(thread_handler);
    t.join();
    return 0;
}

我尝试过

  • 将moveSnake()放入线程
  • 在没有线程的情况下执行thread_handler函数
  • 试图将两个函数放在单独的线程中
  • 尝试使用所有这些可能的解决方案切换顺序

但是这些都不起作用。

我需要一种在同时运行线程的同时获取箭头键的密码的方法

2 个答案:

答案 0 :(得分:3)

像编译器一样,从头到尾遵循源代码。调试器可以帮助您逐步进行调试。您在主线程中陷入了永无止境的循环。之后发生的事情并不重要,因为您永远不会到达那里。

即使切换事物的顺序,您仍然会有一个永无止境的循环,因此调用它后您将无法正确加入。

您需要阅读一些基本的线程课程。 仅仅因为您正在使用线程并不意味着您可以停止担心循环是否退出。循环应始终具有某些退出条件。

对于您的程序,我假设您要启动一个线程来处理输入,锁定某种存储方式并读取按键。回到您的主线程中,您可能想循环直到出现退出信号,锁定并获取存储的按键/命令(也许使用线程安全队列?)并对它做出反应。

这是一个非常简单且天真的示例:

#include <mutex>
#include <thread>
#include <queue>

#include <conio.h>
#include <iostream>

class Application
{
public:

    void Run()
    {
        // Start input thread
        if (m_inputThread.joinable())
        {
            Shutdown();
        }

        auto thread = std::thread(std::bind(&Application::InputThreadProc, this));
        m_inputThread.swap(thread);

        while (!m_shutdown)
        {
            // React to the queued input, including checking for shutdown
            // I'm just going to ignore the complex issue of timing
            std::this_thread::sleep_for(std::chrono::milliseconds(33));
            std::lock_guard<std::mutex> lock(m_mutex);
            if( !m_keysPressed.empty() )
            {  
                auto key = m_keysPressed.front();
                m_keysPressed.pop();

                switch (key)
                {
                case 75:
                    m_shutdown = true;
                default:
                    std::cout << "I saw a key: " << key << std::endl;
                    break;
                }
            }
        }

        Shutdown();
    }

private:

    std::mutex      m_mutex;
    std::queue<int> m_keysPressed;
    bool            m_shutdown = false;
    std::thread     m_inputThread;

    void Shutdown()
    {
        if (m_inputThread.joinable())
        {
            m_inputThread.join();
        }
    }

    void InputThreadProc()
    {
        while (!m_shutdown)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(33));
            std::lock_guard<std::mutex> lock(m_mutex);

            // OS Specific. Better means of getting localized input exist.
            // Also, timing is an issue. Is the key pressed when we are trying to read.
            // Input is a complex topic and many libraries for it exist
            m_keysPressed.emplace(_getch());
        }
    }
};

int main()
{
    Application application;
    application.Run();

    return 0;
}

答案 1 :(得分:1)

将主电源的顺序更改为

int main()
{
    thread t(thread_handler);
    moveSnake();
    t.join();
    return 0;
}

这样,线程将在您的输入循环(这是一个无穷循环)之前启动。确保您将t.join()留在最后。

这样说,您需要创建一个线程和输入循环都退出的方法。当前两者都是无限循环。