78.Isogram Troubles

Hello, I followed the instruction of the Isogram member variable and my compile failed. Everything worked fine beforehand. I get some weird messages in the compiler log.

  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: class TArray<class FString,class TSizedDefaultAllocator<32> > __cdecl UBullCowCartridge::GetValidWords(class TArray<class FString,class TSizedDefaultAllocator<32> > const &)const " (?GetValidWords@UBullCowCartridge@@QEBA?AV?$TArray@VFString@@V?$TSizedDefaultAllocator@$0CA@@@@@AEBV2@@Z) already defined in BullCowCartridge.cpp.obj
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: bool __cdecl UBullCowCartridge::IsIsogram(class FString const &)const " (?IsIsogram@UBullCowCartridge@@QEBA_NAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: virtual void __cdecl UBullCowCartridge::OnInput(class FString const &)" (?OnInput@UBullCowCartridge@@UEAAXAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: void __cdecl UBullCowCartridge::ProcessGuess(class FString const &)" (?ProcessGuess@UBullCowCartridge@@QEAAXAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: void __cdecl UBullCowCartridge::SetupGame(void)" (?SetupGame@UBullCowCartridge@@QEAAXXZ) already defined in BullCowCartridge.cpp.obj
     Creating library C:\UnrealProjects\BullCowGame\BullCowGame-starter-kit\Intermediate\Build\Win64\UE4Editor\Development\BullCowGame\UE4Editor-BullCowGame-0294.suppressed.lib and object C:\UnrealProjects\BullCowGame\BullCowGame-starter-kit\Intermediate\Build\Win64\UE4Editor\Development\BullCowGame\UE4Editor-BullCowGame-0294.suppressed.exp
  C:\UnrealProjects\BullCowGame\BullCowGame-starter-kit\Binaries\Win64\UE4Editor-BullCowGame-0294.dll : fatal error LNK1169: one or more multiply defined symbols found
Invalidating makefile for BullCowGameEditor (BullCowCartridge.cpp modified)
Building BullCowGameEditor...
Using Visual Studio 2019 14.28.29336 toolchain (C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333) and Windows 10.0.18362.0 SDK (C:\Program Files (x86)\Windows Kits\10).
[Upgrade]
[Upgrade] Using backward-compatible build settings. The latest version of UE4 sets the following values by default, which may require code changes:
[Upgrade]     bLegacyPublicIncludePaths = false                 => Omits subfolders from public include paths to reduce compiler command line length. (Previously: true).
[Upgrade]     ShadowVariableWarningLevel = WarningLevel.Error   => Treats shadowed variable warnings as errors. (Previously: WarningLevel.Warning).
[Upgrade]     PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs   => Set in build.cs files to enables IWYU-style PCH model. See https://docs.unrealengine.com/en-US/Programming/BuildTools/UnrealBuildTool/IWYU/index.html. (Previously: PCHUsageMode.UseSharedPCHs).
[Upgrade] Suppress this message by setting 'DefaultBuildSettings = BuildSettingsVersion.V2;' in BullCowGameEditor.Target.cs, and explicitly overriding settings that differ from the new defaults.
[Upgrade]
Building 4 actions with 4 processes...
  [1/4] BullCowCartridge.cpp
  [2/4] UE4Editor-BullCowGame-0294.lib
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: virtual void __cdecl UBullCowCartridge::BeginPlay(void)" (?BeginPlay@UBullCowCartridge@@UEAAXXZ) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: void __cdecl UBullCowCartridge::EndGame(void)" (?EndGame@UBullCowCartridge@@QEAAXXZ) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: class TArray<class FString,class TSizedDefaultAllocator<32> > __cdecl UBullCowCartridge::GetValidWords(class TArray<class FString,class TSizedDefaultAllocator<32> > const &)const " (?GetValidWords@UBullCowCartridge@@QEBA?AV?$TArray@VFString@@V?$TSizedDefaultAllocator@$0CA@@@@@AEBV2@@Z) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: bool __cdecl UBullCowCartridge::IsIsogram(class FString const &)const " (?IsIsogram@UBullCowCartridge@@QEBA_NAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: virtual void __cdecl UBullCowCartridge::OnInput(class FString const &)" (?OnInput@UBullCowCartridge@@UEAAXAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: void __cdecl UBullCowCartridge::ProcessGuess(class FString const &)" (?ProcessGuess@UBullCowCartridge@@QEAAXAEBVFString@@@Z) already defined in BullCowCartridge.cpp.obj; second definition ignored
  BullCowCartridgeLatin.cpp.obj : warning LNK4006: "public: void __cdecl UBullCowCartridge::SetupGame(void)" (?SetupGame@UBullCowCartridge@@QEAAXXZ) already defined in BullCowCartridge.cpp.obj; second definition ignored
     Creating library C:\UnrealProjects\BullCowGame\BullCowGame-starter-kit\Intermediate\Build\Win64\UE4Editor\Development\BullCowGame\UE4Editor-BullCowGame-0294.lib and object C:\UnrealProjects\BullCowGame\BullCowGame-starter-kit\Intermediate\Build\Win64\UE4Editor\Development\BullCowGame\UE4Editor-BullCowGame-0294.exp
  [3/4] UE4Editor-BullCowGame-0294.dll
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: virtual void __cdecl UBullCowCartridge::BeginPlay(void)" (?BeginPlay@UBullCowCartridge@@UEAAXXZ) already defined in BullCowCartridge.cpp.obj
  BullCowCartridgeLatin.cpp.obj : error LNK2005: "public: void __cdecl UBullCowCartridge::EndGame(void)" (?EndGame@UBullCowCartridge@@QEAAXXZ) already defined in BullCowCartridge.cpp.obj

and here is my code:

// Fill out your copyright notice in the Description page of Project Settings.
#include "BullCowCartridge.h"
// #include "LatinWordList.h"
#include "HiddenWordList.h"
//#include "Math/UnrealMathUtility.h"


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

    Isograms = GetValidWords(Words);// Declare it once in Begin Play, and will not need to keep 
                                    // using GetValidWords(Words) everytime we want to call it

    SetupGame();// makes sense to set up game first: Lives and Word ready to go

    PrintLine(TEXT("The number of possible words are %i"), Words.Num()); 
    PrintLine(TEXT("The Number of valid words are: %i."), GetValidWords(Words).Num());
    PrintLine(TEXT(" ValidWords -1 is: %i"), GetValidWords(Words).Num()-1);
}


void UBullCowCartridge::OnInput(const FString& PlayerInput) // When the player hits enter
{  
    if (bGameOver == true)// do not need to add "==true", but it helps with self-documenting
    {
        ClearScreen();
        SetupGame();
        return;   
        // Quit Game?
    } 
    else // Check Player guess
    {
        ProcessGuess(PlayerInput);// passes the players input to ProcessGuess Function
        return;
    }
}  


void UBullCowCartridge::SetupGame()
{

    // Welcomeing The Player
    PrintLine(TEXT("Salve! Welcome to TaurusBos!"));

    HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num()-1)];
    Lives = HiddenWord.Len();
    bGameOver = false;
    
    PrintLine(TEXT("The Hidden word is: %s."), *HiddenWord);// debug line
        // *= dereference
    PrintLine(TEXT("Guess the %i letter word!"), HiddenWord.Len()); 
    PrintLine(TEXT("you have %i lives."), Lives);
    PrintLine(TEXT("Type in your guess and \npress enter to moove on..."));
    PrintLine(TEXT("The Hidden word is: %s."), *HiddenWord);// debug line
}


