0

I am making a program that outputs each char green, yellow, or red depending on whether it matches the word. I have tried making a function that takes In the user guess and compares it against the word. I have just given values to each to test it. When I click run nothing happens it just sits there in replit and VS Code.

first if: checks if the word is equal and if it is returns the entire word.

If the entire world is not equal then I try going through each char.

#include <iostream>
#include <algorithm>
#include <cctype>
#include <string>
#include <random>
using namespace std;

string fun2(string user_guess, string word)
{
    int num = 1; //num for loop
    int num1 = 0; // for yellow to stay const
    int num2 = 0; // postion of char
    bool a1 = false;

    if (user_guess == word) {
        cout << "\033[30;42m" << user_guess << "\033[0m\n"; //returns entire word in green
    }
    else {
        while (num <= word.length()) { //Goes through each char in the word
            if (user_guess[num2] == word[num2]) {
                cout << "\033[30;42m" << user_guess[num2] << "\033[0m\n"; // return char in green
                num2++;
                num++;
                num1++;
            }
            else {
                while (num2 <= word.length()) { // checcks wether char is equal to any other char in the word
                    if (user_guess[num] == word[num2]) {
                        a1 = true;
                    }
                }
                if (a1 == true) {
                    cout << "\033[30;103m" << user_guess[num] << "\033[0m\n"; // return yellow
                }
                else {
                    cout << "\033[30;41m" << user_guess[num2] << "\033[0m\n"; // return red
                }
                num2++;
                num++;
                num1++;
            }
        }
    }
    return "Thanks";
}

int main()
{
    string word = "cake";
    string user_guess = "fake";
    cout << fun2(user_guess, word);
}
rioV8
  • 24,506
  • 3
  • 32
  • 49
  • `while(num <= word.length())` looks like undefined behavior. The valid indices into `word` are `0` to `word.length() - 1`, _not_ including `word.length()`. C++ indexing starts at `0`. – Nathan Pierson Apr 27 '22 at 02:50
  • what is the use of `num1`, take a good look at `a1` use – rioV8 Apr 27 '22 at 04:55

1 Answers1

0

If I understand what you are doing, you are making things quite a bit harder of yourself than they need to be. You are already using std::string. To find if the current character in user_guess appears elsewhere in word, you can simply use the std::basic_string::find_first_of member function by searching word from the current index for a character that matches the current character in user_guess.

For example, you can simply do:

std::string fun2 (std::string user_guess, std::string word)
{
    if (user_guess == word) {   /* words are equal, all green */
        std::cout << "\033[30;42m" << user_guess << "\033[0m\n";
        return "Success";
    }
    
    /* loop over each char (up to shorter of either string) */
    for (int i = 0; user_guess[i] && word[i]; i++) {
        if (user_guess[i] == word[i]) {   /* chars match, green */
            std::cout << "\033[30;42m" << user_guess[i] << "\033[0m";
        }
        /* current char found elsewhere in word - yellow */
        else if (word.find_first_of (user_guess[i], i) != std::string::npos) {
            std::cout << "\033[30;103m" << user_guess[i] << "\033[0m";
        }
        else {  /* current char does not exist in word - red */
            std::cout << "\033[30;41m" << user_guess[i] << "\033[0m";
        }
    }
    
    return "\nThanks";
}

(note: there is no need for an else after user_guess and word match, you are simply done at that point. Simply return from inside that block rather than using an else and forcing an additional level of indentation for the remainder of the code in the else block)

To match the current character in user_guess to any character in word starting from the beginning of word instead of the current index, you can use word.find_first_of (user_guess[i], 0).

The line using namespace std; was removed. See Why is “using namespace std;” considered bad practice?

Hardcoding strings makes it impossible to change word or user_guess without recompiling your code. You shouldn't have to recompile your code to simply provide a different word or user_guess, that's what the parameters to main(), e.g. int argc, char **argv, are for.

Simply pass word and user_guess as the first two arguments on the command line (or prompt the user for input and read from stdin). Taking the arguments as the first two command line parameters, you could do:

#include <iostream>
#include <string>
...
int main (int argc, char **argv)
{
    if (argc < 3) {
        std::cerr << "usage:  ./prog word user_guess.\n";
        return 1;
    }
    
    std::string word { argv[1] };
    std::string user_guess { argv[2] };
    
    std::cout << fun2(user_guess, word) << '\n';
}

(note: those are the only two headers required by your code. Avoid including superfluous header files)

Example Use/Output

If I understood your goal, using:

$ ./bin/word_game_color cake fake
fake
Thanks

Where fake is red,green,green,green.

