Final BullCow Game

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

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

    PopulateIsograms();

    SetupGame();
}

void UBullCowCartridge::OnInput(const FString& PlayerInput) // When the player hits enter
{
    ClearScreen();

    if (bGameOver)
    {
        ClearScreen();
        SetupGame();
    }
    else
    {
        PrintLine(TEXT("Your guess was %s"), *PlayerInput);
        CheckGuess(PlayerInput);     
    }
}

void UBullCowCartridge::PopulateIsograms()
{
    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);
    });
}

void UBullCowCartridge::SetupGame()
{
    HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num()-1)];
    Lives = HiddenWord.Len()*2;
    bGameOver = false;
    bMulligan = true;

    PrintLine(TEXT("Welcome to the Bull Cow Game!"));
    PrintLine(TEXT("You have %i guesses for the secret isogram"), HiddenWord.Len());
    PrintLine(TEXT("*An isogram has no repeating characters*"));
    PrintLine(TEXT("Guess the %i letter word and press enter:"), HiddenWord.Len());
   
    // Debug
    // PrintLine(TEXT("The HiddenWord is: %s"), *HiddenWord);
    // PrintLine(TEXT("%i"), Isograms.Num());
}

void UBullCowCartridge::EndGame()
{
    bGameOver = true;
    if (Lives <= 0)
    {
        PrintLine(TEXT("You have lost this round!"));
        PrintLine(TEXT("The hidden word was %s"), *HiddenWord);
    }
    PrintLine(TEXT("\nPress enter to play again"));

    Isograms.Remove(HiddenWord);
    if (Isograms.Num() <= 0)
    {
        PopulateIsograms();
    }
}

void UBullCowCartridge::CheckGuess(const FString& Guess)
{
    if (Guess == HiddenWord)
    {
        PrintLine(TEXT("You guessed correctly!!!"));
        EndGame();
        return;
    }

    if (Guess == TEXT(""))
    {
        PrintLine(TEXT("You did not type anything"));
        PrintLine(TEXT("Please type a guess and press enter"));
        PrintLine(TEXT("Your guess needs to be %i characters long"), HiddenWord.Len());
        return;
    }

    if (Guess.Len() != HiddenWord.Len() || !IsIsogram(Guess))
    {
        PrintLine(TEXT("ERROR!\nYour guess was not %i characters long"), HiddenWord.Len());
        PrintLine(TEXT("or has repeating characters"));
        if (bMulligan)
        {
            PrintLine(TEXT("This is your one mulligan")); 
            bMulligan = false;
            return;
        }
        if(--Lives <= 0)
        {
            EndGame();
            return;
        }
        PrintLine(TEXT("Guess again, %i guess(es) remaining"), Lives);
        return;
    }
    
    PrintLine(TEXT("You guessed incorrectly"));

    if (--Lives <= 0)
    {
        EndGame();
        return;
    }

    FBullCowCount Score = BullCowCount(Guess);
    
    PrintLine(TEXT("Your guess has %i Bulls and %i Cows"), Score.Bulls, Score.Cows);
    PrintLine(TEXT("Try again, %i guess(es) remaining"), Lives);
}

bool UBullCowCartridge::IsIsogram(const FString& Word)
{
    for (int32 Index = 0; Index < Word.Len() - 1; Index++)
    {
        for (int32 Compare = Index + 1; Compare < Word.Len(); Compare++)
        {
            if (Word[Index] == Word[Compare])
            {
                return false;
            }
        }
    }
    return true;
}

FBullCowCount UBullCowCartridge::BullCowCount(const FString& Guess) const
{
    FBullCowCount Count;

    for (int32 Index = 0; Index < Guess.Len(); Index++)
    {
        if (Guess[Index] == HiddenWord[Index])
        {
            Count.Bulls++;
            continue;
        }
        for (int32 Compare = 0; Compare < HiddenWord.Len(); Compare++)
        {
            if (Guess[Index] == HiddenWord[Compare])
            {
                Count.Cows++;
                break;
            }
        }
    }
    return Count;
}

Here is my final code, fully optimized with the knowledge I have. Some of the extras I have are adding a mulligan to typing in a non-isogram or the wrong number of characters, bouncing it back if the player presses eneter without typing anything, and code in the endgame function that triggers only if the player loses.

1 Like

Congratulations on finishing Bull Cow Game! :partying_face:

1 Like