4

I am in the process of doing "Udemy - Learn to Code in C++ by Developing Your First Game", an unreal engine C++ basic course and in this course you develop a small game where the user tries to guess a word.

The code works great. But i was wanting to add to it. I created the code below and it works great. But it is UGGGGLLLY. And since i am still in the early learning phase I was wanting to start developing the right habits.

So the question is how to make all these If statements go away or condense. If i want to add 50 more words I dont want to have to create 50 more if statements.

I tried to change the ISecret to a FString and use that number to get the number from HIDDEN_WORD[1] but it didn't work as planned.

Here is what I am thinking:

ISecret[1-100] = MyHiddenWord[1-100] = HIDDEN_WORD[1-100]

I know this will not work and I know I have to list out the "words" in the bank, but can i create a word bank and just list all the words in the bank?

    int32 ISecret;             //This section generates a 
    srand(time(NULL));        // random number between 1 and 10.
    ISecret = rand() % 10, 1;///

    const FString HIDDEN_WORD01 = "planet";
    const FString HIDDEN_WORD02 = "bait";
    const FString HIDDEN_WORD03 = "dog";
    const FString HIDDEN_WORD04 = "cat";
    const FString HIDDEN_WORD05 = "stream";///  These are the Hidden words
    const FString HIDDEN_WORD06 = "taco";
    const FString HIDDEN_WORD07 = "ship";
    const FString HIDDEN_WORD08 = "balcony";
    const FString HIDDEN_WORD09 = "tail";
    const FString HIDDEN_WORD10 = "barf";

         if (ISecret == 1){MyHiddenWord = HIDDEN_WORD01;}
    else if (ISecret == 2){MyHiddenWord = HIDDEN_WORD02;}
    else if (ISecret == 3){MyHiddenWord = HIDDEN_WORD03;}// These make is so
    else if (ISecret == 4){MyHiddenWord = HIDDEN_WORD04;}//what ever number 
    else if (ISecret == 5){MyHiddenWord = HIDDEN_WORD05;}//is randomly 
    else if (ISecret == 6){MyHiddenWord = HIDDEN_WORD06;}//generated that  
    else if (ISecret == 7){MyHiddenWord = HIDDEN_WORD07;}//the correct
    else if (ISecret == 8){MyHiddenWord = HIDDEN_WORD08;}//HIDDEN_WORD
    else if (ISecret == 9){MyHiddenWord = HIDDEN_WORD09;}//is chosen.  
    else if (ISecret == 10){MyHiddenWord = HIDDEN_WORD10;}
melpomene
  • 84,125
  • 8
  • 85
  • 148
Melsy
  • 87
  • 1
  • 9
  • 1
    ***ISecret = rand() % 10, 1;*** What did you mean to do here with the comma? – drescherjm Jan 22 '17 at 02:16
  • 3
    Why don't you simply use an array of `FString`? Then it's simply `MyHiddenWord = HidenWordArray[ISecret - 1];` – PaulMcKenzie Jan 22 '17 at 02:17
  • There are also other things you should consider. Every time a new word is added, you have to change your code -- that is inconvenient, since you need to rebuild your app. Instead, consider reading the words from an external file into a `std::vector` or similar container, then there would be no code changes if the number of words is increased (or decreased). – PaulMcKenzie Jan 22 '17 at 02:21
  • The fundamental rule of programming is "zero, one, many": All quantities have to be precisely one of these three. Never two, five or 91. If you don't have zero or one of a thing, you have many and you need a container and loops. – Kerrek SB Jan 22 '17 at 02:21
  • @KerrekSB Counterexample: A color can be described by exactly 3 values (red, green, blue). – melpomene Jan 22 '17 at 02:23
  • 1
    @melpomene **A** color. Note the singular **A**. So it really isn't a counterexample. – PaulMcKenzie Jan 22 '17 at 02:24
  • @PaulMcKenzie **3** values. Note the quantity **3**. – melpomene Jan 22 '17 at 02:26
  • 1
    @melpomene A color is a single aggregate. You create a container of this single aggregate. – PaulMcKenzie Jan 22 '17 at 02:27
  • @PaulMcKenzie Do I? What definition of "container" are you using? – melpomene Jan 22 '17 at 02:28
  • 1
    And an Employee record can be described by 50 fields. A programmer would create a single struct or class, and instead of `Employee employee1, employee2, employee3, etc.` it would simply be `Employee employee[50]`, or similar construct. Don't know how else to explain my point to you. – PaulMcKenzie Jan 22 '17 at 02:34
  • @melpomene: `uint8_t channel[kNumChannels]`... – Kerrek SB Jan 22 '17 at 02:36
  • @PaulMcKenzie A struct is not a "container" in the sense Kerrek SB is using ("*... you have many and you need a container and loops*"). You can't loop over the members of a struct. – melpomene Jan 22 '17 at 02:37

