While循环混淆

While loop confusion

本文关键字:循环 While      更新时间:2023-10-16

问题:

我的while循环未退出。在调试过程中,它非常明确地指出stateID等于3。然而,当我添加std::cout << stateID;时,无论调试器告诉我什么,值1总是被写入控制台

在代码中,我在输入循环之后渲染屏幕。这表明,毫无疑问,输入循环按预期正确退出。此外,如果这还不够的话,它必须退出,stateID才能更改。请不要再讨论嵌套循环的问题。我还在循环之后使用了断点,这些断点被正确命中。

代码:

int main()
{
    stateID = 1;
    GameState* state = new GameStateTitle();
    sf::RenderWindow window(sf::VideoMode(1000, 600), "RPG");
    //GAME LOOP//
    while (stateID != 3)
    {//INPUT//
    sf::Event event;
    while (window.pollEvent(event))
    {
        switch (event.type)
        {
        //Window closed
        case sf::Event::Closed:
            set_next_state(3);
            break;
        }
    }
        change_state(state);
    //RENDERING//
    window.clear(sf::Color::Black);
    state->render(window);
    window.display();
    }
    /////////////
    window.close();
    return 0;
}
void set_next_state(int new_state)
{
    //Set the next state to take place
    next_state = new_state;
}
void change_state(GameState *current_state)
{
    //Check if the next state is null or exit
    if (next_state != 0)
    {
        if (next_state != 3)
            delete current_state;
        //Set the new state
        switch(next_state)
                ...
        }
        stateID = next_state;
        next_state = 0;
    }
}

下面是我的完整代码,以防我错过了一些重要的东西

主要.cpp

#include "GameState.hpp"
int main()
{
    stateID = STATE_TITLE;
    GameState* state = new GameStateTitle();
    sf::RenderWindow window(sf::VideoMode(1000, 600), "RPG");
    //GAME LOOP//
    while (stateID != STATE_EXIT)
    {
        //INPUT//
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type)
            {
            //Window closed
            case sf::Event::Closed:
                set_next_state(STATE_EXIT);
                break;
            }
        }
        ///////////
        ////LOGIC//
        state->logic();
        ///////////
        change_state(state);
        //RENDERING//
        window.clear(sf::Color::Black);
        state->render(window);
        std::cout << stateID;
        window.display();
        /////////////
    }
    ///////////////
    window.close();
    return 0;
}

GameState.hpp

#pragma once
#include <SFML/Graphics.hpp>
//DEFINITIONS ETC//
enum GAME_STATES {
    STATE_NULL,
    STATE_TITLE,
    STATE_BATTLE,
    STATE_EXIT
};
///////////////////
//Game State Class//
class GameState
{
public:
    virtual void input(void) = 0;
    virtual void logic(void) = 0;
    virtual void render(sf::RenderWindow &window) = 0;
};
////////////////////
//FUNCTIONS//
void set_next_state(int new_state);
void change_state(GameState *current_state);
/////////////
//VARIABLES//
static int stateID;
static int next_state;
/////////////
//Title GameState Class//
class GameStateTitle : public GameState
{
private:
    sf::Texture img_title;
    sf::Sprite bgr_title;
public:
    GameStateTitle(void);
    ~GameStateTitle(void);
    void input(void);
    void logic(void);
    void render(sf::RenderWindow &window);
};
/////////////////////////
//Battle GameState Class//
class GameStateBattle : public GameState
{
private:
    sf::Image img_left;
    sf::Image img_right;
public:
    GameStateBattle(void);
    ~GameStateBattle(void);
    void input(void);
    void logic(void);
    void render(sf::RenderWindow &window);
};
//////////////////////////

GameState.cpp

#include "GameState.hpp"
//Game state general functions
void set_next_state(int new_state)
{
    //Set the next state to take place
    next_state = new_state;
}
void change_state(GameState *current_state)
{
    //Check if the next state is null or exit
    if (next_state != STATE_NULL)
    {
        if (next_state != STATE_EXIT)
            delete current_state;
        //Set the new state
        switch(next_state)
        {
        case STATE_TITLE:
            current_state = new GameStateTitle;
            break;
        case STATE_BATTLE:
            current_state = new GameStateBattle;
            break;
        }
        stateID = next_state;
        next_state = STATE_NULL;
    }
}
//The functions of the title state
GameStateTitle::GameStateTitle(void)
{
    //Load texture
    img_title.loadFromFile("title_screen.png");
    //Set texture to background
    bgr_title.setTexture(img_title);
}
GameStateTitle::~GameStateTitle(void)
{
}
void GameStateTitle::input(void)
{
}
void GameStateTitle::logic(void)
{
}
void GameStateTitle::render(sf::RenderWindow &window)
{
    window.draw(bgr_title);
}
//The functions of the battle state
GameStateBattle::GameStateBattle(void)
{
}
GameStateBattle::~GameStateBattle(void)
{
}
void GameStateBattle::input(void)
{
}
void GameStateBattle::logic(void)
{
}
void GameStateBattle::render(sf::RenderWindow &window)
{
}

您有两个while循环。在内部循环退出之前,永远不会测试外部循环中的条件。

考虑只使用一个循环和一个条件。

sf::Event event;
while ( (stateID != 3) && window.pollEvent(event)) {
}

您正在突破switch而不是while

下面的程序(试图(复制您的代码。它按预期工作,两个循环都在应该结束的时候结束

顺便说一句,这就是我们所说的一个简短的、包含的、正确的例子。与compilable一样正确,在while (stateID != 3)中使用stateID等全局变量或3等幻数是不好的形式,不是专业人士的标志。

你的程序与下面的程序有何不同?

#define STATE_TITLE 2
#define STATE_BATTLE 3
#define STATE_NULL 0
int stateID;
int next_state;
struct Event
{
    Event(int Num) : type(Num){}
    Event() : type( 5 ){} // random number grater than 1
    enum Type
    {
        Closed = 1 // equivalent to sf::Event::Closed
    };
    int type;
};
class Window
{
public:
    int pollEvent( Event& Ev )
    {
        return --Ev.type;
    }
};
void set_next_state(int new_state)
{
    next_state = new_state;
}
void change_state()
{
    if (next_state != STATE_NULL)
    {
        stateID = next_state;
        next_state = STATE_NULL;
    }
}
int _tmain()
{
    stateID = STATE_TITLE;
    Window window;
    //GAME LOOP//
    while (stateID != 3)
    {//INPUT//
        Event event;
        // note that there is at least one event with a Closed type before window.pollEvent(event) return false (0)
        while (window.pollEvent(event))
        {
            switch (event.type)
            {
                //Window closed
            case Event::Closed:
                set_next_state(3);
                break;
            }
        }
        change_state();
    }
    return 0;
}

我将函数change_state更改为以下内容:

void change_state(GameState *current_state, int &ID)
{
    //Check if the next state is null or exit
    if (next_state != STATE_NULL)
    {
        if (next_state != STATE_EXIT)
            delete current_state;
        //Set the new state
        switch(next_state)
        {
        case STATE_TITLE:
            current_state = new GameStateTitle;
            break;
        case STATE_BATTLE:
            current_state = new GameStateBattle;
            break;
        }
        ID = next_state;
        next_state = STATE_NULL;
    }
}

这个问题一定在stateID的声明中,因为在这个函数中它从未被更改过。