I'm building a Random Character Generator in C , and I have around 12 large blocks of if
statements, like this:
int wisdom = rand() % 18;
cout << "\n";
if (wisdom == 0 || wisdom == 1) {
cout << "Wisdom Score: 1\n";
cout << "Modifier: -5\n";
} else if (wisdom == 2 || wisdom == 3) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: -4\n";
} else if (wisdom == 4 || wisdom == 5) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: -3\n";
} else if (wisdom == 6 || wisdom == 7) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: -2\n";
} else if (wisdom == 8 || wisdom == 9) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: -1\n";
} else if (wisdom == 10 || wisdom == 11) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: 0\n";
} else if (wisdom == 12 || wisdom == 13) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: 1\n";
} else if (wisdom == 14 || wisdom == 15) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: 2\n";
} else if (wisdom == 16 || wisdom == 17) {
cout << "Wisdom Score: " << wisdom << "\n";
cout << "Modifier: 3\n";
} else {
cout << "Wisdom Score: 18\n";
cout << "Modifier: 4\n";
}
I'm wondering, is there a better way to write this? Perhaps some type of function?
CodePudding user response:
The better way is to not write chained if
s at all, but instead compute the value you care about.
if (wisdom == 0) wisdom = 1; // Handle edge case treating 0 as 1
int modifier = wisdom / 2 - 5;
cout << "Wisdom Score: " << wisdom << '\n';
cout << "Modifier: " << modifier << '\n';
Note that your calculation of int wisdom = rand() % 18;
cannot produce 18 (and does produce 0
, which you don't want), so you probably want to change it to:
int wisdom = rand() % 18 1; // Result guaranteed to be 1-18 inclusive
allowing you to simplify the code by removing the if (wisdom == 0) wisdom = 1;
edge case.
As another answer has already noted, rand
is typically considered a bad API, so unless you're okay with biased results (e.g. slightly more low rolls than high rolls), you'll want to use modern C PRNG APIs (they're a little more work to set up, but trivial to use once you've done so, and they should avoid bias issues).
CodePudding user response:
Use the fact that the division of 2 integral values results in the trucation of the result:
...
int modifier = (wisdom / 2) - 5;
CodePudding user response:
You don't need any conditionals. Also, don't use rand() %
.
std::mt19937 mt(42); // seed
auto const wisdom = std::uniform_int_distribution<int>(0,18)(mt);
auto const score = wisdom !wisdom;
auto const mod = wisdom / 2 - 5;
std::cout << "Wisdom Score: " << score << "\n";
std::cout << "Modifier: " << mod << "\n";
This assumes it is intentional that you have a double chance of wisdom score 1 proccing compared to other scores. If not change the lower bound in the std::uniform_int_distribution
construction from 1
to 0
.