/// G. Hagopian - PPP5 Ex 13

/**
13. The program is a bit tedious because the answer is hard-coded 
into the program. Make a version where the user can play repeatedly 
(without stopping and restarting the program) and each game has a 
new set of four digits. 
*/

#include "std_lib_facilities.h"

const int nSlots{10}; ///number of different ints in secret code
const int range{20};

void createSecretCode(vector<int> &secretCode);
void getGuess(vector<int> &guess);
int scoreBulls(vector<int> secretCode, vector<int> &guess);
int scoreCows(vector<int> secretCode, vector<int> &guess);
void show(vector<int>);

vector<int> initializeGame(vector<vector<int> > &guesses,
                           int &bulls);

void scoreGuess(vector<int> guess,
                vector<int> secretCode,
                vector<vector<int> > &guesses,
                int &bulls);

bool endGame(int);


int main() {
    srand(time(0));
    vector<int> guess, secretCode;
    vector<vector<int> > guesses;
    bool newGame{false};
    int bulls{0};
    do {
        secretCode = initializeGame(guesses, bulls);
        while(bulls != nSlots) {/// while game not over
            getGuess(guess);  /// pass by reference
            scoreGuess(guess, secretCode, guesses, bulls);
        }
        newGame = endGame(guesses.size());
    } while(newGame);
}

void createSecretCode(vector<int> &secretCode) {
    int cntr{0}, rndNum{0};
    bool isNew;
    secretCode.push_back(rand()%range);
    do {
        rndNum = rand()%range;
        isNew = true;
        for(int i = 0; i < secretCode.size(); ++i)
            if(rndNum == secretCode[i])
                isNew = false;
        if(isNew) {
            secretCode.push_back(rndNum);
        }
    } while(secretCode.size()<nSlots);
}

void show(vector<int> v) {
    cout << endl;
    for(int i = 0; i < v.size(); ++i) {
        if(i>=nSlots) cout << "  ";
        cout << v[i] << " ";
    }

}

void getGuess(vector<int> &guess) {
    int n{0};
    guess.clear();
    cout << "\nEnter " << nSlots << " positive integers less than "
         << range << ": ";
    for(int i = 0; i < nSlots; ++i) {
        do {
            cin >> n;
            if(n < 0 || n > range-1)
                cout << "\nThat's not a good entry, try again: ";
        } while(n < 0 || n > range-1);
        guess.push_back(n);
    }
}


int scoreBulls(vector<int> secretCode, vector<int> &guess) {
    int bulls{0};
    for(int i = 0; i < nSlots; ++i)
        if(secretCode[i]==guess[i])
            ++bulls;
    guess.push_back(bulls);
    return bulls;
}

int scoreCows(vector<int> secretCode, vector<int> &guess) {
    int cows{0};
    for(int i = 0; i < nSlots; ++i) /// for each secret code
        for(int j = 0; j < nSlots; ++j) {
            if(guess[j]==secretCode[i] && i != j) {
                ++cows;
                break;
            }
        }
    guess.push_back(cows);
    return cows;
}

vector<int> initializeGame(vector<vector<int> > &guesses,
                           int &bulls)
{
    guesses.clear();
    int cows{0};
    vector<int> secretCode, guess;
    ///create secret code
    createSecretCode(secretCode);
    //show(secretCode);
    ///get a guess
    getGuess(guess);
    ///score the guess
    bulls = scoreBulls(secretCode,guess);
    cows = scoreCows(secretCode, guess);
    guesses.push_back(guess);
    for(int i =0; i < nSlots; ++i) cout << "  ";
    cout << "bulls cows";
    show(guess);
    return secretCode;
}

void scoreGuess(vector<int> guess,
                vector<int> secretCode,
                vector<vector<int> > &guesses,
                int &bulls) {
    int cows{0};
    bulls = scoreBulls(secretCode,guess);
    cows = scoreCows(secretCode, guess);
    /*cout << "\nThat's " << bulls
         << " bull" << ((bulls!=1) ? "s" : "")
         << " and " << cows
         << " cow" << (cows!=1 ? "s" : "") << ".";
    */
    ///show guesses
    guesses.push_back(guess);
    for(int i =0; i < nSlots; ++i) cout << "  ";
    cout << "bulls cows";
    for(int i = 0; i < guesses.size(); ++i)
        show(guesses[i]);
}

bool endGame(int N) {
    char yesno{'n'};
    cout << "\n\nCongratulations, you won after "
         << N << " guesses.";
    cout << "\nDo you want to play again? (y/n)";
    cin >> yesno;
    if(tolower(yesno) == 'n') return false;
    else return true;
}
