std :: cout在我的keyPressed字符串中打印多余的字符,可能是由于“ \ r”所致,例如,如果keyPressed =“ Right arrow”,当我按下向上箭头时,它将打印“ keyPressed = Up arrowoww”,然后,当我再次按向右箭头时,它将再次正常打印“ keyPressed =向右箭头”,但是如果我按除“向右箭头”以外的任何箭头键,它将在末尾打印一些不需要的多余字符
game.cpp
#include "engine.h"
#include <iomanip>
Engine eng;
int main() {
while (eng.isRunning) {
eng.getInput();
std::cout << std::setw(5);
std::cout << "\r X = " << eng.playerX;
std::cout << "| Y = " << eng.playerY;
std::cout << "| KEY = " << eng.keyPressed;
Sleep(100);
}
return 0;
}
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <iostream>
#include <Windows.h>
#include <string>
class Engine {
public:
// Game
bool isRunning = true;
bool gettingInput = true;
// Player
int playerX = 1;
int playerY = 1;
char playerModel = 'P';
// Test / Debug
std::string keyPressed;
// Functions
char getInput() {
// Gets arrow keys states
while (this->gettingInput) {
this->keyPressed = "";
if (GetAsyncKeyState(VK_RIGHT)) {
// Right arrow key
this->playerX++;
this->keyPressed = "Right arrow";
break;
}
else if (GetAsyncKeyState(VK_LEFT)) {
// Left arrow key
this->playerX--;
this->keyPressed = "Left arrow";
break;
}
else if (GetAsyncKeyState(VK_UP)) {
// Up arrow key
this->playerY++;
this->keyPressed = "Up arrow";
break;
}
else if (GetAsyncKeyState(VK_DOWN)) {
// Down arrow key
this->playerY--;
this->keyPressed = "Down arrow";
break;
}
else if (GetAsyncKeyState(VK_END)) {
exit(0);
}
Sleep(255);
}
}
};
#endif
解决此问题的最佳/最简单方法? 我搜索并测试了3天,但没有找到任何东西,请帮帮我。
答案 0 :(得分:2)
由于您要覆盖前一个输出,因此当您打印较短的字符串时,仍会显示前一个输出中的多余字符。将\r
替换为\n
,以查看实际输出的内容。
您可以在键名后输出一些空格,以覆盖多余的字符并清除它们。
答案 1 :(得分:0)
在查看了您提供的代码后,我确实发现了代码设计中的一些问题或疑虑:我将对其进行分解,并解释一些我认为可以提高代码质量的方面。我将从您的main.cpp开始,然后转到您的Engine类。
您最初有这个:
#include "engine.h" #include <iomanip> Engine eng; int main() { while (eng.isRunning) { eng.getInput(); std::cout << std::setw(5); std::cout << "\r X = " << eng.playerX; std::cout << "| Y = " << eng.playerY; std::cout << "| KEY = " << eng.keyPressed; Sleep(100); } return 0; }
我看到的第一个主要问题是您已经在全局级别声明了Engine eng
。我们可以通过
#include "engine.h"
#include <iostream>
#include <iomanip>
int main() {
Engine eng; // declare it here as the first object in main; now it has local
// scope within main's function and is now in Automatic Storage
// instead of Global Storage.
while( ... ) {
// ....
}
return 0;
};
下一个问题从main函数中的while循环的条件表达式开始。 您当前有:
while( engine.isRunning ) { //... }
可以,但这与Engine class's
设计有关。在这里,您将提供任何人都可以访问的public member
。因此,让我们看一下您的类声明/定义;您当前拥有:
#ifndef ENGINE_H #define ENGINE_H #include <iostream> #include <Windows.h> #include <string> class Engine { public: // Game bool isRunning = true; bool gettingInput = true; // Player int playerX = 1; int playerY = 1; char playerModel = 'P'; // Test / Debug std::string keyPressed; // Functions char getInput() { // ... } }; #endif
在这里,您应该保护您的数据成员,并对其具有访问修饰符功能:
#ifndef ENGINE_H
#define ENGINE_H
#include <iostream>
#include <Windows.h>
#include <string>
class Engine {
private:
bool isRunning;
bool gettingInput;
// Player
int playerX;
int playerY;
char playerModel;
// Test / Debug
std::string keyPressed;
public:
Engine() :
isRunning( false ),
isGettingInput( false ),
playerX( 1 ),
playerY( 1 ),
playerModel( 'P' )
{}
void run() { isRunning = true; // set or call other things here... }
// Since we protected our members variables by making them private,
// we now need some access functions to retrieve and modify them.
bool isActive() const { return isRunning; } // make this const so it doesn't change anything
void toggleIsActive() { isRunning = !isRunning; }
bool retrievingInput() const { return isGettingInput; }
void toggleRetrievingInput() { isGettingInput = !isGettingInput; }
int getPlayerX() const { return playerX; }
void setPlayerX( int newX ) { playerX = newX; }
int getPlayerY() const { return playerY; }
void setPlayerY( int newY ) { playerY = newY; }
// set both in one function call
void setPlayerPosition( int newX, int newY ) {
playerX = newX;
playerY = newY;
}
char getPlayerModel() const { return playerModel; }
// don't know if you want to change this: uncomment if you do
// void setPlayerModel( char c ) { playerModel = c; }
std::string& getPressedKey() const { return keyPressed; }
char getInput() { // ... }
};
这应该修复您的类的界面设计。此处唯一的主要区别是,我默认将Boolean
成员变量设置为false
,因为通常在首次启动Engine
时,该变量当前尚未运行。因此,要解决此问题,我们可以调用将触发此事件的公共运行函数。所以main看起来像这样:
int main () {
Engine eng;
eng.run(); // this now starts the engine sets the flag to true
while (...) { //... }
return 0;
}
但是,在您的Engine's
getInput()
函数中,我也几乎没有发现任何问题,因此让我们来看一下。
char getInput() { // Gets arrow keys states while (this->gettingInput) { this->keyPressed = ""; if (GetAsyncKeyState(VK_RIGHT)) { // Right arrow key this->playerX++; this->keyPressed = "Right arrow"; break; } else if (GetAsyncKeyState(VK_LEFT)) { // Left arrow key this->playerX--; this->keyPressed = "Left arrow"; break; } else if (GetAsyncKeyState(VK_UP)) { // Up arrow key this->playerY++; this->keyPressed = "Up arrow"; break; } else if (GetAsyncKeyState(VK_DOWN)) { // Down arrow key this->playerY--; this->keyPressed = "Down arrow"; break; } else if (GetAsyncKeyState(VK_END)) { exit(0); } Sleep(255); } }
第一部分是while loop's
条件语句和您的类的成员。最初,您默认情况下将此设置为true
,但我在代码中没有看到此值被更新的地方。我们不需要更改此成员,但是修复很简单,因为我们可以通过公共接口调用更改此成员。由于我已默认设置您的isGettingInput
false
;现在,您可以在进入while循环之前在此函数中进行设置。我看到的最后一个问题是,在main's
while循环中调用此函数时;该函数从不返回值,并且永远不会使用返回值。
关于cout
用户:1201programalarm的bug的实际问题,已经为您解答了很多。只是以为我会为您的代码提供更多帮助。