TaurusBos Game: Complete

Hello, I have finally completed the TaurusBos (Latin for BullCow) game.

I have created a new topic becuase it is a rather large post compared to the original one.

Features:

  1. Roman Numerals replace all numbering

  2. Main menu: Play, Rules, Quit game

  3. Choose Difficulty: Facile, Medio, Arduus- this is a secondary game setup.

  • Once a difficulty level has been chosen, the player cannot type in “play” to change the difficulty unless the player quits, wins, or loses. Otherwise they will get an “invalid option” message.
  • Each difficulty level dictates how many levels you must complete before you win, the minimum and maximum word length, and how many lives you get.
  • I got some inspiration for my level and menu feature from this post by Kaypocalypse and then went about it my own way as the direction of my own game dictated.
  1. Quit Game feature (Yes or No prompt)

  2. Hint code based off of Kamil_Kolodziejczak work, but in addition saved the answer to the header so that the player can always refer back to the hint.

  • I also had to fix a error in the code, it was calling up the player input as part of its random hint process. I was getting wrong letters. The fix was simple enough, direct it to my hiddenword.
  1. EndGame will depict different messages depending if you won or are quitting.

  2. Closed gaps in the code so that answers will not cause crashes: ex. If do not type in a difficulty, that section will simply prompt the player to type one in until one has been typed in, except if you want to quit or view the rules.

  3. Nothing typed in will not make one lose a life, but will prompt to type something in.

Most importantly:
FIXED: the BullCowCount (or in my case TaurusBos Count) has been fixed. I will post this with the code and on its own. The problem was the whenever the guess was longer than the hidden word it would crash the system, being that there was nothing else to check.

I did a twofold process. I converted the Guess array and the Hidden word array into int32’s by converting the player’s input and the hidden word into integers using int32 member variables, then using them as my conditions for an if/else statement to compare the lengths without crashing the system.

  • If GuessLength > HiddenWordLength, then limit GuessIndex by HiddenWord.Len() (Index< HiddenWord).
  • Else GuessIndex will check the hidden word, but use its own length as the limit.

Thus if the guess is “Bos” and the HiddenWord is “Taurus”, it will only check the first 3 letters of the Hidden world. If the guess is Taurus, and the HiddenWord is Bos, then it will only compare the first 3 letters of the guess to the rest.
Not Perfect, but it will work.

BullCow cpp