If we change it to: ./bin/word_game_color cake feke then the output of feke is red,yellow,green,green.

In case of a match, you have, e.g.

$ ./bin/word_game_color cake cake
cake
Success

Where cake is output all green.


Handling user_guess Longer Than word

You likely want to handle cases where user_guess and word are of differing length. In that case simply add an additional loop to loop over any remaining characters in user_guess while searching for the matching character anywhere in word from the beginning.

You can do that with:

std::string fun2 (std::string user_guess, std::string word)
{
    int i = 0;
    
    if (user_guess == word) {   /* words are equal, all green */
        std::cout << "\033[30;42m" << user_guess << "\033[0m\n";
        return "Success";
    }
    
    /* loop over each char (up to shorted of either string) */
    for (; user_guess[i] && word[i]; i++) {
        if (user_guess[i] == word[i]) {   /* chars match, green */
            std::cout << "\033[30;42m" << user_guess[i] << "\033[0m";
        }
        /* current char found elsewhere in word - yellow */
        else if (word.find_first_of (user_guess[i], 0) != std::string::npos) {
            std::cout << "\033[30;103m" << user_guess[i] << "\033[0m";
        }
        else {  /* current char does not exist in word - red */
            std::cout << "\033[30;41m" << user_guess[i] << "\033[0m";
        }
    }
    
    /* user_guess longer than word -- loop remaining chars */
    for (; user_guess[i]; i++) {
        /* current char found elsewhere in word - yellow */
        if (word.find_first_of (user_guess[i], 0) != std::string::npos) {
            std::cout << "\033[30;103m" << user_guess[i] << "\033[0m";
        }
        else {  /* current char does not exist in word - red */
            std::cout << "\033[30;41m" << user_guess[i] << "\033[0m";
        }
    }
    
    return "\nThanks";
}

In that case if you used "cake" for word and "cakebake" for user_guess you would have:

$ ./bin/word_game_color cake cakebake
cakebake
Thanks

Where cakebake is green,green,green,green,red,yellow,yellow,yellow.

Let me know if I misunderstood what your goal was. This made sense given what you had so far -- but greatly simplified things.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I was at school I was not able to respond quickly. This code I had actually copied and pasted into a separate .cpp file so I can fix the problems that were occurring. So I gave word and user_guess predefined values so I can test it. What I was trying to do is have a word and compare that against the userr_guess. Depending on if word[0] and user_guess[0] match return the letter in green, and if they don't match return red, if user_guess[0] matches with any other letter in a word other than the same position of char it's being compared to. – I need help with my code Apr 28 '22 at 03:39
  • I just did not know how to approach the part comparing the word[pos_char] with every other letter in the word. I have only been coding in c++ for like 2 or 3 months, do you recommend any books, sites, or resources I could use to learn and pick up new things. Thanks for the help. – I need help with my code Apr 28 '22 at 03:42
  • Yes, that makes much more sense. The code above shows exactly how to implement the coloring of characters and the `user_guess` and `word` and basically test-cases for that above. To change the code to have the `word` provided on the command line and then the `user_guess` prompted for is a small change. It's just a matter of getting the input from a different source (for you `word` you could also simply pick a random number from a dictionary file). Do you want to take a stab at modifying the code or do you need help figuring out where to start there? I don't mind helping further. – David C. Rankin Apr 28 '22 at 03:43
  • As for a book, see [The Definitive C++ Book Guide and List](https://stackoverflow.com/q/388242/3422102). There is no replacement for coding, trial/error, using the book and [cppreference.com](https://en.cppreference.com/) as your reference. Asking questions here (after your good-faith attempt to solve a problem and with your well formatted and specific questions) is invaluable. Nothing like being able to get a glimpse of how others with experience approach different problems. (asking "I wonder if I can make the code do X?" -- and then doing it, is the best learning of all) It takes time. – David C. Rankin Apr 28 '22 at 03:49
  • I will take a try first and try putting it all together today and tomorrow. If I have questions I will definitely ask. Thanks for the help – I need help with my code Apr 28 '22 at 04:01
  • Drop a comment here and I'll get it. I would ask the question "Can I create a file named dictionary.txt with `bake, cake, fake, lake, make, cat, dog, frog`, etc.. one on each line. Generate a random number between `1-8` (the number of words in dictionary.txt) and loop that many times reading/dicarding each word until you reach your random line number and read `word`. Now prompt the user for input and read `user_guess`?". Get it working for one `word` and `guess` and then put it in a loop so the user can play any number of times, simply hitting [Enter] on an empty line to quit. (good learning) – David C. Rankin Apr 28 '22 at 04:06