While循环在使用子进程时不中断。

huangapple go评论70阅读模式
英文:

While loop not breaking when using subprocess

问题

我正在制作一个简单的猜词游戏。我创建了一个 C++ 服务器,其中有一个包含 10 个单词的列表,并随机选择一个作为答案。然后它计算答案的字母数并创建一个游戏板:

int randomNum = rand() % (sizeof(names) / sizeof(names[0]));

// 随机选择答案
string answer = names[randomNum];
int answerLength = answer.length();

// 初始化猜测字符串
string guessing;
for (int i = 0; i < answerLength; i++)
{
    guessing += "_";
}

接下来,我进入一个 while 循环,向用户发送这个游戏板(以便用户看到答案的字母数),请求一个字母,进行一些验证,检查字母是否在答案中并打印相应的消息。如果猜中了答案,服务器会退出循环并打印一条消息(用户赢得或失去所有生命):

// 游戏循环
while (lives > 0 && guessing != answer)
{
    cout << guessing << endl;

    char letter;
    cin >> letter;
    letter = tolower(letter);

    // 检查用户是否输入字母
    if (!isalpha(letter))
    {
        cout << "请键入字母。" << endl;
        continue;
    }
    // 检查用户是否已经猜测过这个字母
    if (guessing.find(letter) != string::npos)
    {
        cout << "你已经猜过这个字母,请重试。" << endl;
        continue;
    }

    // 比较答案的每个字母与用户输入的字母
    bool found = false;
    for (int i = 0; i < answerLength; i++)
    {
        if (answer[i] == letter)
        {
            guessing[i] = letter;
            found = true;
        }
    }

    // 如果字母不正确,减少 1 生命
    if (!found)
    {
        --lives;
        cout << "错误。你还有 " << lives << " 生命。" << endl;
    }
    else
    {
        cout << "正确!你还有 " << lives << " 生命。" << endl;
    }
}

if (guessing == answer)
{
    cout << "你猜对了答案 - " << answer << "!" << endl;
}
else
{
    cout << "游戏结束。你未能猜中答案 - " << answer << "!" << endl;
}

客户端是一个使用 subprocess 模块的 Python 脚本,用于启动服务器并与其进行通信。它还进入一个循环,读取游戏板,打印它,然后请求一个字母并将其发送到服务器。然后它读取服务器发送的状态。如果服务器告诉它游戏结束,它应该退出循环并终止进程。

from subprocess import Popen, PIPE, STDOUT

