Here is my code! It would be 100% more readable if I had less comments.
Most of my comments are my own weird pseudocode/talking to the rubber duck. I added a few extra functions that aren’t in course because I’m just like it that way. I’m using a Boolean function!! Once again, ahead of the curve, so some course spoilers in the code below.
// 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"
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 WelcomePlayer();
void ProcessGuess(FString Guess);
void PlayerWinOrLoose(FString Guess);
void BullCowsNumber(FString Guess);
void PlayerDidNotWin();
bool IsIsogram(FString Guess);
// Your declarations go below!
private:
FString HiddenWord;
int32 Lives;
bool bGameOver;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"
void UBullCowCartridge::BeginPlay() // When the game starts
{
Super::BeginPlay();
SetUpGame();
// PrintLine(TEXT("The HiddenWord is %s"), *HiddenWord); //Debug Line
// PrintLine(TEXT("It is %i characters Long"), HiddenWord.Len()); //Debug Line
WelcomePlayer();
}
void UBullCowCartridge::OnInput(const FString& Input) // When the player hits enter
{
ClearScreen();
// If Game is over, ClearScreen() and SetupGame()
if (bGameOver) {
EndGame();
return; // Using a return here to exit early to prevent Normal Game Loop
}
// Normal Game Loop
// Check if Valid
ProcessGuess(Input);
}
void UBullCowCartridge::SetUpGame()
{
HiddenWord = TEXT("Prodigen");
Lives = HiddenWord.Len();
bGameOver = false;
}
void UBullCowCartridge::WelcomePlayer()
{
// Separating these may make it easier to simplify dialogue later
PrintLine(TEXT("Welcome to Bull Cows!"));
PrintLine(TEXT("Guess the %i letter word!"), HiddenWord.Len());
PrintLine(TEXT("You have %i lives."), Lives);
PrintLine(TEXT("Please enter your guess and \nPress enter to continue..."));
}
void UBullCowCartridge::ProcessGuess(FString Guess)
{
if (HiddenWord.Len() != Guess.Len()) // Check Character Length
{
// Prompt to GuessAgain
PrintLine(TEXT("The Hidden Word is %i characters long."), HiddenWord.Len());
PrintLine(TEXT("You have %i lives remaining, try again!"), Lives);
return;
}
if (IsIsogram(Guess)) // Check if it is an Isogram
{
PrintLine(TEXT("No repeating Letters!"));
PrintLine(TEXT("You have %i lives remaining, try again!"), Lives);
return;
}
// Answer is Valid, so now T or C
PlayerWinOrLoose(Guess);
}
void UBullCowCartridge::PlayerWinOrLoose(FString Guess)
{
if (Guess == HiddenWord)
{
PrintLine(TEXT("The Answer is %s"), *HiddenWord);
EndGame();
return;
}
//Didn't win? Now the bad stuff happens!
BullCowsNumber(Guess);
PlayerDidNotWin();
}
// This is taking care of itself, because there is only one way to win.
// Bull Cows Will be calculated separately
void UBullCowCartridge::PlayerDidNotWin()
{
--Lives; // Keep it here because otherwise I'll be writting it twice.
// Ask you dead or dying?
if (Lives <= 0)
{
// If no lives, inform player they have perished.
EndGame();
return;
}
if (Lives == 1)
{
// Warn them about how close they are to dying
PrintLine(TEXT("YOU HAVE ONE FINAL LIFE!"));
PrintLine(TEXT("YOU WILL PERISH IF YOU FAIL AGAIN"));
return;
}
// If your not dead, your alive!
// Prompt user for another guess
PrintLine(TEXT("YOU MUST TRY AGAIN OR PERISH!"));
PrintLine(TEXT("You have %i lives left"), Lives);
}
void UBullCowCartridge::BullCowsNumber(FString Guess)
{
// PlaceHolder
return;
}
bool UBullCowCartridge::IsIsogram(FString Guess)
{
// PlaceHolder
return false;
}
void UBullCowCartridge::EndGame()
{
// If They've confirmed that they want to replay the game
// Then let them re-initialize the game
// This goes first so I have a way to exit early
if (bGameOver) {
// This is here because I feel like the EndGame function,
// Should handle the events that occur EndGame()
SetUpGame();
WelcomePlayer();
return; // Using a return here to exit early
}
// Game over here so that next time function is called, we set the game up again
bGameOver = true;
// Extra shame to those that have failed
// Also show user the hidden word for some closure
if (Lives == 0) {
PrintLine(TEXT("THEN PERISH"));
PrintLine(TEXT("The hidden word was %s\n"), *HiddenWord);
}
// Play Nice now
PrintLine(TEXT("Press enter to play again..."));
}