3 Answers3

7

You could store them in a std::array:

#include<array>

const std::array<FString, 10> hidden_words =
{
    "planet",
    "bait",
    "dog",
    "cat",
    "stream",
    "taco",
    "ship",
    "balcony",
    "tail",
    "barf"
};

int main()
{
    int ISecret = 0;
    std::cout<<hidden_words[ISecret]<<std::endl;
}

Or a std::vector<Fstring>

In general if you plan to distinguish between each element using an integer it can be beneficial to store the elements in an array.

Alex Zywicki
  • 2,263
  • 1
  • 19
  • 34
  • According to OP's intent, `hidden_words[ISecret - 1]` would be fine. – songyuanyao Jan 22 '17 at 02:19
  • Even simpler (and probably faster), something like: `FString hidden_words[] = { "planet", "bait",... };` – Andrew Henle Jan 22 '17 at 02:19
  • @AndrewHenle In general `std::array` should be preferred over raw arrays. [std::array vs array performance](http://stackoverflow.com/a/30263398/3309790) – songyuanyao Jan 22 '17 at 02:25
  • @songyuanyao A performance claim without benchmarks is useless. – Andrew Henle Jan 22 '17 at 12:28
  • @AndrewHenle Fine, it's valid for the statement that raw array is faster too. But this is not just a performance issue about that `std::array` is preferable. – songyuanyao Jan 22 '17 at 12:38
  • @songyuanyao If the difference between coding up a raw array and a `std::array` isn't infinitesimally trivial, coding up anything beyond a "Hello world!" toy is going to be over your head. If you can't understand or code up a raw array, you have no business writing complex code of any kind. And it's awfully close-minded to think that there's only one "preferable" way to do anything. – Andrew Henle Jan 22 '17 at 12:53
  • @AndrewHenle I agree that we should know the difference between raw arrays and `std::array` before choosing; I just said "in general `std::array` is preferable", which means in the situations they both could accomplish `std::array` is preferable. Is it fine? Or you meant we should use raw arrays at first? – songyuanyao Jan 22 '17 at 13:14
  • The difference between the two is negligible if there even is one. Not to mention that any good optimizing compiler would handle any performance differences easily. And if we wanted to take things one step further... Assuming access to a C++14 compliant compiler either array could be marked as a `constexpr` variable and then they would be exactly the same. I see no reason why a C-style array would be any faster though, performing an access on either array results in the same operation...`array[idx]` which is roughly equivalent to `*(ptr + idx) //where ptr is the beginning of the array`. – Alex Zywicki Jan 22 '17 at 14:15
6

First off,

ISecret = rand() % 10, 1;

is wrong. This statement is equivalent to ISecret = rand() % 10; and the 1 has no effect (this should trigger a compiler warning).

If you want a random number in the range [1, 10] (inclusive), you should do:

ISecret = rand() % 10 + 1;

To select a word for a given number, the easiest way is probably an array:

const FString hidden_word[] = {
    "planet",
    "bait",
    "dog",
    "cat",
    "stream",
    "taco",
    "ship",
    "balcony",
    "tail",
    "barf"
};
ISecret = rand() % 10;  // a number between 0 and 9
MyHiddenWord = hidden_word[ISecret];
melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Note that `std::array` can also be used in place of a raw array. – Justin Time - Reinstate Monica Jan 22 '17 at 04:06
  • It's worth noting that C++ arrays are 0 based so generating random runmbers between `1-10` rather than `0-9` could lead to bugs in an array based solution if extra attention isn't paid to make sure to subtract one every time the array is indexed. – Alex Zywicki Jan 22 '17 at 14:22
0

Besides the answers, you can also perform polymorphism. You may have a look at these examples

dynamical binding or switch/case?

how inheritance replace the switch case?

Good luck...

Community
  • 1
  • 1
unnamed
  • 840
  • 9
  • 26
  • 38