Nouri Alnahawi
Nouri Alnahawi

Reputation: 15

Two questions regarding c++ programming

Today I had my first exam in c++ in uni - I study computer science - and I didn't get it all right, because the time was too short and I had to write some long code to do simple tasks. So it was a card game simulation with all kind of different methods.

First problem: We should compare the point values of each player's card to determine the highest, which are all stored in a player class object as a vector class data element. What I did was: get the card, store the value in an int and then compare all like this:

if(a > b && a > c && a > d){...

... and I had to do this four times. Is there a better way to do this ? If not, maybe an easier way to compare the integers ?

Second problem: If you look at this you'll probably know what the problem is

int id0 = players[0].getID();
int bd0 = players[0].getBudget();
int id1 = players[1].getID();
int bd1 = players[1].getBudget();
int id2 = players[2].getID();
int bd2 = players[2].getBudget();
int id3 = players[3].getID();
int bd3 = players[3].getBudget();

stringstream players;
players << "Player's ID" << setw(10) << "Budget" << endl;
players << "-----------" << setw(10) << "------" << endl;
players << id0 << setw(20) << bd0 << endl;
players << id1 << setw(20) << bd1 << endl;
players << id2 << setw(20) << bd2 << endl;
players << id3 << setw(20) << bd3 << endl;


return players.str();

I can't figure out why the functions above didn't work in the stringstream directly! The compiler kept telling me that sstream doesn't support the [] operator, even though it worked in other methods.

Upvotes: 1

Views: 158

Answers (1)

bames53
bames53

Reputation: 88235

Your second problem is that you reused the variable name:

Player players[10]; // or something

void foo() {
    std::stringstream players;
    players << players[1].getID();
} //     ^          ^
  //     |          |
  // stringstream   |
  //                |
  //         also stringstream

Why would you expect the compiler to be able to figure out that the first players in players << players is the string stream but the second is the earlier declared variable?


In the first problem you might make your comparisons simpler in a number of ways.

if (a > std::max(b,c,d)) { ... }
if (b > std::max(a,c,d)) { ... }
...

This does the same thing as your code (including not handling ties), but is a little easier to read. Or you could do:

int top_score = std::max(a,b,c,d);
if (top_score == a) { ... }
if (top_score == b) { ...

This handles ties by executing the if condition for all players with the highest score. Or you could do:

Player &winner = *std::max_element(std::begin(players),std::players(end),
    [](Player &l,Player &r) { if (l.score() < r.score()) return l; else return r; });

// no conditional necessary, just access 'winner'

Although this again does not handle ties well; it just picks a winner from among the top scorers. You can also do:

Player *sorted_players[players.size()];

// fill in sorted_players
std::transform(std::begin(players), std::end(players), sorted_players, [](Player &p) { return &p; });
auto compare_players = [](Player *l, Player *r) { return l->score() < r->score(); };
std::sort(std::begin(sorted_players), std::end(sorted_players), compare_players);

// get the top scorers
int top_score = sorted_players[players.size()-1]->score();
Player *winner_begin = std::lower_bound(std::begin(sorted_players), std::end(sorted_players), top_score, compare_players);

// reward each top scorer.
for (Player *winner = winner_begin; winner<std::end(sorted_players); ++winner) {
    reward(*winner);
}

This handles ties by rewarding every player that matched the top score.

Upvotes: 2

Related Questions