hangman = Popen(["./server"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
isGameOver = False

print("欢迎来到HANGMAN!")

while not isGameOver:
    board = hangman.stdout.readline().decode()
    print(board)

    letter = input("输入一个字母:")
    hangman.stdin.write(letter.encode() + b"\n")
    hangman.stdin.flush()

    status = hangman.stdout.readline().decode().strip()
    if(status.startswith("你猜对了") or status.startswith("游戏结束。")):
        isGameOver = True
        print(status)
    print(status)

hangman.stdin.close()
hangman.stdout.close()
hangman.kill()

您的问题是 - 当我启动 Python 脚本并猜测字母时,我得到 "你猜对了这个词",但客户端侧的循环再次启动并要求我输入一个新字母,而不是退出循环。这是因为你的服务器在发送 "你猜对了" 后,但客户端并没有立刻退出循环,而是继续执行循环中的下一次迭代。要解决这个问题,你可以使用 break 语句来立即退出循环,如下所示:

if(status.startswith("你猜对了") or status.startswith("游戏结束。")):
    isGameOver = True
    print(status)
    break

这将在客户端接收到 "你猜对了" 或 "游戏结束" 的消息后立即退出循环。

英文:

I'm making a simple Hangman game. I made a C++ server that has a list of 10 names and randomly picks one to be the answer. Then it counts the number of letters of the answer and creates a board:

int randomNum = rand() % (sizeof(names) / sizeof(names[0]));

// pick an answer randomly
string answer = names[randomNum];
int answerLength = answer.length();

// initialize the guessing string
string guessing;
for (int i = 0; i &lt; answerLength; i++)
{
    guessing += &quot;_&quot;;
}

Then, I enter a while loop that sends the user this board (so the user can see how many letters the answer has), asks for a letter, does some validation, checks if the letter is in the word and prints out the appropriate message. If the word is guessed, the server exits the loop and prints a message (the user won or lost all lives).

// game loop
while (lives &gt; 0 &amp;&amp; guessing != answer)
{
    cout &lt;&lt; guessing &lt;&lt; endl;

    char letter;
    cin &gt;&gt; letter;
    letter = tolower(letter);

    // check if the user entered a letter
    if (!isalpha(letter))
    {
        cout &lt;&lt; &quot;Please enter a letter.&quot;
             &lt;&lt; endl;
        continue;
    }
    // check if user has already guessed this letter
    if (guessing.find(letter) != string::npos)
    {
        cout &lt;&lt; &quot;You already guessed this. Try again.&quot;
             &lt;&lt; endl;
        continue;
    }

    // compare every letter of the answer to user&#39;s input letter
    bool found = false;
    for (int i = 0; i &lt; answerLength; i++)
    {
        if (answer[i] == letter)
        {
            guessing[i] = letter;
            found = true;
        }
    }

    // if the letter is incorrect, take 1 life
    if (!found)
    {
        --lives;
        cout &lt;&lt; &quot;Incorrect. You have &quot; &lt;&lt; lives &lt;&lt; &quot; lives left.&quot; &lt;&lt; endl;
    }
    else
    {
        cout &lt;&lt; &quot;Correct! You have &quot; &lt;&lt; lives &lt;&lt; &quot; lives left.&quot; &lt;&lt; endl;
    }
}

if (guessing == answer)
{
    cout &lt;&lt; &quot;You guessed the answer - &quot; &lt;&lt; answer &lt;&lt; &quot;!&quot; &lt;&lt; endl;
}
else
{
    cout &lt;&lt; &quot;Game over. You failed to guess the answer - &quot; &lt;&lt; answer &lt;&lt; &quot;!&quot; &lt;&lt; endl;
}

The client is a python script that uses subprocess (and Popen) to start the server and communicate with its stdin and stdout. It also enters a loop and reads the board, prints it out, then asks for a letter and sends it to the server. Then it reads whatever status the server sends it. If the server tells it the game is over, it should exit the loop and kill the process.

from subprocess import Popen, PIPE, STDOUT

hangman = Popen([&quot;./server&quot;], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
isGameOver = False

print(&quot;Welcome to HANGMAN!&quot;)

while not isGameOver:
   board = hangman.stdout.readline().decode()
   print(board)

   letter = input(&quot;Enter a letter: &quot;)
   hangman.stdin.write(letter.encode() + b&quot;\n&quot;)
   hangman.stdin.flush()

   status = hangman.stdout.readline().decode().strip()
   if(status.startswith(&quot;You guessed&quot;) or status.startswith(&quot;Game over.&quot;)):
       isGameOver = True
       print(status)
   print(status)


hangman.stdin.close()
hangman.stdout.close()
hangman.kill()

My problem is - when i start the python script and guess the letter, I get "You guessed the word" but the loop on the client side starts up again and asks me for a new letter instead of breaking the loop. It's my first time working with subprocess, so I'm very new to this. How do i fix this?

答案1

得分: 0

已解决。当用户赢得游戏时,服务器发送2行消息。

  1. 正确。您还有 x 条生命。
  2. 您猜对了答案...

Python脚本在循环结束时将第1条消息识别为 "状态",然后在 while 循环开始时读取第2条消息并要求输入新的字母。为了解决这个问题,我修改了服务器的代码如下:

// 如果猜错了字母,减少1生命
if (!found)
{
    --lives;
    if (lives == 0)
    {
        cout << "游戏结束。您未能猜对答案 - " << answer << "!" << endl;
    }
    else
    {
        cout << "不正确。您还有 " << lives << " 条生命。" << endl;
    }
}
else
{
    if (guessing == answer)
    {
        cout << "您猜对了答案 - " << answer << "!" << endl;
    }
    else
    {
        cout << "正确!您还有 " << lives << " 条生命。" << endl;
    }
}

现在,服务器在每轮猜测后只发送一条消息。

英文:

Figured it out. When the user wins the game, the server sends 2 lines.

  1. Correct. You have x lives left.
  2. You guessed the answer...

The python script reads the 1st message as "status" at the end of the loop, and then it reads the 2nd message as "board" at the start of the while loop and asks for a new letter. To fix this, I modified my server like this:

// if the letter is incorrect, take 1 life
    if (!found)
    {
        --lives;
        if (lives == 0)
        {
            cout &lt;&lt; &quot;Game over. You failed to guess the answer - &quot; &lt;&lt; answer &lt;&lt; &quot;!&quot; &lt;&lt; endl;
        }
        else
        {
            cout &lt;&lt; &quot;Incorrect. You have &quot; &lt;&lt; lives &lt;&lt; &quot; lives left.&quot; &lt;&lt; endl;
        }
    }
    else
    {
        if (guessing == answer)
        {
            cout &lt;&lt; &quot;You guessed the answer - &quot; &lt;&lt; answer &lt;&lt; &quot;!&quot; &lt;&lt; endl;
        }
        else
        {
            cout &lt;&lt; &quot;Correct! You have &quot; &lt;&lt; lives &lt;&lt; &quot; lives left.&quot; &lt;&lt; endl;
        }
    }

Now the server only sends one message after any round of guessing.

huangapple
  • 本文由 发表于 2023年3月3日 18:08:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625680.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定