Help with partial match peg counter in Mastermind game C++ code

Like the title says, I am coding mastermind in C++ have already completed it, the counter pegs are gold for a pure match, and silver for a partial match. I have the gold working correctly but can't get the partial match counter to work for the life of me.

Here is the code so far:
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <iostream>
#include <vector>
#include <cstdlib>
#include "mastermind.h"

using namespace std;

void setupGame(mastermind*&, mastermind*&);
void loadGame(mastermind*&, mastermind*&);
void saveGame(mastermind*&, mastermind*&);
bool yesOrNo(string);
void playGame(mastermind*&, mastermind*&);

int main()
{
  mastermind * currentGame;
  mastermind * savedGame;
  char choice;
  bool done = false;

  currentGame = savedGame = NULL;

  while (!done)
    {
      cout << endl;

      cout << "MAIN MENU" << endl;
      cout << "(P)lay a new game" << endl;
      cout << "(L)oad an existing game" << endl;
      cout << "(C)ontinue current game" << endl;
      cout << "(Q)uit) the program " << endl;
      cout << endl;
      cout << "Choose an option: ";

      cin >> choice;

    switch (tolower(choice))
      {
      case 'p':
      case 'P':
        setupGame(currentGame, savedGame);
        playGame(currentGame, savedGame);
        break;

      case 'l':
      case 'L':
        loadGame(currentGame, savedGame);
        playGame(currentGame, savedGame);
        break;

      case 'c':
      case 'C':
        playGame(currentGame, savedGame);
        break;
      case 'q':
      case 'Q':
        done = true;
        break;

      default:
        cout << endl;
        cout << "Nope. 0/10. Do not approve of this input" << endl;
        break;
      }

    }

  //deallocate the objects if any are still left after
  //user decides to quit
  if (currentGame != NULL)
    delete currentGame;

  if (savedGame != NULL)
    delete savedGame;

  cout << endl;
  cout << "Ok well, I hope this was enjoyable" << endl;

  return 0;
}

//setupGame function creates a new game by prompting user for peg colors
//terminates with 0, if no currentGame in session, allocates new game to currentGame
//If a game is in progress, prompts user to save, if user declines, deallocates
void setupGame(mastermind*& currentGame, mastermind*& savedGame)
{
  string userChoiceColor;
  vector <string> userChoices;
  cout << endl;
  cout << "Enter the peg colors followed by 0: " << endl;

  while (cin >> userChoiceColor)
    {
      for (char & elementToUpper: userChoiceColor)
        {
          (void)tolower(elementToUpper);
        }
      userChoices.push_back(userChoiceColor);

      if(userChoices.at(0) == "0")
        {
          cout << "Sorry! You need at least 1 peg to play the game" << endl;
          userChoices.clear();
          continue;
        }

      else if (userChoiceColor == "0")
        {
          userChoices.pop_back();
          break;
        }
    }

  while (cin >> userChoiceColor)
    {
      for (char & elementToUpper: userChoiceColor)
        {
          (void)tolower(elementToUpper);
        }
      userChoices.push_back(userChoiceColor);

      if(userChoices.at(0) == "0")
        {
          cout << "Sorry! You need at least 1 peg to play the game" << endl;
          userChoices.clear();
          continue;
        }

      else if (userChoiceColor == "0")
        {
          userChoices.pop_back();
          break;
        }
    }

  while(userChoices.size() > 4)
    {
      userChoices.pop_back();
    }
  if (currentGame == NULL)
    {
      currentGame = new mastermind(userChoices);
      return;
    }

  else if (currentGame != NULL)
    {
      cout << endl;
      cout << "You already have a game in progress." << endl;
      cout << "Would you like to save the game?" << endl;
      cout << endl;
      if (yesOrNo("(Y/N): ") == true)
        {
          cout << "Saving current game..." << endl;
          saveGame(currentGame, savedGame);
          if (currentGame == NULL)
            {
              currentGame = new mastermind(userChoices);
              return;
            }
          else
            {
              return;
            }
        }
      else //if (yesOrNo("(Y/N): ") == false)
        {
          delete currentGame;
          currentGame = new mastermind(userChoices);
          return;
        }
    }
}

void saveGame(mastermind*& currentGame, mastermind*& savedGame)
{
  //string userChoice;
  if (savedGame == NULL)
    {
      //cout << "Ok saving game" << endl;
      savedGame = currentGame;
      currentGame = NULL;
      return;
    }

  else
    {
      //cout << "Saving current game..." << endl;
      cout << endl;
      cout << "There is a saved game" << endl;
      cout << "This action will destroy/overwrite the previously saved game. Is this ok?" << endl;
      //cout << "(Y/N): ";
      //cin >> userChoice;
      if (yesOrNo("(Y/N): ") == true)
        {
          delete savedGame;
          //savedGame = NULL;
          savedGame = currentGame;
          currentGame = NULL;
          return;
        }
      else
        {
          return;
        }
    }
}

