I was told earlier that this would be explained later in the course but I still haven’t seen the solution. I’m getting a Debug Assertion Failed error when I type in the proper amount of letters for the isogram whether its the actual word or not. Whenever the hiddenwordlength is equal to the amount of letters i put i get the error. Is anyone else getting this error? If it is explained later, can you tell me which video it’s in?
Here’s my source code
main.cpp
/* This is the console executable, that makes us of the BullCow class
This acts as the view in a MVC pattern, and is responsible for all
user interaction. For game logic see the FBullCowGame class.
*/
#include <iostream>
#include <string>
#include "FBullCowGame.h"
using FText = std::string;
using int32 = int;
void PrintIntro();
void PlayGame();
FText GetValidGuess();
bool AskToPlayAgain();
void PrintGameSummary();
FBullCowGame BCGame; // instantiate a new game
// the entry point for our application
int main()
{
bool bPlayAgain = false;
do
{
PrintIntro();
PlayGame();
// TODO add a game summary
bPlayAgain = AskToPlayAgain();
} while (bPlayAgain);
return 0;
}
void PrintIntro()
{
//introduce the game
std::cout << "\n\nWelcome to Bulls and Cows, a fun word game.\n";
std::cout << "Can you guess the " << BCGame.GetHiddenWordLength();
std::cout << " letter isogram I'm thinking of?\n";
std::cout << std::endl;
return;
}
void PlayGame()
{
BCGame.Reset();
int32 MaxTries = BCGame.GetMaxTries();
// loop asking for guesses while the game
// is NOT won and there are still tries remaining
while (!BCGame.IsGameWon() && BCGame.GetCurrentTry() <= MaxTries) {
FText Guess = GetValidGuess();
// submit valid guess to the game, and receive counts
FBullCowCount BullCowCount = BCGame.SubmitValidGuess(Guess);
std::cout << "Bulls = " << BullCowCount.Bulls;
std::cout << ". Cows = " << BullCowCount.Cows << "\n\n";
}
return;
}
// loop continually until the user gives a valid guess
FText GetValidGuess()
{
FText Guess = "";
EGuessStatus Status = EGuessStatus::Invalid_Status;
do {
int32 CurrentTry = BCGame.GetCurrentTry();
std::cout << "Try " << CurrentTry << ". Enter your guess: ";
FText Guess = "";
std::getline(std::cin, Guess);
Status = BCGame.CheckGuessValidity(Guess);
switch (Status)
{
case EGuessStatus::Wrong_Length:
std::cout << "Please enter a " << BCGame.GetHiddenWordLength() << " letter word.\n";
break;
case EGuessStatus::Not_Isogram:
std::cout << "Please enter a word without repeating letters.\n";
break;
case EGuessStatus::Not_Lowercase:
std::cout << "Please enter all lowercase letters.\n";
break;
default:
// assume guess is valid
break;
}
std::cout << std::endl;
} while (Status != EGuessStatus::OK); // keep looping until no errors
return Guess;
}
bool AskToPlayAgain()
{
std::cout << "Do you want to play again with the same hidden word (y/n)? ";
FText Response = "";
std::getline(std::cin, Response);
return (Response[0] == 'y') || (Response[0] == 'Y');
}
void PrintGameSummary() {
if (BCGame.IsGameWon())
{
std::cout << "WELL DONE - YOU WIN!\n";
}
else
{
std::cout << "Netter luck next time!\n";
}
}
FBullCowGame.h
#pragma once
#include <string>
using FString = std::string;
using int32 = int;
struct FBullCowCount
{
int32 Bulls = 0;
int32 Cows = 0;
};
enum class EGuessStatus
{
Invalid_Status,
OK,
Not_Isogram,
Wrong_Length,
Not_Lowercase
};
class FBullCowGame {
public:
FBullCowGame(); // constructor
int32 GetMaxTries() const;
int32 GetCurrentTry() const;
int32 GetHiddenWordLength() const;
bool IsGameWon() const;
EGuessStatus CheckGuessValidity(FString) const;
void Reset(); // TODO make a more rich return value.
// counts bulls and cows, and increases try number assuming valid guess
FBullCowCount SubmitValidGuess(FString);
private:
// see constructor for initialisation
int32 MyCurrentTry;
int32 MyMaxTries;
FString MyHiddenWord;
bool bGameIsWon;
bool IsIsogram(FString) const;
bool isLowercase(FString) const;
};
FBullCowGame.cpp
#include "FBullCowGame.h"
#include <map>
#define TMap std::map
using int32 = int;
FBullCowGame::FBullCowGame()
{
Reset();
}
int32 FBullCowGame::GetMaxTries() const { return MyMaxTries; }
int32 FBullCowGame::GetCurrentTry() const { return MyCurrentTry; }
int32 FBullCowGame::GetHiddenWordLength() const { return MyHiddenWord.length(); }
bool FBullCowGame::IsGameWon() const { return bGameIsWon; }
void FBullCowGame::Reset()
{
constexpr int32 MAX_TRIES = 8;
const FString HIDDEN_WORD = "planet";
MyMaxTries = MAX_TRIES;
MyHiddenWord = HIDDEN_WORD;
MyCurrentTry = 1;
bGameIsWon = false;
return;
}
EGuessStatus FBullCowGame::CheckGuessValidity(FString Guess) const
{
if (!IsIsogram(Guess)) // if guesss isn't an isogram
{
return EGuessStatus::Not_Isogram;
}
else if (!isLowercase(Guess)) // if the guesss isn't all lowercase
{
return EGuessStatus::Not_Lowercase; // TODO write function
}
else if (Guess.length() != GetHiddenWordLength()) // if the guess length is wrong
{
return EGuessStatus::Wrong_Length;
}
else
{
return EGuessStatus::OK;
}
}
// receives a VALID guess, increments turn, and returns count
FBullCowCount FBullCowGame::SubmitValidGuess(FString Guess)
{
MyCurrentTry++;
FBullCowCount BullCowCount;
int32 WordLength = MyHiddenWord.length(); // assuming same length as guess
//loop through all letters in the hidden word
for (int32 MHWChar = 0; MHWChar < WordLength; MHWChar++) {
//compare letters against the guess
for (int32 GChar = 0; GChar < WordLength; GChar++) {
//if they match then
if (Guess[GChar] == MyHiddenWord[MHWChar]) {
// if they're in the same place
if (MHWChar == GChar) {
BullCowCount.Bulls++; // increment bulls
}
// else
else {
BullCowCount.Cows++; // must be a cow
}
}
}
}
if (BullCowCount.Bulls == WordLength) {
bGameIsWon = true;
}
else
{
bGameIsWon = false;
}
return BullCowCount;
}
bool FBullCowGame::IsIsogram(FString Word) const
{
// treat 0 and 1 letter words as isograms
if (Word.length() <= 1) { return true; }
TMap< char, bool > LetterSeen; // setup our map
for (auto Letter : Word)
{
Letter = tolower(Letter); // handle mixed case
if (LetterSeen[Letter]) { // if the letter is in the map
return false; // we do not have an isogram
}
else
{
LetterSeen[Letter] = true; // add the letter to the map as seen
}
}
return true; // for example in case where /0 is entered
}
bool FBullCowGame::isLowercase(FString Word) const
{
for (auto Letter : Word)
{
if (!islower(Letter)) // if not a lowercase letter
{
return false;
}
}
return true;
}
Because you are creating a new variable for your guess in this function within the do-while loop. Meaning the guess you enter to the SubmitGuess function will be an empty string
// loop continually until the user gives a valid guess
FText GetValidGuess()
{
FText Guess = "";
EGuessStatus Status = EGuessStatus::Invalid_Status;
do {
int32 CurrentTry = BCGame.GetCurrentTry();
std::cout << "Try " << CurrentTry << ". Enter your guess: ";
FText Guess = ""; //Creating a new variable local to do-while loop
1 Like
So are you saying I should remove the second FText Guess? I’m confused.
Ok, I think I gotcha. Thanks for the help!