`#include "BullCowCartridge.h"
#include "LatinWordList.h"
#include "RomanNumerals.h"


//------1. BEGIN------
void UBullCowCartridge::BeginPlay() 
{
    Super::BeginPlay();
    SetupGame();
}


//------2. INPUT------
void UBullCowCartridge::OnInput(const FString& PlayerInput) 
{  
   //  Game Over
    if (bGameOver == true || bRules == true)
    {
        ClearScreen();
        SetupGame();
        return;   
    } 

    //Quit
    if (bQuit == true)
    {
        if (PlayerInput == TEXT("yes"))
        {
            ClearScreen();
            EndGame();
            return;
        }
        if (PlayerInput == TEXT("no"))
        {
            ProcessGuess(PlayerInput);
            return;
        }
        else
        {
            PrintLine(TEXT("Please type in Yes or No."));
            return;
        }       
    }
    
    //Play
    if (bPlay == true && bDifficultySetup == false)// if player has not set up game yet.
    {
        Difficulty(PlayerInput);
        return;
    }

    // Hint
    if (PlayerInput == TEXT("Hint") && bDifficultySetup == true) 
    {
        RandomLetterHint(PlayerInput);
        bHint = true;
        return;
    }
    
    //Process Guess
    else 
    {
        ProcessGuess(PlayerInput);
        return;
    }
}  


//------3. SETUP------
void UBullCowCartridge::SetupGame()
{
    //Basic Setup
    Level = 0;
    Lives = 0;
    MaxLevel = 0;
    bGameOver = false;
    bQuit = false;
    bRules = false;
    bDifficultySetup = false;
    bPlay = false;
    bHint = false;
    bWin = false;
    bLose = false;
    
    //bNextLevel;

    PrintLine(TEXT("Salve! Welcome to TaurusBos!"));
    PrintLine(TEXT(""));
    PrintLine(TEXT("Type in any of the the Following: \n Play \n Rules \n Quit"));
}


//-----4. END GAME-----
void UBullCowCartridge::EndGame()
{
    if (bWin == true)
    {
        bGameOver = true;
        PrintLine(TEXT("Veni, Vidi, Vici! \n You Win!"));
        PrintLine(TEXT("Press Enter to play again..."));
        return;
    }
    if (bLose == true)
    {
        bGameOver = true;
        PrintLine(TEXT("Me Paenitet! You have runout of lives!"));
        PrintLine(TEXT("The hidden word was: %s."), *HiddenWord);
        PrintLine(TEXT("Press Enter to play again..."));
        return;
    }
    else
    {
        bGameOver = true; 
        PrintLine(TEXT("Vale! Gratias Tibi Agere.\nBye! Thank you for playing!"));
        PrintLine(TEXT("\nPress Enter to play again..."));
    }
}


//-----5. PROCESS GUESS-----
void UBullCowCartridge::ProcessGuess(const FString& Guess) 
{
// Nothing Typed
    if (Guess == TEXT(""))
        {
            PrintLine(TEXT("Please type something in"));
            return;
        }
    
// Play
    if (Guess == TEXT("play"))// true if type in "play" and the difficulty setup has not been set up yet.
    {
        if (bDifficultySetup == false)
        {   
            ClearScreen();
            PrintLine(TEXT(" Type in a difficulty level: \n Facile, \n Medio, \n Arduus")); 
            bPlay = true;      
            return;
        }
        else
        {
            PrintLine(TEXT("Invalid Entry"));
            return;
        }
    }

// Rules
    if (Guess == TEXT("rules"))
    {
        if (bPlay == false)
        {
            ClearScreen();
            PrintLine(TEXT("TaurusBos is an Isogram guessing game."));
            PrintLine(TEXT("An Isogram is any word that does not have any repeating letters in it. You have a")); 
            PrintLine(TEXT("number of levels to complete, and will"));
            PrintLine(TEXT("lose lives if the word is incorrect or is not an Isogram. type in \"Hint\" at any"));
            PrintLine(TEXT("point to get help for a word."));
            PrintLine(TEXT("\n Taurus = Letter in Right place\n Bos = Right Letter, Wrong Place"));
            bRules = true;
            return;
        }
        else// will not bring one back to the startup screen.
        {
            ClearScreen();
            PrintLine(TEXT("TaurusBos is an Isogram guessing game."));
            PrintLine(TEXT("An Isogram is any word that does not have any repeating letters in it. You have a")); 
            PrintLine(TEXT("number of levels to complete, and will"));
            PrintLine(TEXT("lose lives if the word is incorrect or is not an Isogram. type in \"Hint\" at any"));
            PrintLine(TEXT("point to get help for a word."));
            PrintLine(TEXT("\n Taurus = Letter in Right place\n Bos = Right Letter, Wrong Place"));
        }
    return;
    }

// Quit
    if (Guess == TEXT("quit"))
        {
            PrintLine(TEXT("Are you sure you want to quit? Yes/No?"));
            bQuit= true;// triggers quit options.
            return;
        }

// "No" Extention takes into account if typed in "play" or not
    if (Guess == TEXT("No") && bQuit == true)
    {
        if (bPlay == false)
        {
            ClearScreen();
            SetupGame();
            return;
        }
        else
        {
            ClearScreen();
            PrintLine(TEXT("Guess the %s letter Hidden Word"), *Numerals[HiddenWord.Len()]);
            PrintLine(TEXT("You currently have %s lives left."), *Numerals[Lives]);
            PrintLine(TEXT("The Hidden Word is: %s"), *HiddenWord);
            bQuit = false;
            return;
        }
    }

// Check Guess
    else
    {
        if (bDifficultySetup == true) // to insure that it does not check the guess if the game has not been setup yet.
        {
            CheckGuess(Guess);
            return;
        }
        else
        {
            return;
        }
    }
}


//-----6. SETUP DIFFICULTY-----
void UBullCowCartridge::Difficulty(const FString& Difficulty)
{

//  EASY
    if (Difficulty == TEXT("facile"))// This is a secondary setup.
    {
    MinLength = 3;
    MaxLength = 6;
    Isograms = GetValidWords(Verba);
    HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num() -1)];
    Lives = HiddenWord.Len() * 2;
    MaxLevel = 3; 
    Level = 1;// so not to start at level "no"

    ClearScreen();
    PrintLine(TEXT("TaurusBos difficulty has been set to: \nFacile"));
   PrintLine(TEXT("* Word Lengths are set to %s-%s letters long\n* There are %s levels to complete"), *Numerals[MinLength], *Numerals[MaxLength], *Numerals[MaxLevel]);
    PrintLine(TEXT("* Lives are Doubled"));
    PrintLine(TEXT("Guess the %s letter word."), *Numerals[HiddenWord.Len()]);
    PrintLine(TEXT("The Hidden Word is: %s"), *HiddenWord);// debug line

    bDifficultySetup = true;// turns off setup

    return;
}
// MEDIUM
    if (Difficulty == TEXT("medio"))
    {
        MinLength = 4;
        MaxLength = 8;
        Isograms = GetValidWords(Verba);
        HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num() -1)];
        Lives = HiddenWord.Len() *2; 
        MaxLevel = 6;
        Level = 1;
        
        ClearScreen();
        PrintLine(TEXT("TaurusBos difficulty has been set to: Medio"));
        PrintLine(TEXT("* Word Lengths are set to %s-%s letters long\n* There are %s levels to complete"), *Numerals[MinLength], *Numerals[MaxLength], *Numerals[MaxLevel]);
        PrintLine(TEXT("* Lives are Doubled"));
        PrintLine(TEXT("Guess the %s letter word."), *Numerals[HiddenWord.Len()]);
        PrintLine(TEXT("The Hidden Word is: %s"), *HiddenWord);// debug line
        
        bDifficultySetup = true;
        
        return;
        }
// HARD
        if (Difficulty == TEXT("arduus"))
        {
            MinLength = 5;
            MaxLength = 10;
            Isograms = GetValidWords(Verba);
            HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num() -1)];
            Lives = HiddenWord.Len(); 
            MaxLevel = 8;
            Level = 1;

            ClearScreen();
            PrintLine(TEXT("TaurusBos difficulty has been set to: Arduus"));
            PrintLine(TEXT("* Word Lengths are set to %s-%s letters long\n* There are %s levels to complete"), *Numerals[MinLength], *Numerals[MaxLength], *Numerals[MaxLevel]);
            PrintLine(TEXT("Guess the %s letter word."), *Numerals[HiddenWord.Len()]);
            PrintLine(TEXT("The Hidden Word is: %s"), *HiddenWord);// debug line
            
            bDifficultySetup = true;
            
            return;
        }     
    else
    {
        PrintLine(TEXT("Please type in a Difficulty: \n Facile \n Medio \n Arduus"));
        return;
    }    
}


//-----7. CHECK GUESS-----
void UBullCowCartridge::CheckGuess(const FString& PassGuess)
 {
// ALL LEVELS COMPLETE?
    if (PassGuess == HiddenWord && Level == MaxLevel)
        {
            ClearScreen();
            bWin = true;
            EndGame(); 
            return;
        }
// CURRENT LEVEL COMPLETE?
    if (PassGuess == HiddenWord && Level < MaxLevel)// checks to see if current level is completed
        {
            ClearScreen();
            PrintLine(TEXT("Vici! You passed level %s.\nYou have %s levels left to go!"), *Numerals[Level], *Numerals[MaxLevel - Level]);
            ++Level;
            HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num()-1)];// refreshes hidden word.
            Lives = HiddenWord.Len();// refreshes lives?
            PrintLine(TEXT("The next Hidden Word is: %s"), *HiddenWord);
            PrintLine(TEXT("It is %s letters long"), *Numerals[HiddenWord.Len()]);
            PrintLine(TEXT("You have %s lives."), *Numerals[Lives]);
            bHint = false;
            return;
        }
    ClearScreen();
    PrintLine(TEXT("Me Paenitet, your answer was incorrect,"));
       
// LengthCheck(PassGuess);
    if (PassGuess.Len() != HiddenWord.Len())
    {
        PrintLine(TEXT("The hidden word is %s letters long."), *Numerals[HiddenWord.Len()]);
    } 
    GuessLength = PassGuess.Len();// remembers length as an int for Taurus?Bos Check.
    HiddenLength = HiddenWord.Len();

//Isogram?
    if (!IsIsogram(PassGuess))
    {
        PrintLine(TEXT("You have repeating letters!"));
    } 

// No more lives
    if (Lives <= 0)     
    {
        ClearScreen();
        bLose = true;
        EndGame();
        return;
    }

     PrintLine(TEXT("You lost a Life!"));
    --Lives;     

// Show the player BUlls and Cows
    FTaurusBosCount Score = GetTaurusBos(PassGuess); 
   
    PrintLine(TEXT("You have %s Tauri and %s Boves"), *Numerals[Score.Taurus], *Numerals[Score.Bos]);
    PrintLine(TEXT("Guess again, you have %s lives left."), *Numerals[Lives]);
}



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



//-----9. GET VALID WORDS-----
TArray<FString> UBullCowCartridge::GetValidWords(const TArray<FString>& WordList) const
{
    TArray<FString> ValidWords; //Making the empty storage unit: the variable. 

    for (const FString& Word : WordList )
    {  
        if (Word.Len() >= MinLength && Word.Len() <= MaxLength && IsIsogram(Word) )//Checks specific word 
        {
            ValidWords.Emplace(Word);            
        }
    }
    return ValidWords;
}



//-----10. GET TAURUSBOS NUMBERS-----
FTaurusBosCount UBullCowCartridge::GetTaurusBos(const FString& Guess) const
{
    FTaurusBosCount Count;

    //*************************FIXED ISSUE**********************************

    // For every index Guess is the same as Index of the HiddenWord, BullCount++
    //If not a bull, was it a cow? If yes, CowCount++

    // The if/else statement added here ensures that any TArray does not go out of the shortest array length, thus avoiding crashing.
    if (GuessLength > HiddenLength)// IF Guess is Greater than Hiddenword Length, only check Guess up to Hidden Word Length.
    {
        for (int32 GuessIndex = 0; GuessIndex < HiddenWord.Len(); GuessIndex++)
        {
            if  (Guess[GuessIndex] == HiddenWord[GuessIndex])
            {
                Count.Taurus++;
                continue;   
            }
            for (int32 HiddenIndex = 0; HiddenIndex < HiddenWord.Len(); HiddenIndex++)
            {
                if  (Guess[GuessIndex] == HiddenWord[HiddenIndex])
                {
                    Count.Bos++;
                    break;
                }
            }       
        }
        return Count;
    }
    else  // If if Guess is less than HiddenWord Length, Check against Guess length
    {
        for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
    {
        if  (Guess[GuessIndex] == HiddenWord[GuessIndex])
        {
            Count.Taurus++;
            continue;   
        }
        for (int32 HiddenIndex = 0; HiddenIndex < Guess.Len(); HiddenIndex++)
        {
            if  (Guess[GuessIndex] == HiddenWord[HiddenIndex])
            {
                Count.Bos++;
                break;
            }
        }       
    }
    return Count;
    }    
}

//-----11. HINT-----
// clever hint system by Kamil_Kolodziejczak at GameDev.tv.
void UBullCowCartridge::RandomLetterHint(const FString& Hint) 
{
    FString VerbumHint;
    
    if (bHint == false)
    {    const int32 RandomHint = FMath::RandRange(0, HiddenWord.Len()-2);// the last letter is not hinted at because there is a hint already there.

        for (int32 Index= 0; Index < HiddenWord.Len(); Index++)
        {
            if (Index == RandomHint)
            {
                VerbumHint.AppendChar (Hint[Index]);// this puts a letter where the random hint is randomly located, one letter as hit
                continue;
            }
            VerbumHint.Append ("*"); // very clever trick, I like this; this will place "*" wherever Index and RandomHint do not meet. 
        }
        VerbumH = VerbumHint;// Matter of Hierarchy. Would not take this before because in the wrong spot.
        PrintLine(TEXT("a, o, e, i, t, r, m, s. "));
        PrintLine(TEXT("The Hint is: %s"), *VerbumHint); 
        return;
    }
    else
    {
        PrintLine(TEXT("a, o, e, i, t, r, m, s. "));
        PrintLine(TEXT("The Hint is: %s"), *VerbumH);
    }

    return;    
}`

