HiddenWord Variable not storing return value from IsValidWord() function

I am following the Unreal 4.22 C++ Developer Course and am stuck at the “Random And The UE4 Docs” segment. When I use the GetValidWords function to set the HiddenWord variable and PrintLine the output, it is always blank and the length of the word is always zero.

This happens when I use RandRange or just accessing the array element directly. (I can still throw it out of bounds and crash unreal if its larger than the array). I also tried calling IsValidWords and storing the return value in a temporary array and then setting HiddenWords to the temporary array and still get a blank word and zero value for length.

Hard coding the HiddenWord variable works as normal and the debug lines used to print the number of words in Words and the ValidWords array are showing the correct number in all cases.

There are no errors or compile problems in any of the files.

Notable changes:

  • I am only using 13 words for my list and it narrows to 4, not the full 1000 word list.
  • Unreal Version 4.26.1
  • Visual Studio 2019
// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"
#include "HiddenWordList.h"

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

    PrintLine(TEXT("%i"), FMath::RandRange(0, 10)); //RandRange test is working
    
    SetupGame();

    PrintLine(TEXT("The number of hidden words is %i"), Words.Num()); //Debug -This is working correctly
    PrintLine(TEXT("The number of valid words is %i"), GetValidWords(Words).Num()); //Debug -This is working correctly  
    PrintLine(TEXT("The hidden word is: %s and is %i long"), *HiddenWord, HiddenWord.Len());  //Debug -This works when HiddenWord is hard coded but prints out the blank line and zero length otherwise
    
}


void UBullCowCartridge::OnInput(const FString& Input) // When the player hits enter
{
    if (bGameOver)
    {
        ClearScreen();
        SetupGame();
        
        return;
    }
    if (Lives > 0)
    {
        ProcessGuess(Input);
    }
    else
    {
        PrintLine(TEXT("You are out of lives! Game over!"));
        EndGame();
    }
}

void UBullCowCartridge::SetupGame()
{
     //Greet Player
    PrintLine(TEXT("Welcome to Cows and Bulls"));

    HiddenWord = GetValidWords(Words)[0]; //This seems to return nothing to hidden word when called.
    Lives = HiddenWord.Len();
    bGameOver = false;
    
    PrintLine(TEXT("Guess the %i letter word"), HiddenWord.Len());
    PrintLine(TEXT("Press enter to continue"));
    PrintLine(TEXT("You have %i lives"), Lives);
}

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

bool UBullCowCartridge::IsIsogram(const FString& Word) const
{
    for (int32 Index = 0; Index < Word.Len(); Index++)
    {
        for (int32 Compare = Index + 1; Compare < Word.Len(); Compare++)
        {
            if (Word[Index] == Word[Compare]) //Dont forget that you need to compare the index of Word not just the index itself.
            {
                //not iso
                //PrintLine(TEXT("No repeating letters, Guess again"));
                return false;
            }
        }

    }
    return true;

}

TArray<FString> UBullCowCartridge::GetValidWords(const TArray<FString>& WordList) const
{
    TArray<FString> ValidWords;
    // Range based for loop. Used to loop through a collection things, usually an array
    for (FString Word : WordList)
    {
        if (Word.Len() >= 4 && Word.Len() < 8 && IsIsogram(Word))
        {
            ValidWords.Emplace();
        }
    }
    return ValidWords;
}

void UBullCowCartridge::ProcessGuess(const FString& Guess)
{
    // Check Guess
    if (Guess == HiddenWord)
    {
        PrintLine(TEXT("They are a match! You Win!"));
        EndGame();
        return;
    }

    //Check number of charaters
    if (Guess.Len() != HiddenWord.Len())
    {
        PrintLine(TEXT("The hidden word is %i characters long, Guess again"), HiddenWord.Len());
        PrintLine(TEXT("you have %i lives remaining"), Lives);
        return;
    }

  
    //isogram check
    if (!IsIsogram(Guess))
    {
        //Check 
        PrintLine(TEXT("No repeating letters, Guess again"));
        return;
    }

    //remove life
    PrintLine(TEXT("Lost a life!"), Lives);
    --Lives;

    //check lives < 0
    if (Lives <= 0)
    {  
        ClearScreen();
        PrintLine(TEXT("You have no lives left! Game over"));
        PrintLine(TEXT("The hidden word was: %s"), *HiddenWord);
        EndGame();
        return;
    }
    //Show player Bulls and Cows
    PrintLine(TEXT("Guess again, You have %i lives left"), Lives);
}

Screenshot of the game with incorrect ouput:

Adding an update to my post above. I found that when I remove the ‘&’ reference from the GetValidWords function and return a copy instead I get the correct behavior. It seems that whatever is being passed back in that memory location when done by reference is returning incorrectly? Something is getting lost along the way.

ValidWords.Emplace();

This is emplacing a default constructed FString i.e. it’s the same as ValdWords.Emplace(FString()). You need to pass Word

ValidWords.Emplace(Word);
1 Like

Yep this is what I missed, it’s working correctly. Thank you Dan! much appreciated!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.