C++ Problem z grą w wisielca :-(

1

Dzień dobry
A więc: jeśli chodzi o grę- poprawiłam to, z czym miałam problem przy poprzednim wpisie (+jeszcze kilka innych drobnych błędów). Tym razem gra się nie sypie- kompilator nie przerywa odtwarzania programu, nie pokazuje błędów. Po odpaleniu jednak nie działa poprawnie :-(.
Kiedy wpisuję frazę i podaję kolejno same poprawne 'strzały'(zgadnięcia?) wszystko idzie pokazuje się jak trzeba. Kolejne daszki ukrytej frazy uzupełniają się na podane przez użytkownika znaki. Na końcu pokazuje się komunikat o wygranej i zapytanie, czy użytkownik chce ponownie rozpocząć grę.
Problem pojawia się jednak w momencie, kiedy padnie nietrafiony strzał (np. podana fraza była "kot", a ja w guess podaję n). W tym momencie (tak jakby) nie dzieje się nic. To znaczy- gra nie kara mnie za nietrafioną odpowiedź, a szubienica nie pokazuje kolejnych elementów wisielca. Oprócz tego zamiast podanych przeze mnie w kodzie programu 6- mam nieskończoną ilość prób- nie mogę przegrać.

Wydawało mi się, że problem może kryć się w funkcji UpdateBoard, bo to ona dostaje zamiast kopii referencję (oryginał) zmiennej numberOfGuessesLeft, której wartość ma pomniejszyć o jeden w przypadku nietrafienia przez użytkownika. Przeanalizowałam jednak wszystko, co z nią związane, i nie widzę, w którym miejscu tkwi błąd.

Podaje kod programu (struktura projektu; main, nagłówki w wisielec.h, ciała funkcji w wisielec.cpp)

main:

#include <iostream>
#include "wisielec.h"

using namespace std;

int main()
{
    const int IGNORE_CHARS = 256;
    const char * INPUT_ERROR_STRING = "input error! Please, try again.";
    do
    {
        PlayGame();
    }while(WantToPlayAgain());

    return 0;
}

wisielec.h :

#include <iostream>

using namespace std;

void PlayGame();
bool WantToPlayAgain();
char*MakeHiddenPhrase(const char*secretPhrase, int secretPhraseLength);
void DrawBoard(int numberOfGuessesLeft, const char* noptrHiddenPhrase);
int GetSecretPhrase(char secretPhrase[], int maxLength);
char GetGuess();
void UpdateBoard(char guess, char*optrHiddenPhrase, const char secretPhrase[], int secretPhraseLength, int&numberOfGuessesLeft);
bool isGameOver(int numberOfGuessesLeft, const char*noptrHiddenPhrase, int secretPhraseLength);
void DisplayResult(const char*secretPhrase, int numberOfGuessesLeft);

char GetCharacter(const char* prompt, const char*error);
char GetCharacter(const char* prompt, const char*error, const char validInput[], int validInputLength);

wisielec.cpp:

#include <iostream>
#include <cstring>
#include <cctype>
#include "wisielec.h"

using namespace std;

const int IGNORE_CHARS = 256; //to do main
const char * INPUT_ERROR_STRING = "input error! Please, try again.";

//Play Game
void PlayGame()
{
    const int MAX_LENGTH_OF_SECRET_PHRASE = 256;
    const int MAX_NUMBER_OF_GUESSES = 6;

    char secretPhrase[MAX_LENGTH_OF_SECRET_PHRASE];
    char* optrHiddenPhrase = nullptr;
    int nubmerOfGuessesLeft = MAX_NUMBER_OF_GUESSES;

    int secretPhraseLength = GetSecretPhrase(secretPhrase, MAX_LENGTH_OF_SECRET_PHRASE);//z t¹ lnijk¹ by³ problem

    optrHiddenPhrase = MakeHiddenPhrase(secretPhrase, secretPhraseLength);

    DrawBoard(nubmerOfGuessesLeft, optrHiddenPhrase);

    do
    {
        char guess = GetGuess();
        UpdateBoard(guess, optrHiddenPhrase, secretPhrase, secretPhraseLength, nubmerOfGuessesLeft);
        DrawBoard(nubmerOfGuessesLeft, optrHiddenPhrase);

    }while(!isGameOver(nubmerOfGuessesLeft, optrHiddenPhrase, secretPhraseLength));

    DisplayResult(secretPhrase, nubmerOfGuessesLeft);

    delete [] optrHiddenPhrase;
}
    /*do
    {
        PlayGame();
    }while(WantToPlayAgain());

}*/ ///To muszę się jeszcze zastanowić, gdzie powinnam umieścić ;)

char GetGuess()
{
    return GetCharacter("Let's input your guess: ", INPUT_ERROR_STRING);
}

void UpdateBoard(char guess, char*optrHiddenPhrase, const char secretPhrase[], int secretPhraseLength, int&numberOfGuessesLeft)
{
    bool found = false;

    for(int i=0; i<secretPhraseLength; i++)
    {
        if(tolower(secretPhrase[i])==guess)
            optrHiddenPhrase[i] = secretPhrase[i];
            found = true;
    }
    if(found==false)
    {
        numberOfGuessesLeft--;
    }
}

bool isGameOver(int numberOfGuessesLeft, const char*noptrHiddenPhrase, int secretPhraseLength)
{
    bool hasDash =  false;
    for(int i=0;i<secretPhraseLength;i++)
    {
        if(noptrHiddenPhrase[i]=='-')
        {
            hasDash = true;
            break;
        }
    }return numberOfGuessesLeft==0 || !hasDash;
}

void DisplayResult(const char*secretPhrase, int numberOfGuessesLeft)
{
    if(numberOfGuessesLeft>0)
    {
        cout<<"You got it! The phrase was: "<<secretPhrase<<endl;
    }
    else
    {
        cout<<"You didn't get it...The phrases was: "<<secretPhrase<<endl;
    }
}

bool WantToPlayAgain()
{
    const char validInputs[] = {'y','n'};
    char response = GetCharacter("Would you like to play again? (y/n)", INPUT_ERROR_STRING, validInputs, 2);
    return response == 'y';
}

//Get Secret Phrase
int GetSecretPhrase(char secretPhrase[], int maxLength)
{
    bool failure;
    int length;
    do
    {
        failure = false;
        cout<<"Enter the secret phrase: ";
        cin.get(secretPhrase, maxLength);

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << INPUT_ERROR_STRING << endl;
            failure = true;
        }
        else
        {
            length = strlen(secretPhrase);

            if(length==0)
            {
                cout<<"You didn't enter any characters. Please, enter a word."<<endl;
                failure = true;
            }
        }

    }while(failure);
    return length;
}
//Make Hidden Phrase
char*MakeHiddenPhrase(const char*secretPhrase, int secretPhraseLength)
{
    char* hiddenPhrase = new char[secretPhraseLength+1];
    for(int i=0;i<secretPhraseLength;i++)
    {
        if(secretPhrase[i] != ' ')
        {
            hiddenPhrase[i]='-';
        }
        else hiddenPhrase[i] = ' ';
    }
    hiddenPhrase[secretPhraseLength]='\0';
    return hiddenPhrase;
}
//Draw Board
void DrawBoard(int numberOfGuessesLeft, const char* noptrHiddenPhrase)
{
    switch(numberOfGuessesLeft)
    {
    case 0:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |  /|\\"<<endl;
        cout<<" |  / \\"<<endl;
        cout<<"-+-"<<endl<<endl;
    }
    case 1:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |  /|\\"<<endl;
        cout<<" |  / "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break;

    case 2:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |  /|\\"<<endl;
        cout<<" |  "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break;
    case 3:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |  /|"<<endl;
        cout<<" |  "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break;
    case 4:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |  "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break;
    case 5:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   O"<<endl;
        cout<<" |  "<<endl;
        cout<<" |  "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break;
    case 6:
    {
        cout<<" +---+"<<endl;
        cout<<" |   |"<<endl;
        cout<<" |   "<<endl;
        cout<<" |  "<<endl;
        cout<<" |  "<<endl;
        cout<<"-+-"<<endl<<endl;
    }break; default: break;
    }cout<<"Secret Phrase: "<<noptrHiddenPhrase<<endl<<endl;
}

