Hi, in my BullCow Game i added some feature:
- Stage, for every Stage there are 3 Level and for each stage will affect Lives, Max HiddenWord Length, and Hint where in Stage 1 the Hint will showed and else will not showed
- Level, will affect the Length of HiddenWord
- Hint, we can see where the Bull position but the Hint will only show in Stage 1, also i add Hint for show the first letter of HiddenWord
BullCowCartridge.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"
#include "Misc/FileHelper.h"
#include "Misc/Paths.h"
void UBullCowCartridge::BeginPlay() // When the game starts
{
Super::BeginPlay();
const FString WordListPath = FPaths::ProjectContentDir() / TEXT("WordLists/HiddenWordList.txt");
FFileHelper::LoadFileToStringArray(Words, *WordListPath);
SetupGame();
}
void UBullCowCartridge::SetupGame()
{
//Set the Level
Level.LevelNow = 1;
Level.MaxLevel = 3;
Stage.StageNow = 1;
bGameOver = false;
NewLevel();
}
void UBullCowCartridge::OnInput(const FString &PlayerInput) // When the player hits enter
{
if (bGameOver)
{
ClearScreen();
SetupGame();
}
else
{
ProcessGuess(PlayerInput);
}
}
void UBullCowCartridge::EndGame()
{
bGameOver = true;
PrintLine(TEXT("Congaratulations you finish the game"));
PrintLine(TEXT("Press Enter, to play again!"));
}
void UBullCowCartridge::NewLevel()
{
ClearScreen();
if (Level.LevelNow > Level.MaxLevel)
{
Stage.StageNow++;
Level.LevelNow = 1;
}
if (Stage.StageNow > Stage.MaxStage)
{
EndGame();
return;
}
ValidWords = GetValidWords(Words);
HiddenWord = ValidWords[FMath::RandRange(0, ValidWords.Num() - 1)];
Lives = FMath::RoundToInt(HiddenWord.Len() * 1.5) - Stage.StageNow;
// Welcoming Player
PrintLine(TEXT("Welcome to Stage %i, Level %i"), Stage.StageNow, Level.LevelNow);
PrintLine(TEXT("The HiddenWord is: %s"), *HiddenWord);
PrintLine(TEXT("Guess the %i letter word!"), HiddenWord.Len());
PrintLine(TEXT("The first letter is '%c'"), HiddenWord[0]);
PrintLine(TEXT("You have %i Lives."), Lives);
PrintLine(TEXT("Type in your guess and, \npress enter to continue...")); // Prompt Player For Guess
}
void UBullCowCartridge::ProcessGuess(const FString &Guess)
{
// If the guess is true
if (Guess == HiddenWord)
{
Level.LevelNow++;
NewLevel();
return;
}
// Check Right Number Of Characters
if (Guess.Len() != HiddenWord.Len())
{
PrintLine(TEXT("The hidden word is %i letters long"), HiddenWord.Len());
PrintLine(TEXT("Sorry, try guessing again! \nYou have %i lives remaining"), Lives);
return;
}
// Check if Isogram
if (!IsIsogram(Guess))
{
PrintLine(TEXT("No repeating letters, guess again!"));
return;
}
// Remove Live
PrintLine(TEXT("Lost a life!"));
--Lives;
if (Lives <= 0)
{
ClearScreen();
PrintLine(TEXT("You have no lives left!"));
PrintLine(TEXT("The HiddenWord was: %s"), *HiddenWord);
EndGame();
return;
}
// Show the player Bulls and Cows
FBullCowCount Score = GetBullCows(Guess);
PrintLine(TEXT("Guess again, you have %i lives left"), Lives);
}
bool UBullCowCartridge::IsIsogram(const FString &Word)
{
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;
}
FBullCowCount UBullCowCartridge::GetBullCows(const FString &Guess) const
{
FBullCowCount Count;
TArray<char> Hint;
for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
{
if (Guess[GuessIndex] == HiddenWord[GuessIndex])
{
Count.Bulls++;
Hint.Emplace(Guess[GuessIndex]);
continue;
}
else
{
Hint.Emplace('-');
}
for (int32 HiddenIndex = 0; HiddenIndex < HiddenWord.Len(); HiddenIndex++)
{
if (HiddenWord[HiddenIndex] == Guess[GuessIndex])
{
Count.Cows++;
break;
}
}
}
PrintLine(TEXT("You have %i Bulls and %i Cows"), Count.Bulls, Count.Cows);
if (Stage.StageNow == 1)
{
for (int IndexHint = 0; IndexHint < Hint.Num(); IndexHint++)
{
PrintLine(TEXT("=> %c"), Hint[IndexHint]);
}
}
return Count;
}
TArray<FString> UBullCowCartridge::GetValidWords(TArray<FString> WordList)
{
TArray<FString> ValidWords;
int32 MinLength = FMath::RoundToInt(Level.LevelNow * 1.5);
int32 MaxLength = Level.LevelNow * 3 + Stage.StageNow;
for (FString Word : WordList)
{
if (Word.Len() >= MinLength && Word.Len() <= MaxLength && IsIsogram(Word))
{
ValidWords.Emplace(Word);
}
}
return ValidWords;
}
BullCowCartridge.h
// 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 FBullCowCount
{
int32 Bulls = 0;
int32 Cows = 0;
};
struct FLevel
{
int32 LevelNow = 1;
int32 MaxLevel = 5;
};
struct FStage
{
int32 StageNow = 1;
int32 MaxStage = 3;
};
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 NewLevel();
void ProcessGuess(const FString &Guess);
static bool IsIsogram(const FString &Word);
FBullCowCount GetBullCows(const FString &Guess) const;
TArray<FString> GetValidWords(TArray<FString> WordList);
// Your declarations go below!
private:
FString HiddenWord;
int32 Lives;
FLevel Level;
FStage Stage;
bool bGameOver;
TArray<FString> Words;
TArray<FString> ValidWords;
};