我正在尝试用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;
}
我尝试过
但是这些都不起作用。
我需要一种在同时运行线程的同时获取箭头键的密码的方法
答案 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()
留在最后。
这样说,您需要创建一个线程和输入循环都退出的方法。当前两者都是无限循环。