char GetCharacter(const char* prompt, const char*error)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                input = tolower(input);
            }
            else
            {
                cout<<error<<endl;
                failure = true;
            }
        }
    }while(failure); return input;
}

char GetCharacter(const char* prompt, const char* error, const char validInput[], int validInputLength)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                input = tolower(input);

                for (int i=0;i<validInputLength;i++)
                {
                    if(input==validInput[i])
                    {
                        return input;
                    }
                }
            }
            cout<<error<<endl;
            failure=true;
        }
    }while(failure); return input;
}
  • jeszcze to, co otrzymuję w konsoli:
Enter the secret phrase: Test
 +---+
 |   |
 |
 |
 |
-+-

Secret Phrase: ----

Let's input your guess: t
+---+
| |
|
|
|
-+-

Secret Phrase: T--t

Let's input your guess: e
+---+
| |
|
|
|
-+-

Secret Phrase: Te-t

Let's input your guess: s
+---+
| |
|
|
|
-+-

Secret Phrase: Test

You got it! The phrase was: Test
Would you like to play again? (y/n)y
Enter the secret phrase: Test
+---+
| |
|
|
|
-+-

Secret Phrase: ----

Let's input your guess: i
+---+
| |
|
|
|
-+-

Secret Phrase: ----

Let's input your guess: i
+---+
| |
|
|
|
-+-

Secret Phrase: ----

Let's input your guess: j
+---+
| |
|
|
|
-+-

Secret Phrase: ----

Let's input your guess:

![screenshot-20190712135040.png](https://4programmers.net/uploads/attachment/5d/5d287410b1ee2.png)
Grę napisałam głównie w celu przećwiczenia użycia wskaźników i referencji- bo wciąż nie posługuję się nimi swobodnie.

Będzie mi bardzo miło, jeśli ktoś spróbuje mi podpowiedzieć, jak to poprawić :-)
1

Pierwszy błąd jaki widzę to tu w UpdateBoard:

        if(tolower(secretPhrase[i])==guess)
            optrHiddenPhrase[i] = secretPhrase[i];
            found = true;

nie ma nawiasów więc zawsze będzie found == true

2

Błąd logiczny masz w funkcji UpdateBoard(), powinno być

   if(tolower(secretPhrase[i])==guess)
   {
      optrHiddenPhrase[i] = secretPhrase[i];
      found = true;
   }

Zapomniałaś nawiasów {}

1

W drawBoard() w instrukcji switch i case 0: nie dodałaś breakprzez co na koniec gry rysuje dodatkowo ludzia (bez nogi) :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1