My Latin Word List (I keep finding English words scattered about, but it was the best (or rather only) wordlist I could find at the time:

#pragma once
#include "CoreMinimal.h"

//ForLatin
const TArray<FString> Verba =

{
TEXT("ut"),
TEXT("sum"),
TEXT("eius"),
TEXT("quod"),
TEXT("ipse"),
TEXT("fuit"),
TEXT("nam"),
TEXT("in"),
TEXT("sunt"),
TEXT("cum"),
TEXT("illi"),
TEXT("esse"),
TEXT("at"),
TEXT("unum"),
TEXT("habent"),
TEXT("hoc"),
TEXT("de"),
TEXT("calidum"),
TEXT("verbo"),
TEXT("sed"),
TEXT("quod"),
TEXT("aliqua"),
TEXT("est"),
TEXT("quod"),
TEXT("vos"),
TEXT("vel"),
TEXT("quod"),
TEXT("in"),
TEXT("de"),
TEXT("ut"),
TEXT("et"),
TEXT("a")
TEXT("in"),
TEXT("nos"),
TEXT("potest"),
TEXT("ex"),
TEXT("alia"),
TEXT("erant"),
TEXT("quibus"),
TEXT("facite"),
TEXT("eorum"),
TEXT("tempore"),
TEXT("si"),
TEXT("voluntas"),
TEXT("quam"),
TEXT("Dixitque"),
TEXT("an"),
TEXT("quisque"),
TEXT("indica"),
TEXT("quod"),
TEXT("tribus"),
TEXT("volo"),
TEXT("aer"),
TEXT("etiam"),
TEXT("etiam"),
TEXT("fabula"),
TEXT("parva"),
TEXT("finem"),
TEXT("posuit"),
TEXT("domum"),
TEXT("lego"),
TEXT("manibus"),
TEXT("portus"),
TEXT("magna"),
TEXT("eamque"),
TEXT("addunt"),
TEXT("etiam"),
TEXT("terra"),
TEXT("hic"),
TEXT("necesse"),
TEXT("magnum"),
TEXT("princeps"),
TEXT("talis"),
TEXT("sequitur"),
TEXT("actum"),
TEXT("quid"),
TEXT("quaeris"),
TEXT("homines"),
TEXT("mutatio"),
TEXT("abiit"),
TEXT("lucem"),
TEXT("quaedam"),
TEXT("domus"),
TEXT("ipsum"),
TEXT("tentant"),
TEXT("nos"),
TEXT("rursus"),
TEXT("pecus"),
TEXT("punctum"),
TEXT("mater"),
TEXT("orbis"),
TEXT("prope"),
TEXT("aedificabis"),
TEXT("ipsum"),
TEXT("terra"),
TEXT("pater"),
TEXT("aliqua"),
TEXT("novum"),
TEXT("opus"),
TEXT("pars"),
TEXT("accipe"),
TEXT("adepto"),
TEXT("factum"),
TEXT("vivo"),
TEXT("ubi"),
TEXT("postquam"),
TEXT("rursus"),
TEXT("parum"),
TEXT("nisi"),
TEXT("per"),
TEXT("hominis"),
TEXT("anno"),
TEXT("factum"),
TEXT("ostende"),
TEXT("omnis"),
TEXT("bonum"),
TEXT("me"),
TEXT("dabit"),
TEXT("nostrum"),
TEXT("sub"),
TEXT("nomen"),
TEXT("ipsum"),
TEXT("per"),
TEXT("iustus"),
TEXT("forma"),
TEXT("sententia"),
TEXT("magna"),
TEXT("puto"),
TEXT("dicunt"),
TEXT("adiuva"),
TEXT("humilis"),
TEXT("differunt"),
TEXT("vicissim"),
TEXT("causa"),
TEXT("tantum"),
TEXT("significant"),
TEXT("antequam"),
TEXT("movemur"),
TEXT("ius"),
TEXT("puer"),
TEXT("Vetus"),
TEXT("etiam"),
TEXT("idem"),
TEXT("quae"),
TEXT("omnes"),
TEXT("ibi"),
TEXT("cum"),
TEXT("ascendit"),
TEXT("usus"),
TEXT("tuus"),
TEXT("modo"),
TEXT("de"),
TEXT("multis"),
TEXT("tunc"),
TEXT("eorum"),
TEXT("scribo"),
TEXT("utinam"),
TEXT("sicut"),
TEXT("ita"),
TEXT("haec"),
TEXT("eius"),
TEXT("longis"),
TEXT("fac"),
TEXT("aliquid"),
TEXT("video"),
TEXT("eo"),
TEXT("duobus"),
TEXT("habet"),
TEXT("respice"),
TEXT("die"),
TEXT("potuit"),
TEXT("vade"),
TEXT("venit"),
TEXT("Feceruntque"),
TEXT("numerus"),
TEXT("tuba"),
TEXT("canerent"),
TEXT("nulla"),
TEXT("maxime"),
TEXT("populus"),
TEXT("mea"),
TEXT("supra"),
TEXT("scitis"),
TEXT("aquam"),
TEXT("quam"),
TEXT("prima"),
TEXT("qui"),
TEXT("ut"),
TEXT("descendit"),
TEXT("latere"),
TEXT("fuit"),
TEXT("nunc"),
TEXT("invenies"),
TEXT("caput"),
TEXT("stant"),
TEXT("ipse"),
TEXT("page"),
TEXT("ut"),
TEXT("patriae"),
TEXT("invenit"),
TEXT("dicendum"),
TEXT("scholae"),
TEXT("crescat"),
TEXT("studiorum"),
TEXT("etiam"),
TEXT("discant"),
TEXT("herba"),
TEXT("Cover"),
TEXT("cibum"),
TEXT("solis"),
TEXT("quatuor"),
TEXT("inter"),
TEXT("status"),
TEXT("custodi"),
TEXT("oculus"),
TEXT("numquam"),
TEXT("novissime"),
TEXT("dimitte"),
TEXT("cogitavit"),
TEXT("urbem"),
TEXT("lignum"),
TEXT("transire"),
TEXT("fundum"),
TEXT("difficile"),
TEXT("initium"),
TEXT("ut"),
TEXT("fabula"),
TEXT("Viderunt omnes"),
TEXT("tantum"),
TEXT("mare"),
TEXT("hauriret"),
TEXT("reliquit"),
TEXT("quondam"),
TEXT("currunt"),
TEXT("non"),
TEXT("cum"),
TEXT("turba"),
TEXT("proxime"),
TEXT("noctis"),
TEXT("ipsum"),
TEXT("vita"),
TEXT("pauci"),
TEXT("aquilonem"),
TEXT("liber"),
TEXT("ferte"),
TEXT("tulit"),
TEXT("scientia"),
TEXT("manducare"),
TEXT("locus"),
TEXT("amicitia"),
TEXT("coeperunt"),
TEXT("idea"),
TEXT("pisces"),
TEXT("montem"),
TEXT("subsisto"),
TEXT("quondam"),
TEXT("basi"),
TEXT("audite"),
TEXT("equo"),
TEXT("sectis"),
TEXT("certus"),
TEXT("vigilate"),
TEXT("colorem"),
TEXT("faciem"),
TEXT("lignum"),
TEXT("aperi"),
TEXT("videtur"),
TEXT("simul"),
TEXT("postero"),
TEXT("album"),
TEXT("filii"),
TEXT("incipe"),
TEXT("obtinuit"),
TEXT("ambulate"),
TEXT("exemplum"),
TEXT("relevare"),
TEXT("cartam"),
TEXT("semper"),
TEXT("musica"),
TEXT("eorum"),
TEXT("et"),
TEXT("caracterem"),
TEXT("saepe"),
TEXT("litteris"),
TEXT("usque"),
TEXT("mille passuum"),
TEXT("fluvio"),
TEXT("pedes"),
TEXT("cura"),
TEXT("secundo"),
TEXT("sufficit"),
TEXT("patet"),
TEXT("puella"),
TEXT("adulescens"),
TEXT("parata"),
TEXT("supra"),
TEXT("in perpetuum"),
TEXT("album"),
TEXT("tametsi"),
TEXT("sentio"),
TEXT("Disputatio"),
TEXT("avem"),
TEXT("mox"),
TEXT("corpus"),
TEXT("canem"),
TEXT("familia"),
TEXT("dirige"),
TEXT("aut statum"),
TEXT("relinquo"),
TEXT("canticum"),
TEXT("metiretur"),
TEXT("ostium"),
TEXT("Vestibulum"),
TEXT("nigrum"),
TEXT("breves"),
TEXT("numerales"),
TEXT("class"),
TEXT("spiritus"),
TEXT("quaestio"),
TEXT("fieri"),
TEXT("completum"),
TEXT("navem"),
TEXT("area"),
TEXT("dimidiam"),
TEXT("petrae"),
TEXT("ut"),
TEXT("ignis"),
TEXT("austri"),
TEXT("forsit"),
TEXT("frustrum"),
TEXT("nuntiavit"),
TEXT("cognovit"),
TEXT("factum"),
TEXT("cum"),
TEXT("omnis"),
TEXT("rex"),
TEXT("platea"),
TEXT("multiplicabo"),
TEXT("aliquid"),
TEXT("scilicet"),
TEXT("manete"),
TEXT("rotam"),
TEXT("pleni"),
TEXT("vi"),
TEXT("hyacintho"),
TEXT("obiectum"),
TEXT("decernere"),
TEXT("superficies"),
TEXT("abyssus"),
TEXT("lunam"),
TEXT("insulam"),
TEXT("pede"),
TEXT("ratio"),
TEXT("occupatus"),
TEXT("aliquam"),
TEXT("testimonium"),
TEXT("navicula"),
TEXT("commune"),
TEXT("aurum"),
TEXT("potest"),
TEXT("planum"),
TEXT("pro eo"),
TEXT("siccum"),
TEXT("admiramini"),
TEXT("rideat"),
TEXT("milia"),
TEXT("ago"),
TEXT("cucurrit"),
TEXT("reprehendo"),
TEXT("ludum"),
TEXT("figura"),
TEXT("aequat"),
TEXT("calidum"),
TEXT("requisierit"),
TEXT("adduxerunt"),
TEXT("calor"),
TEXT("nix"),
TEXT("piget"),
TEXT("adducet"),
TEXT("etiam"),
TEXT("imple"),
TEXT("orientem"),
TEXT("pingere"),
TEXT("lingua"),
TEXT("in"),
TEXT("unitas"),
TEXT("potestatem"),
TEXT("urbem"),
TEXT("Postremo"),
TEXT("quaedam"),
TEXT("fuge"),
TEXT("ceciderit"),
TEXT("ducit"),
TEXT("clamor"),
TEXT("obscuro"),
TEXT("apparatus"),
TEXT("exspecta"),
TEXT("consilium"),
TEXT("figura"),
TEXT("stella"),
TEXT("agro"),
TEXT("Reliqua"),
TEXT("recte"),
TEXT("potest"),
TEXT("libra"),
TEXT("factum"),
TEXT("pulchritudo"),
TEXT("coegi"),
TEXT("stetit"),
TEXT("continent"),
TEXT("ante"),
TEXT("docebit"),
TEXT("ultima"),
TEXT("deditque"),
TEXT("viridem"),
TEXT("acutus"),
TEXT("evolvere"),
TEXT("oceanus"),
TEXT("calidum"),
TEXT("absque"),
TEXT("minute"),
TEXT("confortare"),
TEXT("peculiarem"),
TEXT("animus"),
TEXT("retro"),
TEXT("patet"),
TEXT("caudae"),
TEXT("producere"),
TEXT("eo"),
TEXT("locus"),
TEXT("audivit"),
TEXT("optimum"),
TEXT("hora"),
TEXT("melius"),
TEXT("verum"),
TEXT("per"),
TEXT("centum"),
TEXT("quinque"),
TEXT("memores"),
TEXT("occasu"),
TEXT("terra"),
TEXT("attingere"),
TEXT("ieiunium"),
TEXT("verbo"),
TEXT("cantabo"),
TEXT("audite"),
TEXT("mensamque"),
TEXT("peregrinationes"),
TEXT("decem"),
TEXT("simplex"),
TEXT("vocali"),
TEXT("in"),
TEXT("bellum"),
TEXT("dormivitque"),
TEXT("contra"),
TEXT("exemplar"),
TEXT("tardus"),
TEXT("centrum"),
TEXT("amant"),
TEXT("aliquis"),
TEXT("pecuniam"),
TEXT("serviant"),
TEXT("appareant"),
TEXT("via"),
TEXT("tabula"),
TEXT("pluviae"),
TEXT("imperium"),
TEXT("regunt"),
TEXT("attrahendam"),
TEXT("frigus"),
TEXT("Observate"),
TEXT("vox"),
TEXT("navitas"),
TEXT("probabile"),
TEXT("cubili"),
TEXT("frater"),
TEXT("ovum"),
TEXT("Credere"),
TEXT("forsan"),
TEXT("colligunt"),
TEXT("repentino"),
TEXT("Numerabitis"),
TEXT("quadratum"),
TEXT("ideo"),
TEXT("longitudinis"),
TEXT("repraesentant"),
TEXT("subiectum"),
TEXT("regionem"),
TEXT("amplitudo"),
TEXT("habita"),
TEXT("dicere"),
TEXT("pondus"),
TEXT("generalis"),
TEXT("glaciem"),
TEXT("materia"),
TEXT("circulus"),
TEXT("par"),
TEXT("comprehendo"),
TEXT("divide"),
TEXT("syllabae"),
TEXT("sensi"),
TEXT("magnificum"),
TEXT("pila"),
TEXT("sed"),
TEXT("unda"),
TEXT("concrescunt"),
TEXT("cor"),
TEXT("sum"),
TEXT("praesens"),
TEXT("magna"),
TEXT("chorea"),
TEXT("locus"),
TEXT("brachium"),
TEXT("vela"),
TEXT("material"),
TEXT("fractionem"),
TEXT("saltus"),
TEXT("sedebitis"),
TEXT("generis"),
TEXT("fenestram"),
TEXT("aestas"),
TEXT("erant"),
TEXT("somnum"),
TEXT("probant"),
TEXT("agitur"),
TEXT("exercitium"),
TEXT("murum"),
TEXT("captiones"),
TEXT("montem"),
TEXT("volunt"),
TEXT("caelum"),
TEXT("tabulam"),
TEXT("gaudium"),
TEXT("scriptum"),
TEXT("fera"),
TEXT("instrumentum"),
TEXT("custodivit"),
TEXT("vitro"),
TEXT("faenum"),
TEXT("vitulus"),
TEXT("officium"),
TEXT("signum"),
TEXT("molli"),
TEXT("splendidum"),
TEXT("Vestibulum"),
TEXT("tempestas"),
TEXT("mense"),
TEXT("ferre"),
TEXT("peroratum"),
TEXT("beati"),
TEXT("spero"),
TEXT("flos"),
TEXT("induere"),
TEXT("mirum"),
TEXT("abiit"),
TEXT("commercia"),
TEXT("melodiam"),
TEXT("trinus"),
TEXT("officium"),
TEXT("accipiet"),
TEXT("os"),
TEXT("exactam"),
TEXT("signum"),
TEXT("mortuus"),
TEXT("minimus"),
TEXT("angustia"),
TEXT("jubila"),
TEXT("nisi"),
TEXT("scripsit"),
TEXT("iungere"),
TEXT("suadeant"),
TEXT("mundi"),
TEXT("aspiret"),
TEXT("dominae"),
TEXT("navale"),
TEXT("surgere"),
TEXT("malum"),
TEXT("ictus"),
TEXT("olei"),
TEXT("sanguis"),
TEXT("tangerent"),
TEXT("crevit"),
TEXT("miscere"),
TEXT("bigas"),
TEXT("perierat"),
TEXT("brunneis"),
TEXT("induere"),
TEXT("hortum"),
TEXT("aequales"),
TEXT("misit"),
TEXT("elige"),
TEXT("cecidit"),
TEXT("apta"),
TEXT("influunt"),
TEXT("pulchrae"),
TEXT("ripam"),
TEXT("colligunt"),
TEXT("salvum"),
TEXT("imperium"),
TEXT("decimales"),
TEXT("aurem"),
TEXT("aliud"),
TEXT("prorsus"),
TEXT("fregit"),
TEXT("ita"),
TEXT("mediam"),
TEXT("occides"),
TEXT("filius"),
TEXT("stagnum"),
TEXT("momento"),
TEXT("statera"),
TEXT("magna"),
TEXT("ver"),
TEXT("observa"),
TEXT("puer"),
TEXT("rectas"),
TEXT("consonans"),
TEXT("gentem"),
TEXT("lac"),
TEXT("celeritate"),
TEXT("methodo"),
TEXT("organo"),
TEXT("redde"),
TEXT("saeculi"),
TEXT("section"),
TEXT("habitus"),
TEXT("nubes"),
TEXT("mirantique"),
TEXT("quietum"),
TEXT("lapis"),
TEXT("vegrandis"),
TEXT("ascenditur"),
TEXT("frigus"),
TEXT("consilium"),
TEXT("pauper"),
TEXT("multum"),
TEXT("experimento"),
TEXT("imo"),
TEXT("ferrum"),
TEXT("una"),
TEXT("lignum"),
TEXT("viginti"),
TEXT("pelle"),
TEXT("risu"),
TEXT("rimula"),
TEXT("violet"),
TEXT("salire"),
TEXT("Praesent"),
TEXT("octo"),
TEXT("villa"),
TEXT("concurrunt"),
TEXT("radix"),
TEXT("emptum"),
TEXT("resuscitabo"),
TEXT("ferrum"),
TEXT("sive"),
TEXT("dis"),
TEXT("septem"),
TEXT("paragraph"),
TEXT("tertia"),
TEXT("numquid"),
TEXT("Posside"),
TEXT("capillum"),
TEXT("describere"),
TEXT("cocus"),
TEXT("pavimentum"),
TEXT("aut"),
TEXT("comburet"),
TEXT("tumulus"),
TEXT("salvum"),
TEXT("century"),
TEXT("considerate"),
TEXT("legem"),
TEXT("aliquam"),
TEXT("litore"),
TEXT("rescriptum"),
TEXT("silentium"),
TEXT("arenam"),
TEXT("solum"),
TEXT("volumen"),
TEXT("temperatus"),
TEXT("digitus"),
TEXT("industria"),
TEXT("pugna"),
TEXT("mendacium"),
TEXT("percute"),
TEXT("excitant"),
TEXT("naturalis"),
TEXT("visum"),
TEXT("sensum"),
TEXT("capitale"),
TEXT("nolo"),
TEXT("cathedra"),
TEXT("periculum"),
TEXT("fructus"),
TEXT("aliquid"),
TEXT("operantur"),
TEXT("praxi"),
TEXT("separatum"),
TEXT("difficile"),
TEXT("medicus"),
TEXT("obsecro"),
TEXT("protegat"),
TEXT("meridies"),
TEXT("seges"),
TEXT("modern"),
TEXT("aliquid"),
TEXT("ictus"),
TEXT("discipulo"),
TEXT("anguli"),
TEXT("pars"),
TEXT("copia"),
TEXT("cuius"),
TEXT("locant"),
TEXT("orbis"),
TEXT("captus"),
TEXT("tempus"),
TEXT("indica"),
TEXT("radio"),
TEXT("Locutusque"),
TEXT("atom"),
TEXT("hominis"),
TEXT("rerum"),
TEXT("effectus"),
TEXT("electrica"),
TEXT("sperare"),
TEXT("osse"),
TEXT("cogitis"),
TEXT("imaginari"),
TEXT("praestare"),
TEXT("conveniunt"),
TEXT("ita"),
TEXT("mitis"),
TEXT("mulier"),
TEXT("dux"),
TEXT("Suspicor"),
TEXT("necesse"),
TEXT("acutum"),
TEXT("alae"),
TEXT("partum"),
TEXT("proximus"),
TEXT("lava"),
TEXT("Biblia"),
TEXT("potius"),
TEXT("turba"),
TEXT("frumentum"),
TEXT("compare"),
TEXT("nervo"),
TEXT("tintinnabulum"),
TEXT("cibum"),
TEXT("fricabis"),
TEXT("celebre"),
TEXT("pupa"),
TEXT("fluvius"),
TEXT("timore"),
TEXT("visum"),
TEXT("tenuis"),
TEXT("triangulo"),
TEXT("planeta"),
TEXT("festinate"),
TEXT("princeps"),
TEXT("coloniam"),
TEXT("horologium"),
TEXT("mea"),
TEXT("tatem"),
TEXT("intrant"),
TEXT("major"),
TEXT("recentes"),
TEXT("quaerere"),
TEXT("minor"),
TEXT("mitto"),
TEXT("flavis"),
TEXT("sino"),
TEXT("mortuus"),
TEXT("locum"),
TEXT("deserto"),
TEXT("sectam"),
TEXT("current"),
TEXT("vitae"),
TEXT("surrexit"),
TEXT("perveniunt"),
TEXT("magister"),
TEXT("semita"),
TEXT("parente"),
TEXT("litore"),
TEXT("divisione"),
TEXT("linteum"),
TEXT("substantia"),
TEXT("gratiam"),
TEXT("Pertinent"),
TEXT("post"),
TEXT("expendas"),
TEXT("chorda"),
TEXT("adipem"),
TEXT("gavisus"),
TEXT("original"),
TEXT("statio"),
TEXT("Pater"),
TEXT("panem"),
TEXT("Testificor"),
TEXT("proprium"),
TEXT("segmentum"),
TEXT("servus"),
TEXT("anas"),
TEXT("ipsum"),
TEXT("gradum"),
TEXT("frequentare"),
TEXT("pullus"),
TEXT("carissimi"),
TEXT("hostem"),
TEXT("respondeo"),
TEXT("potum"),
TEXT("incididunt"),
TEXT("auxilium"),
TEXT("oratio"),
TEXT("natura"),
TEXT("range"),
TEXT("vapor"),
TEXT("motus"),
TEXT("semita"),
TEXT("liquidum"),
TEXT("stipes"),
TEXT("intelligantur"),
TEXT("quotus"),
TEXT("dentium"),
TEXT("testa"),
TEXT("cervicibus"),
TEXT("dolor"),
TEXT("mortem"),
TEXT("bellum"),
TEXT("peritia"),
TEXT("mulieres"),
TEXT("tempore"),
TEXT("solutio"),
TEXT("magnes"),
TEXT("argentum"),
TEXT("gratias"),
TEXT("ramum"),
TEXT("par"),
TEXT("etiamne"),
TEXT("maxime"),
TEXT("timere"),
TEXT("ingenti"),
TEXT("soror"),
TEXT("ferrum"),
TEXT("disputant"),
TEXT("simile"),
TEXT("dirige"),
TEXT("experientiam"),
TEXT("Octoginta"),
TEXT("pupillam"),
TEXT("emptum"),
TEXT("ductus"),
TEXT("picem"),
TEXT("tunica"),
TEXT("missa"),
TEXT("pecto"),
TEXT("cohors"),
TEXT("fune"),
TEXT("labente"),
TEXT("vincere"),
TEXT("somniatis"),
TEXT("ad vesperum"),
TEXT("condicionis"),
TEXT("pascuntur"),
TEXT("ferramentum"),
TEXT("totalis"),
TEXT("prima"),
TEXT("olfactus"),
TEXT("vallis"),
TEXT("neque"),
TEXT("duplex"),
TEXT("cathedra"),
TEXT("perseverant"),
TEXT("clausus"),
TEXT("cursus"),
TEXT("vende"),
TEXT("successu"),
TEXT("comitatu"),
TEXT("Auferatur"),
TEXT("eventus"),
TEXT("particularis"),
TEXT("multum"),
TEXT("natant"),
TEXT("oppositi"),
TEXT("uxorem"),
TEXT("calceum"),
TEXT("umero"),
TEXT("expandit"),
TEXT("disponere"),
TEXT("castra"),
TEXT("confingunt"),
TEXT("bombicis"),
TEXT("natus"),
TEXT("statuere"),
TEXT("quart"),
TEXT("novem"),
TEXT("dolor"),
TEXT("sonus"),
TEXT("plana"),
TEXT("forte"),
TEXT("congregate"),
TEXT("taberna"),
TEXT("tractum"),
TEXT("mittite"),
TEXT("luceat"),
TEXT("proprietate"),
TEXT("columna"),
TEXT("moleculo"),
TEXT("eligere"),
TEXT("iniuriam"),
TEXT("iterum"),
TEXT("requirunt"),
TEXT("lata"),
TEXT("praeparabit"),
TEXT("sal"),
TEXT("nasum"),
TEXT("iratus"),
TEXT("clamium"),
TEXT("continentem")

};

My Roman Numerals Header list:

#pragma once 
#include "CoreMinimal.h"

const TArray<FString> Numerals =

{
    TEXT("no"),
    TEXT("I"),
    TEXT("II"),
    TEXT("III"),
    TEXT("IV"),
    TEXT("V"),
    TEXT("VI"),
    TEXT("VII"),
    TEXT("VIII"),
    TEXT("IX"),
    TEXT("X"),
    TEXT("XI"),
    TEXT("XII"),
    TEXT("XIII"),
    TEXT("XIV"),
    TEXT("XV"),
    TEXT("XVI")
};

And my main Headerfile:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

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

struct FTaurusBosCount
{
	int32 Taurus = 0;
	int32 Bos = 0;
	// initializing to 0 since they will be nothing else at the start of the game. 
	// also protects us from garbage code filling up the space. 
};

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;
	void SetupGame();
	void EndGame();
	void ProcessGuess(const FString& Guess); // can ignore the variable names, but useful documentation.
	bool IsIsogram(const FString& Word) const;
	TArray<FString> GetValidWords(const TArray<FString>& WordList) const;  
	FTaurusBosCount GetTaurusBos(const FString& Guess) const;
	void CheckGuess (const FString& PassGuess);
	void Difficulty (const FString& Difficulty);
	void LengthCheck (const FString& Length);
	void NewWord ();
	void RandomLetterHint (const FString& Hint) ;


	// Your declarations go below!
	private:
	FString HiddenWord;
	int32 Lives; 
	bool bGameOver;
	TArray<FString> Isograms;
	int32 Level, MaxLevel;
	int32 MinLength, MaxLength;
	int32 GuessLength, HiddenLength;
	bool bQuit;
	bool bPlay;
	bool bNextLevel;
	bool bRules;
	bool bDifficultySetup;
	bool bHint;
	bool bWin;
	bool bLose;
	FString VerbumH;
	
		
};

