Bull Cow * 2

In my version, I did a few Unreal modifications and a few C++ modifications. I got really interested in learning how I could have more than one instance of the terminal and having them operate independently. After fiddling with it between lectures, I eventually figured out the capture input issue and playing with the blueprint.

Specifically, in the larger C++ portion, I implemented a Freebie system where you get several free tries if they are drastically wrong. The wrong length, not an isogram, etc. But if you keep doing it and ignoring the warnings, your lives/tries will start being decremented. I also put in a section to determine if you should add an “s” at the end of the word or not. Glad I could use the short form I use so much in other languages.
bool ? “true”: “false”

I left a lot of the old code in and kept it commented as I often return to previous work to see how I did things. At least until I get super comfortable with the language.

I almost had to rebuild the section as I moved the folder and all the references that Visual Studio Code had were broken. Worked out eventually. Phew.

// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"

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

    // Old way
    const FString WordListPath = FPaths::ProjectContentDir() / TEXT("WordLists/HiddenWordList.txt");
    // FFileHelper::LoadFileToStringArray(AvailableWords, *WordListPath);
    // ValidWords = GetValidWords(AvailableWords);
    // New Way
    FFileHelper::LoadFileToStringArrayWithPredicate(
        ValidWords, *WordListPath,
        [](const FString &CheckWord)
        {
            return CheckWord.Len() >= 4 && CheckWord.Len() <= 8 && IsIsogram(CheckWord);
        });

    PrintLine(TEXT("Hello there!"));

    SetupGame();
}

TArray<FString> UBullCowCartridge::GetValidWords(const TArray<FString> &Words) const
{
    TArray<FString> ReturnWords;
    for (FString CheckWord : Words)
    {
        if (CheckWord.Len() >= 4 && CheckWord.Len() <= 8 && IsIsogram(CheckWord))
        {
            ReturnWords.Emplace(CheckWord);
            // PrintLine(TEXT("%s"), *Words[Index]);
        }
    }

    // for (int32 Index = 0; Index < Words.Num(); Index++)
    // {
    //     if (Words[Index].Len() >= 4 && Words[Index].Len() <= 8 && IsIsogram(Words[Index]))
    //     {
    //         ReturnWords.Emplace(Words[Index]);
    //         // PrintLine(TEXT("%s"), *Words[Index]);
    //     }
    // }

    return ReturnWords;
}

void UBullCowCartridge::PrintInstructions()
{
    // PrintLine(TEXT("Press enter to continue..."));
}

void UBullCowCartridge::DecrementTries(const bool &Freebie)
{
    if (Freebie && Freebies-- > 0)
    {
        PrintLine(TEXT("- Be careful, this will reduce your\n  available tries in the future."));
    }
    else
    {
        --Tries;
    }
}

// bool UBullCowCartridge::IsIsogram(const FString &Word) const // When the player hits enter
bool UBullCowCartridge::IsIsogram(const FString &Word) // When the player hits enter
{
    TCHAR Letter;
    for (int32 Index = 0; Index < Word.Len() - 1; Index++)
    {
        Letter = Word.ToUpper()[Index];
        for (int32 Comparison = Index + 1; Comparison < Word.Len(); Comparison++)
        {
            if (Letter == Word.ToUpper()[Comparison])
            {
                return false;
            }
        }
    }
    return true;
}

void UBullCowCartridge::ProcessGuess(const FString &Guess) // When the player hits enter
{
    if (Guess.ToUpper() == HiddenWord.ToUpper())
    {
        PrintLine(TEXT("- You're a winner. Moo moo moo."));
        EndGame();
        return;
    }

    bool bIsIsogram = true;
    if (Guess == TEXT(""))
    {
        PrintLine(TEXT("- You need to enter something."));
        DecrementTries(true);
    }
    else if (Guess.Len() != HiddenWord.Len())
    {
        PrintLine(TEXT("- Your guess should be a length of %i."), HiddenWord.Len());
        DecrementTries(true);
    }
    else if (!IsIsogram(Guess)) // Check if not isogram
    {
        PrintLine(TEXT("- Your guess needs to be an isogram."));
        DecrementTries(true);
    }
    else
    {
        FBullCowCount Count = GetBullCows(Guess);
        // int32 Bulls, Cows;
        // GetBullCows(Guess, Count.Bulls, Count.Cows);
        PrintLine(TEXT("You found %i bull%s and %i cow%s."), Count.Bulls, Count.Bulls == 1 ? "" : "s", Count.Cows, Count.Cows == 1 ? "" : "s");
        DecrementTries(false);
    }

    if (Tries <= 0)
    {
        PrintLine(
            TEXT("- I'm sorry, but the word we were looking\n  for was \"%s\""),
            *HiddenWord);
        EndGame();
    }
    else
    {
        PrintLine(TEXT("- That was incorrect. Try Again.\n- You have %i tries remaining."), Tries);
    }
}

// void UBullCowCartridge::GetBullCows(const FString &Guess, int32 &BullCount, int32 &CowCount) const
FBullCowCount UBullCowCartridge::GetBullCows(const FString &Guess) const
{
    FBullCowCount Count;
    // TCHAR Letter;
    for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
    {
        int32 LookupIndex;
        HiddenWord.ToUpper().FindChar(Guess.ToUpper()[GuessIndex], LookupIndex);

        if (LookupIndex != INDEX_NONE)
        {
            if (LookupIndex == GuessIndex)
            {
                Count.Bulls++;
            }
            else
            {
                Count.Cows++;
            }
        }
        // // Guess.FindChar
        // if (Guess.ToUpper()[GuessIndex] == HiddenWord.ToUpper()[GuessIndex])
        // {
        //     BullCount++;
        //     continue;
        // }
        // else
        // {
        // }

        // Letter = Guess.ToUpper()[GuessIndex];
        // for (int32 Comparison = 0; Comparison < Guess.Len(); Comparison++)
        // {
        //     if (Letter == HiddenWord.ToUpper()[Comparison])
        //     {
        //         if (Comparison == GuessIndex)
        //         {
        //             BullCount++;
        //         }
        //         else
        //         {
        //             CowCount++;
        //         }
        //     }
        // }
    }

    return Count;
}

void UBullCowCartridge::OnInput(const FString &PlayerInput) // When the player hits enter
{
    if (!bGameOver)
    {
        ProcessGuess(PlayerInput);
    }
    else
    {
        if (PlayerInput.ToUpper() == TEXT("Y"))
        {
            ClearScreen();
            SetupGame();
        }
    }
}

void UBullCowCartridge::EndGame()
{
    PrintLine(TEXT("- Do you wish to play agian?"));
    PrintLine(TEXT("- y for Yes."));
    bGameOver = true;
}

void UBullCowCartridge::SetupGame()
{
    // int32 RandomIndex = FMath::RandRange(0, ValidWords.Num() - 1);
    HiddenWord = ValidWords[FMath::RandRange(0, ValidWords.Num() - 1)];
    Tries = HiddenWord.Len() + 1;
    Freebies = 3;
    bGameOver = false;

    PrintLine(
        TEXT("- Guess the %i letter word."),
        HiddenWord.Len());
    PrintLine(
        TEXT("- You have %i guesses available."),
        Tries);
    PrintLine(TEXT("- Type in your guess and press enter."));
    // PrintLine(TEXT("The number of possible words is %i."), AvailableWords.Num());
    // PrintLine(TEXT("The number of valid words is %i."), ValidWords.Num());
    // PrintLine(TEXT("Hidden Word is: %s"), *HiddenWord);
}
2 Likes

I’m glad you are learning a lot with the section. You are on your way to being a C++ and Unreal master.

Privacy & Terms