void UBullCowCartridge::EndGame()
{
    bGameOver = true; 
        PrintLine(TEXT("\nPress Enter to play again..."));
}


void UBullCowCartridge::ProcessGuess(const FString& Guess) 
{
    if (Guess == HiddenWord)
        {
            ClearScreen();
            PrintLine(TEXT("You Win!"));
            EndGame(); 
            return;
           
        }
   
 
    if (Guess.Len() != HiddenWord.Len())//Right Length?
    {
        PrintLine(TEXT("The hidden word is %i letters long."), HiddenWord.Len());
        PrintLine(TEXT("Sorry! Guess again, you have %i \nlives left."), Lives);
        
        return; 
        
    }
     // Isogram?
    if (!IsIsogram(Guess))
    {
       PrintLine(TEXT("You have repeating letters, guess again!"));
       return;
    }
    

    PrintLine(TEXT("Lost a Life!"));
    --Lives;

    if (Lives <= 0)     
    
    {
        ClearScreen();
        PrintLine(TEXT("You have no lives left!"));
        PrintLine(TEXT("The hidden world was: %s."), *HiddenWord);
        EndGame();
        return;
    }
    // Show the player BUlls and Cows
    PrintLine(TEXT("Guess again, you have %i lives left."), Lives);
     
    // Check User PlayerInput
    // Play Again or Quit?     
}

bool UBullCowCartridge::IsIsogram(const FString& Word) const
{

// Instructors Code
    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;
   
}

TArray<FString> UBullCowCartridge::GetValidWords(const TArray<FString>& WordList) const
{
     TArray<FString> ValidWords; //Making the empty storage unit: the variable. 


    for (const FString& Word : WordList )
    {  
        if (Word.Len() >= 3 && Word.Len() <= 8 && IsIsogram(Word) )//Checks specific word 
        {
            ValidWords.Emplace(Word);            
        }
    }
    return ValidWords;
}

and my HeaderFile

// 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 ProcessGuess(const FString& Guess); // can ignore the variable names, but useful documentation.
	bool IsIsogram(const FString& Word) const;
	TArray<FString> GetValidWords(const TArray<FString>& WordList) const;  

	// Your declarations go below!
	private:
	FString HiddenWord;
	int32 Lives; 
	bool bGameOver;
	TArray<FString> Isograms;
};

What seems to be the issue here?

I looked around and the only thing I know for sure is that it thinks I am double declaring something. There are multiple answers out there on how to fix it, but I am not sure how to implement them.

All of the fixes I found were for int, but not TArray. When I tried them, they did not work.

I also changed the SetupGame HiddenWord “Isograms” back to “GetValidWords(Words)”. This failed. There is something happening when I declare the TArray in the Headerfile. It will accept any other code and cross it over fine, just not this.

edit:
I removed the “GetValidWords(Words)” from the BeginGame “Isograms” and still got the same problem. So I have isolated it to the TArray.

You appear to have two files that are a duplicate

BullCowCartridgeLatin.cpp and
BullCowCartridge.cpp

Gratias tibi agere!

Thank you very much. It did the job. I now recall what happened. I have been keeping backups for each lesson so that I may have a copy to refer to. So I decided to do something similar, but for the latin wordlist and code. However, I accidentally saved it in my “current project” file rather than my “backup code” file. Apparently it makes a difference :slight_smile:

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

Privacy & Terms