The BullCowCount fix I figured out:

//-----10. GET TAURUSBOS NUMBERS-----
FTaurusBosCount UBullCowCartridge::GetTaurusBos(const FString& Guess) const
{
    FTaurusBosCount Count;

    //*************************FIXED ISSUE**********************************

    // For every index Guess is the same as Index of the HiddenWord, BullCount++
    //If not a bull, was it a cow? If yes, CowCount++

    // The if/else statement added here ensures that any TArray does not go out of the shortest array length, thus avoiding crashing.
    if (GuessLength > HiddenLength)// IF Guess is Greater than Hiddenword Length, only check Guess up to Hidden Word Length.
    {
        for (int32 GuessIndex = 0; GuessIndex < HiddenWord.Len(); GuessIndex++)
        {
            if  (Guess[GuessIndex] == HiddenWord[GuessIndex])
            {
                Count.Taurus++;
                continue;   
            }
            for (int32 HiddenIndex = 0; HiddenIndex < HiddenWord.Len(); HiddenIndex++)
            {
                if  (Guess[GuessIndex] == HiddenWord[HiddenIndex])
                {
                    Count.Bos++;
                    break;
                }
            }       
        }
        return Count;
    }
    else  // If if Guess is less than HiddenWord Length, Check against Guess length
    {
        for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
    {
        if  (Guess[GuessIndex] == HiddenWord[GuessIndex])
        {
            Count.Taurus++;
            continue;   
        }
        for (int32 HiddenIndex = 0; HiddenIndex < Guess.Len(); HiddenIndex++)
        {
            if  (Guess[GuessIndex] == HiddenWord[HiddenIndex])
            {
                Count.Bos++;
                break;
            }
        }       
    }
    return Count;
    }    
}

Finally, pictures
1.Main Menu


2.Rules

3. Quit option

4.Choose Difficulty level

5. Difficulty level chosen

6. Random hint and that hint is stored and is saved for each word. It will not give the last letter, as there is already a hint involved with it.

7. Completed Level

8.Win Message

9. Incorrect

10. Quit? No.

11. Quit, and its endgame message.

My process: I simply worked on one idea at a time until it worked. The Difficulty level probably took the most work, but the next most was making the entire thing ship tight to prevent any “leaking”. The menu was fairly intuitive once I figured out my “play” option, which was the most involved.

It was fun, took me the last week or two with a bit of time here and there, so probably around 15-20 hours, roughly 1hr and a half a day. I wanted it as tight as possible, so that if someone wanted to play it, it should not give any problems. I was tempted to do a point system, but I held off. It was a nicety, but not a necessity.

Enjoy!

2 Likes

Wow wow wow I am super impressed. Congratulations on your game! :partying_face:

1 Like

I’m glad my code was helpful to you. GJ :slight_smile:

1 Like

I found it to be very clever and an indispensable tool for my purposes. With some tweaking it fit in nicely.

Privacy & Terms