BullCow Extra credit - Word Length Selection

So for the extra credit portion I decided add in the ability to choose the length of the word that you want go guess. I got hung up trying to figure out why a few things weren’t working but in the end got it figured all out.

BullCowCartridge.cpp

#include "BullCowCartridge.h"
#include "Misc/FileHelper.h"
#include "Misc/Paths.h"
#include "Misc/Char.h"
#include "Misc/CString.h"

void UBullCowCartridge::BeginPlay() // When the game starts
{
    Super::BeginPlay();

    const FString WordListPath = FPaths::ProjectContentDir() / TEXT("WordLists/HiddenWordList.txt");
    FFileHelper::LoadFileToStringArrayWithPredicate(Isograms, *WordListPath, [](const FString& Word)
    {
        return Word.Len() >= 4 && Word.Len() <= 8 && IsIsogram(Word);
    });

    SetupGame();          
}

void UBullCowCartridge::OnInput(const FString& Input) // When the player hits enter
{
    if (bGameOver)
    {
        ClearScreen();
        SetupGame();
    }
    else if (!bLengthSet)
    {
        RequestLength(Input);

        if (bLengthSet)
        {
            InitializeGame();
        }  
    }
    else
    {
        ProcessGuess(Input);
    } 
}

void UBullCowCartridge::SetupGame()
{
    bGameOver = false;
    bLengthSet = false;  
    bIsInitialized = false;
    FWordLength WordLength = ProcessLength();
    WordMin = WordLength.Min;
    WordMax = WordLength.Max;

    PrintLine(TEXT("Welcome to Bull Cows!\n"));

    PrintLine(TEXT("The goal is to guess an isogram of the\nlength of your choice.\n"));

    PrintLine(TEXT("The shortest word is %i long."), WordMin);
    PrintLine(TEXT("The longest word is %i long.\n"), WordMax);
    PrintLine(TEXT("Please enter the length of a word you\nwould like to guess and hit enter."));
} 

//Builds the array of words of the length that you chose, sets lives, sets HiddenWord
void UBullCowCartridge::InitializeGame()
{
    IsogramsLength = LengthListBuild(Isograms);
    HiddenWord = IsogramsLength[FMath::RandRange(0, IsogramsLength.Num() - 1)]; 
    Lives = (HiddenWord.Len()) * 2; 
    bIsInitialized = true;
    
    PrintLine(TEXT("Guess the %i letter word."), HiddenWord.Len());
    PrintLine(TEXT("You have %i lives."), Lives);  

    PrintLine(TEXT("\nType in your guess and press enter to \ncontinue...")); // Prompt player for guess
}


void UBullCowCartridge::EndGame()
{
    bGameOver = true;
    PrintLine(TEXT("\nPress enter to play again..."));
}

void UBullCowCartridge::ProcessGuess(const FString& PlayerGuess)
{
    //Check for correct guess.
    if (PlayerGuess == HiddenWord)
    {
        ClearScreen();
        PrintLine(TEXT("\nYou guessed correctly!"));
        EndGame();
        return;
    }

    //Check if guess is the correct number of characters.
    if (PlayerGuess.Len() != HiddenWord.Len())
    {
        PrintLine(TEXT("The word is %i characters long!\nPlease enter a word with the correct\namount of characters...\n"), HiddenWord.Len()); 
        return;
    }

    //Check if the guess is an isogram.
    if (!IsIsogram(PlayerGuess))
    {
        PrintLine(TEXT("\nThe word you have entered is not an\nisogram..."));
        PrintLine(TEXT("\nPlease guess again...\n"));
        return;
    }
    
    PrintLine(TEXT("You did not guess correctly..."));
    PrintLine(TEXT("You have %i lives left...\n "), --Lives); 
    
    //check for remaining lives.
    if (Lives <= 0) 
    {
        ClearScreen();
        PrintLine(TEXT("You are out of lives!"));
        PrintLine(TEXT("The word was... %s"), *HiddenWord);
        PrintLine(TEXT("Better luck next time..."));
        EndGame();
        return;
    }

    //Show player the bulls and the cows
    FBullCowCount BCCount = GetBullCows(PlayerGuess);

    PrintLine(TEXT("You have %i Bulls and %i Cows"), BCCount.Bulls, BCCount.Cows);
}


// Checks that a word is an isogram.
bool UBullCowCartridge::IsIsogram(const FString& Word)
{
    for (int32 Index = 0; Index < Word.Len() - 1; Index++)
    {
        for (int32 Comparison = Index + 1; Comparison < Word.Len(); Comparison++)
        {
            if (Word[Index] == Word[Comparison])
            {
                return false;
            }
        }
    }
    return true;        
}

