Hi, I keep getting this error when putting together the ValidWords:
Assertion failed: IsValidIndex(Index) [File:C:\Program Files\Epic Games\UE_4.22\Engine\Source\Runtime\Core\Public\Containers/UnrealString.h] [Line: 201] String index out of bounds: Index 7 from a string with a length of 7
// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"
#include "Containers/UnrealString.h"
#include "HiddenWordList.h"
void UBullCowCartridge::BeginPlay() // When the game starts
{
Super::BeginPlay();
TArray<FString> CheckWords = GetValidWords(Words);
PrintLine(TEXT("The number of possible words are: %i."), CheckWords.Num());
SetupGame();//Setting up game
//debug only
/* PrintLine(TEXT("The Hidden Word is: %s."), *HiddenWord);// debug line
PrintLine(TEXT("\nIts length is: %i"), HiddenWord.Len());// debug line */
}
void UBullCowCartridge::OnInput(const FString& Input) // When the player hits enter
{
//Main loop on entry by Player
if (bGameOver)//is Game Over?
{
ClearScreen();
SetupGame();
} else if(!bGameOver)//checking guess
{
ProcessGuess(Input);
}
}
void UBullCowCartridge::SetupGame()
{
//Initialize Member Variable(s)
HiddenWord = TEXT("ounces");
Lives = HiddenWord.Len();
bGameOver = false;
//Welcome message
PrintLine(TEXT("Welcome Player to Bull Cows!"));
PrintLine(TEXT("Guess the %i letter magic word..."), HiddenWord.Len());
PrintLine(TEXT("You have %i Lives to guess the word..."), Lives);
PrintLine(TEXT("Type in your guess and\nPress <ENTER> to continue..."));
/* const TCHAR HW[] = TEXT("peaches");
//const TCHAR HW = {TEXT('o'), TEXT('u'), TEXT('n'), TEXT('c'), TEXT('e'), TEXT('s'), TEXT('\0')};
PrintLine(TEXT("Character 1 of the hidden word is: %c"), HiddenWord[0]);//should print first char of the word "o"
PrintLine(TEXT("Character 4 of HW array is: %c"), HW[3]); */
}
void UBullCowCartridge::EndGame()
{
bGameOver = true;
PrintLine(TEXT("\nThe Game is Over\nPress <ENTER> to play again..."));
}
void UBullCowCartridge::ProcessGuess(FString Guess)
{
if (Guess == HiddenWord)
{
PrintLine(TEXT("You Won!"));
EndGame();
return;
}
//Check length of guess to length of Hidden Word
if (Guess.Len() != HiddenWord.Len())
{
PrintLine(TEXT("The HiddenWord is %i letters long"), HiddenWord.Len());
PrintLine(TEXT("Sorry, guess not same length as word\nYou have %i lives left..."), Lives);
return;
}
//Check if it's an isogram
if (!IsIsogram(Guess))
{
IsIsogram(Guess);
//IsIsogram return a bool on whether it's an Isogram or not, if not
PrintLine(TEXT("No repeating letters allowed,\nYou have lost a life\nGuess again!\nYou have %i lives left."), Lives);
//remove Life
--Lives;
return;
}
//Remove a Life
PrintLine(TEXT("You have lost a life...\nYou have %i lives left."), Lives);
--Lives;
//check if any Lives left
if (Lives <= 0)
{
ClearScreen();
PrintLine(TEXT("You have no lives left, the cows rejoice"));
PrintLine(TEXT("The Hidden Word was %s.\nGood job for doing as well as you did..."), *HiddenWord);
EndGame();
return;
}
//Show player the Bulls and Cows
PrintLine(TEXT("Guess again, you have %i Lives left..."), Lives);
}//end ProcessGuess
bool UBullCowCartridge::IsIsogram(FString Word) const
{
//get length of Guess, so we know our outer bounds
int32 GuessLength = Word.Len();
int32 Comparison = 0;
while (GuessLength!=0)
{
//Guess
for (int32 Index = 0; Index < GuessLength; Index++)
{
Comparison = Index+1;
//outer loop starts with Index
if (Word[Index] == Word[Comparison])
{
//Inner loops starts with Comparison, steps through remaining chars
for (; Comparison < GuessLength; Comparison++)
{
if (Word[Index] == Word[Comparison])
{
return false;
}
}
return false;
}//end if
}//end for
GuessLength--;
}
return true;
}
TArray<FString> UBullCowCartridge::GetValidWords(TArray<FString> WordList) const
{
TArray<FString> ValidWords;
//step through all of Words
for (int32 Index = 0; Index < WordList.Num(); Index++)
{
// Check for Isograms between 4 and 8 Characters long
if (WordList[Index].Len() >= 4 && WordList[Index].Len() <= 8 && IsIsogram(WordList[Index]))
{
ValidWords.Emplace(WordList[Index]);
}
}
return ValidWords;
}//end ISIsogram
/*
int32 Comparison = 0;
//IsIsogram check of the letters in the word
for (int32 Index = 0; Index < Words[Index].Len(); Index++)
{
Comparison = Index+1;
//outer loop starts with Index
if (Words[Index] == Words[Comparison])
{
//Inner loops starts with Comparison, steps through remaining chars
for (; Comparison < Words[Index].Len(); Comparison++)
{
//Check if letters identical
if (Words[Index] == Words[Comparison])
{
//end the comparison loop with first positive
break;
}else// otherwise carry on
{
//if not add to array of ValidWords
ValidWords.Emplace(Words[Index]);
}
}
}//end if
}//end for
}//end outer if
*/
That is an incorrect implementation of IsIsogram for 2 reasons.
You go out of bounds of the string
You don’t compare each letter with each other.
For the word “ability” you do the following comparisons
a == b
b == i
i == l
l == i
i == t
t == y
y == ???? # go out of bounds here
And you would do that 7 times and the function would return true which is incorrect as that word is not an isogram.
On a side note, you do not use Comparison outside of the for loop so you shouldn’t define it at the start of the function. You should define variables in the smallest possible scope.