User selecting item in map

73 Views Asked by At

I am currently writing a command line game program where I have stored the categories and solutions in a map<string, vector<string>>. The key value is the category and the vector is a vector of solution strings.

I would like to prompt the user to select a category however I am unsure of the best way to do it as I don't want to force the user to manually type the category and therefore am only receiving an int with their selection.

Is there a way to use an int to access a map? (for example solutionMap[2] = the second value?)

Here is a snippet from my code just to clarify

cout << "\nCategories:\n-----------" << endl;
int categoryCount = 1;
for (map<string, vector<string> >::iterator it = solutionMap.begin(); it != solutionMap.end(); ++it){
    cout << categoryCount << ": " << it->first << endl;
    ++categoryCount;
}

// Prompt user for selection and save as currentCategory
int currentCategory;
bool isValid = false;

do{
    cout << "Please enter the number of the category you would like to use: ";
    cin >> currentCategory;

    // if cin worked and number is in range, continue out of the loop
    if (cin.good() && currentCategory <= solutionMap.size()){
        isValid = true;
    }
    else{
        cout << "Invalid entry!" << endl;

        // Clear the buffer
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
} while (!isValid);

What I would like to do at this point is send the number to the game class and have is select a random solution from the vector using the selected key value, however as far as I know I need the selection as a string to find it.

Any help would be appreciated!

1

There are 1 best solutions below

2
On BEST ANSWER

If you want to access your map using an integer index, you can proceed as follows:

 auto ix=solutionMap.begin();   // bidirectional iterator to the map 
 advance (ix,currentCategory);  // move the iterator
 cout << "choice is "<<ix->second<<endl;      // here you are 

But be careful: as soon as you insert/remove an element, the ordre of the elements might not correspond anymore to the menu you've displayed.

How does it work ?

Iterator to maps are bidirectional: you can only advance or go-back by 1 element at a time. advance() repeats this operation the correct number of times

Alternatives

If you don't really use the map as associative array, and mostly use menus and indexes, you should opt for another variant, using a vector instead of a map:

 vector<pair<string, vector<string>> solutionMap; 

You could then easily access the elements, using their index. If you need to occasionnally find a specific element by using the key string, you could still use find_if().