TArray<FString> UBullCowCartridge::GetValidWords(const TArray<FString>& WordList) const
{
    TArray<FString> ValidWords;
    
    for (FString WordInList : WordList)
    {
        if (WordInList.Len() >= 4 && WordInList.Len() <= 8 && IsIsogram(WordInList))
        {
            ValidWords.Emplace(WordInList);
        }
    }
    return ValidWords;
}

//Returns the amount of Bulls and Cows in the guess made by the player
FBullCowCount UBullCowCartridge::GetBullCows(const FString& Guess) const
{
    FBullCowCount Count;

      for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
    {
        if (Guess[GuessIndex] == HiddenWord[GuessIndex])
        {
            Count.Bulls++;
            continue;
        }

        for (int32 CowIndex = 0; CowIndex < Guess.Len(); CowIndex++)
        {
            if (Guess[GuessIndex] == HiddenWord[CowIndex])
            {
                Count.Cows++;
                break;
            }  
        }
    }  

    return Count;
}

//Will check and return length of the shortest and longest word in the list
FWordLength UBullCowCartridge::ProcessLength() const
{
    FWordLength Length;
    
    //Checks for the longest word
    for (int32 Index = 0; Index < Isograms.Num(); Index++)
    {
        if (Isograms[Index].Len() > Length.Max)
        {
            Length.Max = Isograms[Index].Len();
        }
    }
    
    Length.Min = Length.Max;

    //Checks for the shortest word
    for (int32 Index = 0; Index < Isograms.Num(); Index++)
    {
        if (Isograms[Index].Len() <= Length.Min)
        {
            Length.Min = Isograms[Index].Len();
        }
    }
    return Length;
}

//Checks that the length requested by the player is an integer and that it is within the valid range
void UBullCowCartridge::RequestLength(FString Input)
{
    ChoiceInt = 0;

    //Verifies that the input is an integer
    for (int32 Index = 0; Index < Input.Len(); Index++) 
    {
        if (isdigit(Input[Index]) == false) 
        {
            bIsValidInt = false;
            PrintLine(TEXT("You have not entered an integer..."));
            return;
        }
        else
        {
            bIsValidInt = true;
        }    
    }

    //Atoi is only used after the input has been confirmed to be an integer as it does not return any errors.
    ChoiceInt = FCString::Atoi(*Input);

    //Verifies that the integer is within the Min and Max lenth of words.
    if (ChoiceInt > WordMax || ChoiceInt < WordMin)
    {
        ClearScreen();
        PrintLine(TEXT("The number you have entered is not within the valid range.\n"));
        PrintLine(TEXT("The range is %i - %i"), WordMin, WordMax);
        bIsValidInt = false;
        return;
    }

    //PrintLine(TEXT("The number entered: %i"), ChoiceInt);
    bLengthSet = true;
    ClearScreen();
    return;
}

// Returns the words that match the requested length from the list of all isograms
TArray<FString> UBullCowCartridge::LengthListBuild(const TArray<FString>& IsogramsList) const
{
    TArray<FString> ValidWords;
    
    for (int32 Index = 0; Index < IsogramsList.Num(); Index++)
    {
        if (IsogramsList[Index].Len() == ChoiceInt)
        {
            ValidWords.Emplace(IsogramsList[Index]);
        }
    }
    return ValidWords;
}
 

BullCowCartridge.h

#pragma once

#include "CoreMinimal.h"
#include "Console/Cartridge.h"
#include "BullCowCartridge.generated.h"

struct FBullCowCount
{
	int32 Bulls = 0;
	int32 Cows = 0;
};

struct FWordLength
{
	int32 Min = 0;
	int32 Max = 0;
};

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class BULLCOWGAME_API UBullCowCartridge : public UCartridge
{
	GENERATED_BODY()

	public:
	virtual void BeginPlay() override;
	virtual void OnInput(const FString& Input) override;
	FWordLength ProcessLength() const;
	void RequestLength(FString Input);
	void ProcessGuess(const FString& PlayerGuess);
	void SetupGame();
	void EndGame();
	void InitializeGame();
	static bool IsIsogram(const FString& Word);
	TArray <FString> GetValidWords(const TArray<FString>& WordList) const;
	TArray <FString> LengthListBuild(const TArray<FString>& IsogramList) const;
	FBullCowCount GetBullCows(const FString& Guess) const;
	

	// Your declarations go below!
	private:
	int32 Lives;
	int32 WordMin = 0;
	int32 WordMax = 0;
	int32 ChoiceInt;
	FString HiddenWord;
	bool bIsValidInt;
	bool bLengthSet;
	bool bGameOver;
	bool bIsInitialized;
	TArray<FString> Words;
	TArray<FString> Isograms;
	TArray<FString> IsogramsLength;
};

2 Likes

Awesome job! :grin:

Privacy & Terms