void loadGame(mastermind*& currentGame, mastermind*& savedGame)
{
  //string userChoice;
  if (savedGame == NULL)
    {
      cout << endl;
      cout << "There is no game to load. Unable to complete the task." << endl << endl;
      return;
    }
  if (currentGame != NULL)
    {
      cout << endl;
      cout << "This action will destroy current game." << endl;
      cout << "This action cannot be undone." << endl;
      cout << "Do you wish to continue?" << endl << endl;
      //cout << "(Y/N): ";
      //cin >> userChoice;
      if (yesOrNo("(Y/N): ") == false)
        {
          return;
        }
      else
        {
          cout << "Ok loading game" << endl;
          delete currentGame;
          currentGame = savedGame;
          savedGame = NULL;
          return;
        }
    }  
else
    {
      currentGame = savedGame;
      savedGame = NULL;
      return;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
bool yesOrNo(string msg)
{
        char choice;

        cout << endl;

        do
        {
                cout << msg;
                cin >> choice;
                choice = tolower(choice);
        }
        while (choice != 'y' && choice != 'n');

        return choice == 'y';
}

void playGame(mastermind*& currentGame, mastermind*& savedGame)
{
  /*if (currentGame == NULL)
    {
      cout << endl;
      cout << "No current game found" << endl;
      return;
      }*/

  vector <string> userChoices;
  string userChoiceColor;
  int gameResult;
  int gold;
  int silver;

  if (currentGame == NULL)
    {
      cout << endl;
      cout << "No current game found" << endl;
      return;
    }
  //game in session
  while (currentGame -> getMoveIndex() <= 5)
    {
      userChoices.clear();
      cout << endl;
      //1+
      cout << "Turn " << currentGame -> getMoveIndex() << ": Enter ";
      cout << currentGame -> getNumberOfColumns() << " colors or (P)ause:" << endl;

      for ( int i = 0; i < currentGame -> getNumberOfColumns(); i++)
        {
          cin >> userChoiceColor;
          for (char & elementToUpper: userChoiceColor)
            {
              (void)tolower(elementToUpper);
            }
          userChoices.push_back(userChoiceColor);

          if (userChoiceColor == "p" || userChoiceColor == "P")
            {
              cout << "Ok, we all need a break sometimes" << endl;
              cout << "Would you like to save the game?";
              if (yesOrNo("(Y/N): ") == true)
                {
                  cout << "Ok saving game" << endl;
                  saveGame(currentGame, savedGame);
                  return;
                }
              else
                {
                  cout << "Ok that's fine, you can always resume" << endl;
                  return;
                }
            }
          if(userChoices.size() >= currentGame -> getNumberOfColumns() )
            {
              break;
            }
          //userChoices.push_back(userChoiceColor);
        }
      gold = 0;
      silver = 0;
      gameResult = currentGame -> move(userChoices, gold, silver);
      cout << "Gold pegs: " << gold << endl;
      cout << "Silver pegs: " << silver << endl;

      if (gameResult == 0)
        {
          continue;
        }

      else if (gameResult == 1)
        {
          cout << endl;
          cout << "You won!  :)" << endl;
          cout << "Destroying game" << endl << endl;
          delete currentGame;
          currentGame = NULL;
          return;
        }
      else if (gameResult == -1)
        {
          cout << endl;
          cout << "You lost :( " << endl;
          cout << "Destroying game" << endl << endl;
          delete currentGame;
          currentGame = NULL;
          return;
        }
    }
}
mastermind.h file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <vector>
using namespace std;

class mastermind
{
public:
        mastermind(int);
        mastermind(vector<string>);
        int move(vector<string>, int&, int&);
        int getMoveIndex() const;
        int getNumberOfColumns() const;
private:
        int maxMoves;
        vector<string> solution;
        int moves;
};


mastermind.cpp file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "mastermind.h"
#include <vector>
#include <string>

using namespace std;

mastermind::mastermind(int size)
{
  solution.resize(size);
  //i < solution.size();
  for(int i = 0; i < size; i++)
    {
      solution[i] = "red";
      //solution.push_back("red");
    }
  maxMoves = 5;
  moves = 0;
}

mastermind::mastermind(vector<string> initial)
{
  for(string word: initial)
    {
      for(char letter: word)
        {
          tolower(letter);
        }
      solution.push_back(word);
      }
  maxMoves = 5;
  moves = 0;
}

int mastermind::move(vector<string> playerMove, int& gold, int& silver)
{
  int size = playerMove.size();
  //gold = 0;
  //silver = 0;
  //vector<bool> pureMatch(getNumberOfColumns());
  //vector<bool> partialMatch(getNumberOfColumns());

  if (size != getNumberOfColumns())
    {
      return 2;
    }

  for(int i = 0; i < getNumberOfColumns(); i++)
    {
      if (playerMove[i] == solution[i])
        {
          gold++;
        }
    }
  for(int i = 0; i < getNumberOfColumns(); i++)
    {
      for (int k = 0; k < size; k++)
        {
          if (playerMove[i].compare(solution[k]) && !playerMove[i].compare(solution[i]))
            {
              silver++;
            }
        }
    }
  /*
  //check for pure matches ie gold pegs
  for(int i = 0; i < getNumberOfColumns(); i++)
    {
      if(playerMove[i] == solution[i])
        {
          gold++;
          pureMatch[i] = true;
        }
      else
        {
          pureMatch[i] = false;
        }
    }
  //check for partial matches ie silver pegs
  for(int i = 0; i < getNumberOfColumns(); i++)
    {
      if (pureMatch[i] == true)
        {
          continue;
        }
      for(int j = 0; j < size; j++)
        {
          if (pureMatch[j] == true)
            {
              continue;
            }
          else if(partialMatch[j] == true)
            {
              continue;
            }
          if((playerMove[i].compare(solution[j])) && (!playerMove[i].compare(solution[i])))
            //if(playerMove[i] == solution[j])
            {
              silver++;
              partialMatch[j] = true;
            }
          else
            {
              partialMatch[j] = false;
            }
        }
    }
  */
  if(gold == solution.size())
    //if (gold == getNumberOfColumns())
    {
      return 1;
    }
  else if (getMoveIndex() > maxMoves)
    {
      return -1;
    }
  else if (playerMove.size() != solution.size())
    {
      return 2;
    }
  else
    {
      moves++;
      return 0;
    }
}

int mastermind::getMoveIndex() const
{
  //moves = moves + 1;
  return moves + 1;
}

int mastermind::getNumberOfColumns() const
{
  return solution.size();
}


The issue I'm getting are the silver counter not working right, it will count right the first turn, but the second turn will be off. Also the game lets turns go to 6 when they should not go beyond 5 turns, or it should print the losing game message. No matter what the game will not print the losing game message when a value of -1 is returned. The 1 value returned for a winning game works, but only rarely. Please help me figure this out.
http://sscce.org/
Your main should be something like this.

1
2
3
4
5
6
7
int main ( ) {
   mastermind game({"r","g","r","b"});
   int gold, silver;
   int gameResult = game.move({"g","b","r","r"}, gold, silver);
   cout << "Gold pegs: " << gold << endl;
   cout << "Silver pegs: " << silver << endl;
}

Along with the minimum class implementation to show the problem you're looking at.

Having gone through this exercise, you might just discover the problem anyway because it forces you to really look at just one issue.

What this gives you is
- No cumbersome UI to fiddle with every time you want to test an idea.
- No irrelevant functionality like load and save.
- No guessing what we're supposed to type in.
- No code spread across multiple files and multiple posts in a thread.

It's just a simple single file, single post, code that can be dropped directly into a file, compiled and tested without any additional effort.

The more you make people work to get into a position to help you, the less likely it is to happen.

FWIW, I think you're double-counting.
If you guess "rbbb" against "grbr", you only count the "r" once, not twice.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
using namespace std;

template<typename T>
auto calc_result(vector<T> code, vector<T> guess) {
    const T CrossedOut {};
    int exact = 0, near = 0;
    // count exact matches
    for (size_t i = 0; i < code.size(); ++i)
        if (code[i] == guess[i]) {
            ++exact;
            code[i] = guess[i] = CrossedOut;
        }
    // count near matches
    for (auto& gx: guess) {
        if (gx == CrossedOut) continue;
        for (auto& cx: code)
            if (cx == gx) {
                ++near;
                cx = gx = CrossedOut;
                break;
            }
    }
    return make_pair(exact, near);
}

int main() {
    vector<vector<vector<int>>> v { // positive values for colors
        //  code            guess           result
        { { 1, 2, 2, 2 }, { 3, 1, 2, 1 }, { 1, 1 } },
        { { 5, 3, 4, 3 }, { 3, 5, 4, 2 }, { 1, 2 } },
        { { 2, 3, 4, 5 }, { 2, 5, 4, 5 }, { 3, 0 } },
        { { 2, 3, 4, 5 }, { 5, 4, 3, 2 }, { 0, 4 } },
        { { 2, 2, 3, 3 }, { 3, 3, 2, 2 }, { 0, 4 } },
        { { 1, 1, 1, 1 }, { 2, 2, 2, 2 }, { 0, 0 } },
        { { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 4, 0 } },
        { { 2, 3, 4, 5 }, { 2, 3, 4, 5 }, { 4, 0 } },
        { { 2, 3, 4, 5 }, { 2, 5, 4, 3 }, { 2, 2 } },
    };
    for (const auto& x: v) {
        auto [exact, near] = calc_result(x[0], x[1]);
        cout << exact << ' ' << near;
        if (exact != x[2][0] || near != x[2][1])
            cout << "  wrong!";
        cout << '\n';
    }
}

Topic archived. No new replies allowed.