Возвратный удар - PullRequest
       20

Возвратный удар

0 голосов
/ 22 декабря 2018

std :: cout печатает дополнительные символы в моей строке keyPressed, возможно, из-за "\ r", например, если keyPressed = "Стрелка вправо", когда я нажимаю стрелку вверх, она печатает "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 дней, но ничего не нашел, пожалуйста, помогите мне.

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

После просмотра предоставленного вами кода я вижу несколько проблем или проблем с дизайном кода: я разобью его и объясню некоторые вещи, которые, как я вижу, могут улучшить качество вашего кода.Я начну с вашего 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;
};

Следующая проблема начинается с условного выражения 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 уже почти ответил на этот вопрос для вас.Просто подумал, что помогу тебе немного больше с твоим кодом.

0 голосов
/ 22 декабря 2018

Поскольку вы перезаписываете предыдущий вывод, при печати более короткой строки дополнительные символы из предыдущего вывода по-прежнему отображаются.Замените \r на \n, чтобы увидеть, что на самом деле выводится.

Вы можете вывести несколько пробелов после имени ключа, чтобы перезаписать эти лишние символы пробелами и удалить их.

...