Using struct, GetBullCows() using FindChar and StringView

Here is my partial code. I used a struct to pass GetBullCow() function; also using FStringView and used FindChar instead of second loop; this is the part from ProcessGuess();

FBullCowCount Count;
   GetBullCows(Input, Count);
   PrintLine(TEXT("Bulls: %i, Cows: %i"), Count.Bulls, Count.Cows);

FBullCowCount is a struct defined in header file and i create an instance of it then pass it to function GetBullCows() . Here is my header file ;

struct FBullCowCount
{
	int32 Bulls = 0;
	int32 Cows = 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;
	virtual void OnInput(FStringView Input) override;
	void SetupGame();
	void EndGame();
	void ProcessGuess(FStringView Guess);	// Guess=Input
	void GetValidWords();
	bool IsIsogram(FStringView Guess) const;
	void GetBullCows(FStringView Guess, FBullCowCount& count);

	private:
		FString HiddenWord;
		int32 Lives{0};
		bool bGameOver{false};
		TArray<FString>WordList;
};

And here is the GetBullCow() function ;

void UBullCowCartridge::GetBullCows(FStringView Guess, FBullCowCount& Count)
{ 
    int32 Position{ 0 };
    for (int32 Index = 0; Index < Guess.Len(); ++Index)
    {
        HiddenWord.FindChar(Guess[Index], Position);
        if (Position == Index)
            ++Count.Bulls;
        else if (Position != INDEX_NONE)
            ++Count.Cows;
    }
}

FindChar() is a member function for FStringView or FString that takes a char; Guess[Index]

Position is a local int32 variable passed to FindChar(). This function looks for the character and the index of character is stored in the passed Position .
So if Position ==Index that means we have a cow;

if the character is not found Position == INDEX_NONE which means it does not exit

So in the else condition if Position != INDEX_NONE ; it means it exist but in a different position so we have cow.

1 Like

Wow great work! How did you figure all this out? Trial and error?

no…I just went over the implementation of the member function but it did not take too long to figure out because I was doing similar thing using C++ STL library…STL has more flexible tools but this one works OK.

HiddenWord or Guess is a String so when write Guess. then intellisense will bring list of member function you can go thru and see something you are looking and you do right click and select Peek Definition then it opens up related Engine file so you can look at the implementation there is a brief description over there too.

To be honest I understand better this way rather going thru Unreal Documentation …better to read the code :slight_smile:

I don’t yet understand what this means. Is it the same as int32 Position = 0? If yes, then what’s the difference? =)

Haven’t used FStringView yet, could you explain its function? How is it different from FString?

I also used FindChar, but a bit differently - it also returns bool if passed character is found (and I’m ignoring Index parameter). Here is my solution:

void UBullCowCartridge::CountBullsAndCows(const FString& Word, int32& Bulls, int32& Cows) const
{
    Bulls = 0, Cows = 0;
    for (int32 Index = 0; Index < Word.Len(); Index++)
    {
        const TCHAR Letter = Word[Index];
        if (Letter == HiddenWord[Index])
        {
            Bulls++;
            continue;
        }
        int32 _;
        if (HiddenWord.FindChar(Letter, _))
        {
            Cows++;
        }
    }
}

FStringView is like const char* and a the size which is used to view a FString; when you use const FString& it make a copy but when you have FStringView it refers to FString that is passed but does not make a copy ; it refers to the original String and it also store the size ; it is just more efficient but you need to make sure FString that you are using still exist otherwise it will be a dangling reference.
int32 Position{0} is same as int32 Position = 0;
I like to use brace initialization sometimes the other way around.

1 Like