-2

I am new to C++ and am having trouble with an assignment. I cannot figure out the issue I am having with the double white pegs being counted. Can someone please help? I can understand that I have the issue of double counting because I am only using "or" statements, but other than that I believe I need to subtract the black pegs from the white pegs but I do not know how to do that.

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {

    char colors[4];

    srand(time(0));
    int randomint = (rand() % 5) + 1;

    for (int i = 0;i<4;i++) {
        randomint = (rand() % 5) + 1;

        switch (randomint) {
        case 1:
            colors[i] = 'R';
            break;
        case 2:
            colors[i] = 'B';
            break;
        case 3:
            colors[i] = 'Y';
            break;
        case 4:
            colors[i] = 'P';
            break;
        case 5:
            colors[i] = 'G';
            break;
        case 6:
            colors[i] = 'Bl';
            break;
        case 7:
            colors[i] = 'R';
            break;
        case 8:
            colors[i] = 'O';
            break;
        case 9:
            colors[i] = 'T';
            break;
        }
    }


    char usercolors[4];

    cout << "We have our colors!" << endl;
    cout << endl << endl;
    int turncounter = 0;
    while (turncounter != 12) {
        turncounter++;

        cout << "Current try: " << turncounter << endl;

        for (int i = 0;i<4;i++) {
            cout << "Color " << i << ": ";
            cin >> usercolors[i];
            cout << endl;
        }

        for (int i = 0;i<4;i++) {
            if (usercolors[i] == colors[i])
                cout << "Black Peg" << " ";
        }

        if (usercolors[0] == colors[1] ||
            usercolors[0] == colors[2] ||
            usercolors[0] == colors[3]) {
            cout << "White Peg" << " ";
        }
        if (usercolors[1] == colors[0] ||
            usercolors[1] == colors[2] ||
            usercolors[1] == colors[3]) {
            cout << "White Peg" << " ";
        }
        if (usercolors[2] == colors[0] ||
            usercolors[2] == colors[1] ||
            usercolors[2] == colors[3]) {
            cout << "White Peg" << " ";
        }
        if (usercolors[3] == colors[0] ||
            usercolors[3] == colors[1] ||
            usercolors[3] == colors[2])
        {
            cout << "White Peg" << " ";
        }

        cout << endl << endl;

        if (usercolors[0] == colors[0] &&
            usercolors[1] == colors[1] &&
            usercolors[2] == colors[2] &&
            usercolors[3] == colors[3])
        {
            cout << "You win! Number of tries: " << turncounter << endl;
            turncounter = 12;
        }
        else {
            cout << "Try Again!" << endl << endl;
        }

    }
    if (turncounter == 12) {
        cout << "Sorry, you are incorrect!" << endl;
        cout << "Answer: ";
        cout << "Color 1: " << colors[0] << "\t" << "Color 2: " << colors[1] << "\t" << "Color 3: " << colors[2] << "\t" << "Color 4: " << colors[3] << "\t" << endl;
    }

    cin.get();
    cin.get();
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • `(rand() % 5) + 1` will never produce 6, 7, 8 or 9. – rustyx Sep 15 '17 at 19:01
  • this should not work colors[i] = 'Bl'; colors are char you put two characters in the single quotes. use uppercase B and lower case b instead? for Black and blue. Or use an enumerated type. – Rob Sep 15 '17 at 19:01
  • 3
    Step through with a debugger and watch what happens first. – John Sep 15 '17 at 19:02
  • 2
    Comment out `srand` during debugging to get reproducible results. – rustyx Sep 15 '17 at 19:04
  • `I cannot figure out the issue I am having` Neither can anyone else, because you didn't think to tell us what it is. – underscore_d Sep 19 '17 at 12:19

1 Answers1

0

When you count the white pegs, you have to ignore all positions where black pegs were detected. So after detecting black pegs, you're trying to detect white pegs by doing:

if (usercolors[0] == colors[1] ||
    usercolors[0] == colors[2] ||
    usercolors[0] == colors[3]) {
    cout << "White Peg" << " ";
}

As you already noticed, this approach will lead to double counts. One example: The secret pattern contains a green peg on the first position. Now you enter your guess: Green on the first position and green on the fourth. Your code will detect a black peg on the first position and (at least) two additional white pegs, which is not the way it's supposed to work. Black peg positions have to be ignored while counting the white pegs, and all already detected white pegs.

So you have to modify your code. The double white peg count can be avoided by writing the detected black peg positions to a map (called match_map), and by leaving the inner loop after the first white peg match (which also has to be written to your list). Please be aware that you had a 'R' twice in your colour list. Giving 'Bt' as a char cannot work, I replaced it with a 'b'. You can do without the switch() by using an array of colors, then a single loop is sufficient to process the secret pattern.

Avoid using namespaces std; - look here for an explanation - , as it's considered bad pratice and can lead to further problems.

#include <iostream>
#include <cstdlib>
#include <ctime>

enum {
    PEG_NO_MATCH,
    PEG_BLACK,
    PEG_WHITE,
};

int main() {
    char colors[4], usercolors[4], match_map[4];
    const char rand_colors[8] = { 'R', 'B', 'Y', 'P', 'G', 'b', 'O', 'T' };    // B -> Black, b -> Blue
    int turncounter = 0, black_cnt, white_cnt;

    std::srand(time(0));

    for (int i = 0; i < 4; i++) colors[i] = rand_colors[std::rand() % 8];

    std::cout << "We have our colors!" << std::endl << std::endl << std::endl;

    while (turncounter != 12) {
        turncounter++;

        std::cout << "Current try: " << turncounter << std::endl;

        black_cnt = 0;
        white_cnt = 0;

        // Get input and count black pegs
        for (int i = 0; i < 4; i++) {
            std::cout << "Color " << i << ": ";
            std::cin >> usercolors[i];
            std::cout << std::endl;

            if (usercolors[i] == colors[i]){
                black_cnt++;
                match_map[i] = PEG_BLACK;
            }else{
                match_map[i] = PEG_NO_MATCH;
            }
        }

        // Count white pegs
        for (int i = 0; i < 4; i++) {
            if (match_map[i] != PEG_BLACK){
                for (int k = 0; k < 4; k++) {
                    if ((i != k) && (match_map[k] == PEG_NO_MATCH) && (usercolors[i] == colors[k])){
                        match_map[k] = PEG_WHITE;
                        white_cnt++;
                        break;
                    }
                }
            }
        }

        std::cout << std::endl << std::endl;

        // Display result
        std::cout << "Black Pegs : " << black_cnt << std::endl;
        std::cout << "White Pegs : " << white_cnt << std::endl;

        // Do all pegs match?
        if (black_cnt == 4)
        {
            std::cout << "You win! Number of tries: " << turncounter << std::endl;
            break;
        }
        else {
            std::cout << "Try Again!" << std::endl << std::endl;
        }
    }

    if (turncounter == 12) {
        std::cout << "Sorry, you are incorrect!" << std::endl;
        std::cout << "Answer: " << "Color 1: " << colors[0] << "\t" << "Color 2: " << colors[1] << "\t" << "Color 3: " << colors[2] << "\t" << "Color 4: " << colors[3] << "\t" << std::endl;
    }

    // Wait for input
    std::cin.get();
    std::cin.get();

    return 0;
}
CheviN
  • 59
  • 6
  • Welcome to Stack Overflow! This question is looking for an *explanation*, not simply for working code. Your answer provides very little insight for the questioner, and may be deleted. Please [edit] to explain what causes the observed symptoms, and how your code is reached from the original. You might also want to mention why we avoid `using namespace std;` too. – Toby Speight Sep 19 '17 at 08:13
  • @Toby: I will add further explanations. – CheviN Sep 19 '17 at 08:28
  • @sp2danny: Could you please give an example where it matches multiple times? – CheviN Sep 19 '17 at 08:44
  • @sp2danny: You're right, thank you for pointing that out. The modified code should handle it. The explanation on the English wikipedia page is much better than its German version. – CheviN Sep 19 '17 at 09:24
  • 1
    [my solution, slightly different](http://coliru.stacked-crooked.com/a/b03224f19d3e80ed) works without `user_match_map` – sp2danny Sep 19 '17 at 11:58