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 < answerLength; i++)
{
guessing += "_";
}
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 > 0 && guessing != answer)
{
cout << guessing << endl;
char letter;
cin >> letter;
letter = tolower(letter);
// check if the user entered a letter
if (!isalpha(letter))
{
cout << "Please enter a letter."
<< endl;
continue;
}
// check if user has already guessed this letter
if (guessing.find(letter) != string::npos)
{
cout << "You already guessed this. Try again."
<< endl;
continue;
}
// compare every letter of the answer to user's input letter
bool found = false;
for (int i = 0; i < answerLength; i++)
{
if (answer[i] == letter)
{
guessing[i] = letter;
found = true;
}
}
// if the letter is incorrect, take 1 life
if (!found)
{
--lives;
cout << "Incorrect. You have " << lives << " lives left." << endl;
}
else
{
cout << "Correct! You have " << lives << " lives left." << endl;
}
}
if (guessing == answer)
{
cout << "You guessed the answer - " << answer << "!" << endl;
}
else
{
cout << "Game over. You failed to guess the answer - " << answer << "!" << 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(["./server"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
isGameOver = False
print("Welcome to HANGMAN!")
while not isGameOver:
board = hangman.stdout.readline().decode()
print(board)
letter = input("Enter a letter: ")
hangman.stdin.write(letter.encode() + b"\n")
hangman.stdin.flush()
status = hangman.stdout.readline().decode().strip()
if(status.startswith("You guessed") or status.startswith("Game over.")):
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?
Figured it out. When the user wins the game, the server sends 2 lines.
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 << "Game over. You failed to guess the answer - " << answer << "!" << endl;
}
else
{
cout << "Incorrect. You have " << lives << " lives left." << endl;
}
}
else
{
if (guessing == answer)
{
cout << "You guessed the answer - " << answer << "!" << endl;
}
else
{
cout << "Correct! You have " << lives << " lives left." << endl;
}
}
Now the server only sends one message after any round of guessing.