简体   繁体   English

C ++ - 通过调用main()函数重新启动游戏

[英]C++ - Restarting a game by calling the main() function

I'm building a small game. 我正在建造一个小游戏。 One of the input options is to restart the game. 其中一个输入选项是重启游戏。 The only way I could think of doing this was to call the main function from within the main function 我能想到这样做的唯一方法是从main函数中调用main函数

int main(int argc, char argv[]) {
 ...
 if (input == "restart") {
  main(argc, argv);
 }

Is this bad form? 这是不好的形式? Will it even work? 它会工作吗?

No, the C++ standard disallows calling main manually. 不,C ++标准不允许手动调用main

To cite the standard (C++11: 3.6.1 Main Function) 引用标准(C ++ 11:3.6.1主要功能)

The function main shall not be used within a program. 函数main不得在程序中使用。 The linkage (3.5) of main is implementation-defined. main的链接(3.5)是实现定义的。 A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill- formed. 将main定义为已删除或将main声明为内联,静态或constexpr的程序是错误的。 The name main is not otherwise reserved. 名称main不以其他方式保留。

You can't call main() recursively. 你不能递归地调用main() That's actually undefined behavior. 这实际上是未定义的行为。

Use a loop instead: 改为使用循环:

int main() {
     bool restart = false;
     do {
         // Do stuff ...

         // Set restart according some condition inside of the loop
         if(condition == true) {
             restart = true;
         } // (or simplyfied restart = condtion;)
     } while(restart);
}

Do not do this. 不要这样做。 From http://en.cppreference.com/w/cpp/language/main_function 来自http://en.cppreference.com/w/cpp/language/main_function

The main function has several special properties: main函数有几个特殊属性:

1) It cannot be used anywhere in the program 1)它不能在程序中的任何地方使用

a) in particular, it cannot be called recursively a)特别是,它不能递归调用

Since recursively calling main is impossible in C++ and would not really solve the problem, here's my 2 cents on how to deal with the problem: 因为在C ++中递归调用main是不可能的,并且不能真正解决问题,所以这是我如何处理问题的2美分:

Basically, any large program is a loop that might look like this: 基本上,任何大型程序都是一个可能如下所示的循环:

int main()
{
    bool quit = false;

    //Initialise and aquire resources...
    while (!quit)
    {
        //Run game and set quit if user wants to quit...
    }
    //free resources, should be automatic when RAII is adhered.
}

Your game should already look something like this, since any program that is not a loop will immidiately quit and won't be much of a game. 你的游戏应该看起来像这样,因为任何不是循环的程序都将会立即退出并且不会是游戏。 Just change the structure to this: 只需将结构更改为:

int main()
{
    bool quit = false;
    bool restart = false;

    while (!quit)
    {   
        Restart = false;
        //Initialise and aquire resources...
        while (!quit && !restart)
        {
            //Run game and update quit and restart according to user input.            
        }
        //free resources, should be automatic when RAII is adhered.
    }
}

you can use GOTO but this is not a good way of programming in general. 你可以使用GOTO,但这不是一般编程的好方法。 As the guys mentioned to use booleans or loops to check the current state or any other way instead of goto because it causes sometimes problems in the compiler. 正如那些人提到使用布尔值或循环来检查当前状态或任何其他方式而不是goto,因为它有时会导致编译器出现问题。 However it is still available in C and not C++ (AFAIK) 但它仍然可以在C而不是C ++(AFAIK)中使用

If in addition to reloading internal resources, you also need to reload external things like a libraries that the game links to you can do this by re-launching the game in a thread, detaching the thread and then shutting down. 如果除了重新加载内部资源之外,还需要重新加载外部事物,例如游戏链接到您的库,可以通过在线程中重新启动游戏,分离线程然后关闭来完成此操作。

I use this in a game I've made where I have automatic updates, to start the new updated executable and libraries. 我在我自动更新的游戏中使用它,以启动新的更新的可执行文件和库。

int main() {

    //initialize the game

    bool restart=false, quit=false;

    while (!quit) {
        //Main loop of the game
    }

    if (restart) {
        #ifdef _WIN32
            std::thread relaunch([](){ system("start SpeedBlocks.exe"); });
        #elif __APPLE__
            std::thread relaunch([](){
                std::string cmd = "open " + resourcePath() + "../../../SpeedBlocks.app";
                system(cmd.c_str());
            });
        #else
            std::thread relaunch([](){ system("./SpeedBlocks"); });
        #endif
        relaunch.detach();
    }

    return 0;
}

A bit of a hack, but it gets the job done. 有点黑客,但它完成了工作。 The #ifdef s just make it use the correct launch cmd for Windows/Max/Linux. #ifdef只是让它为Windows / Max / Linux使用正确的启动cmd。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM