My code is full of If statements and I want to reduce the amount if not get rid of them all. How do I do that? Any other tips and improvements is much appreciated thanks!
I've just begun learning to code and have followed a tutrioal to write this but am struggling to understand how to minimise the amount of IFs.
void Combat() {
//combat simiulator
CombatHUD();
int userAttack;
int userDamage = 1000; //8 * level / 2;
int monsterAttack = 6 * monsterlevel / 2;
if (character.totalHealth >= 1 && monsterHealth >= 1) {
std::cout << "\n";
std::cout << "1. Attack\n";
std::cout << "2. Block\n";
std::cout << "3. Run\n";
std::cout << "\n";
std::cin >> userAttack;
if (userAttack == 1) {
//User Attack
std::cout << "Attacking... you did " << userDamage << " to the " << currentMonster << std::endl;
monsterHealth = monsterHealth - userDamage;
Sleep(1000);
CombatHUD();
if (monsterHealth >= 1) {
std::cout << "Monster is attacking... \n";
character.totalHealth = character.totalHealth - monsterAttack;
std::cout << "You recieved " << monsterAttack << " damage " << std::endl;
if (character.totalHealth <= 0) {
character.totalHealth = 0;
system("cls");
std::cout << "You died! Game over!";
Sleep(2000);
exit(0);
}
}
else if (monsterHealth <= 0) {
monsterHealth = 0;
if (character.level != character.maxlevel) {
character.current_xp += monsterXp;
LevelUp();
}
std::cout << "\n";
std::cout << "You defeated " << currentMonster << " you get " << monsterXp << "XP.\n";
Sleep(2000);
HUD();
}
Sleep(1000);
Combat();
}
else if (userAttack == 2) {
//User Block. broken?
std::cout << "Blocking\n";
int i = rand() % 100 + 1;
if (i >= 50) {
std::cout << "You blocked the incoming attack\n";
character.heal = character.level * 10 / 2;
std::cout << "you have been healed for " << character.heal << std::endl;
character.totalHealth += character.heal;
Sleep(1000);
Combat();
}
}
else if (userAttack == 3) {
//User escape
std::cout << "You try to run\n";
int x = rand() % 100 + 1;
if (x >= 50) {
std::cout << "You run away\n";
HUD();
}
else {
std::cout << "You failed to run away \n";
std::cout << "Monster does a critical hit! \n";
character.totalHealth -= monsterAttack + 10;
std::cout << "You suffered " << monsterAttack + 10 << "Your current health is " << character.totalHealth << std::endl;
Sleep(2000);
Combat();
}
}
else {
std::cout << "Invalid Input\n";
Sleep(500);
Movement();
}
}
}
void Movement() {
//user movement. enhance?
int choice;
std::cout << "\n\n";
std::cout << "1. Move forward\n";
std::cout << "2. Chill\n";
std::cout << "3. Move Backwards\n";
std::cout << "\n";
std::cin >> choice;
if (choice == 1) {
int temp = rand() % 100 + 1;
std::cout << "You begin moving forward...\n";
if (temp >= 50) {
Monster();
std::string tempName = monsterName[rand() % currentMonsterNames];
std::cout << "A " << tempName << "! Get ready to fight it!\n";
currentMonster = tempName;
Sleep(1000);
Combat();
}
std::cout << "You find nothing\n";
Sleep(1000);
HUD();
}
else if (choice == 2) {
std::cout << "You want to chill for the rest of the day\n";
if (character.totalHealth <= 99) {
character.totalHealth += 10 * character.level;
}
std::cout << "You healed by chilling Health is now " << character.totalHealth << std::endl;
Sleep(1000);
HUD();
}
else if (choice == 3) {
std::cout << "You begin moving backwards...\n";
std::cout << "You're going no where\n";
Sleep(2000);
system("cls");
}
else {
std::cout << "Invalid Input\n";
Sleep(500);
Movement();
}
}
void Monster() {
//monster creator
monsterHealth = 30; {
monsterlevel = (rand() % 3) + character.level;
}
monsterHealth = (rand() % 30) * monsterlevel;
monsterXp = monsterHealth;
if (monsterHealth == 0)
Monster();
if (monsterlevel == 0)
Monster();
}
void LevelUp() {
//level up mechanic
if (character.current_xp >= character.xp_to_level) {
character.xp_to_level += floor(character.level + 15 * pow(2, character.level / 7));
character.totalHealth = floor(character.totalHealth + 10 * pow(2, character.level / 8));
if (character.level >= character.minLevel && character.level <= character.maxlevel) {
character.level++;
}
else {
character.level = 5;
}
character.maxHealth = character.totalHealth;
std::cout << "Ba Da Bing! You've leveled up! You're max health has increased!" << std::endl;
Sleep(2000);
LevelUp();
}
Sleep(2000);
HUD();
}
Here's your Movement function represented as a switch:
void Movement() {
//user movement. enhance?
int choice;
std::cout << "\n\n";
std::cout << "1. Move forward\n";
std::cout << "2. Chill\n";
std::cout << "3. Move Backwards\n";
std::cout << "\n";
std::cin >> choice;
switch (choice)
{
case 1:
int temp = rand() % 100 + 1;
std::cout << "You begin moving forward...\n";
if (temp >= 50) {
Monster();
std::string tempName = monsterName[rand() % currentMonsterNames];
std::cout << "A " << tempName << "! Get ready to fight it!\n";
currentMonster = tempName;
Sleep(1000);
Combat();
}
std::cout << "You find nothing\n";
Sleep(1000);
HUD();
break;
case 2:
std::cout << "You want to chill for the rest of the day\n";
if (character.totalHealth <= 99) {
character.totalHealth += 10 * character.level;
}
std::cout << "You healed by chilling Health is now " << character.totalHealth << std::endl;
Sleep(1000);
HUD();
break;
case 3:
std::cout << "You begin moving backwards...\n";
std::cout << "You're going no where\n";
Sleep(2000);
system("cls");
break;
default:
std::cout << "Invalid Input\n";
Sleep(500);
Movement();
}
}
Learning switch statements and having even better function separation will usually reduce the amount of ifs. Ifs themselves are most likely unavoidable though.
This is an extremely broad, open-ended question for software design in general -- not just C++.
For the most part, you won't be able to remove ifs since you have conditional logic -- and this is fine. However there are design practices you can follow so that there are less if statements per function:
Factoring logic into smaller functions that isolate their concerns. For example, each of the different Combat actions could be individual functions. This doesn't reduce ifs, but limits the amount of nesting per-function to where it's logically needed.
Finding repeated code or patterns, and extracting them into functions. Again, this helps limit the ifs to where they are needed
Using a switch case in place of if/else ladder
With smaller functions, you can change if statements to check for early termination cases and return early to avoid nesting. This keeps nesting shorter, since the main branch after an early return is implicitly the else. For example:
void check_user_death()
{
// Instead of 'if (character.totalHealth <= 0)'
if (character.totalHealth > 0) {
return;
}
system("cls");
std::cout << "You died! Game over!";
Sleep(2000);
exit(0);
}
All of the above suggestions are just overall software design topics, and are not strictly-speaking specific to C++
As an unrelated note, you might want to look into using loops (e.g. for or while), since your Combat function seems to recursively call itself in a few cases -- which could potentially result in stack overflows.
Related
So I have an issue with my code where I cannot get either of my functions (int human_turn, or int computer_turn) to return the correct value of their turn totals. What I am trying to do is have the two int functions return their respective turn totals after they are done with their turn, then have a separate function that will cout these values and will act as the scoreboard and also show if the win conditions are met. Currently at the end of the while loop for each ones turn, I have turnTotal_1 = roll_1 + turnTotal_1; which updates the total and then the loop checks to see if the while is still true. I then put a return turnTotal_1; statement after the loop so it would return this value, and it will always return 1. No matter what the value of the turn total is, the return statement will always return 1. any help or advice would be appreciated.
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <unistd.h>
#include <stdio.h>
using namespace std;
/**
* rollDie
* returns a random integer between 1 and 6, works as rolling a dice.
* return value, int number (1-6)
*/
int rollDie()
{
return random() % 6 + 1;
}
int human_turn(int turnTotal_1)
{
cout << "It is now human's turn" << endl;
cout << "Do you want to roll a dice(Y/N)?:" << endl;
char user_choice;
cin >> user_choice;
while ((user_choice == 'y') || (user_choice == 'Y'))
{
int roll_1 = rollDie();
if ((roll_1 == 2) || (roll_1 == 5))
{
cout << "You rolled a " << roll_1 << endl;
roll_1 = 0;
}
else if ((roll_1 == 1) || (roll_1== 3) ||(roll_1 == 6))
{
cout << "You rolled a " << roll_1 << endl;
}
else if (roll_1 == 4)
{
cout << "You rolled a " << roll_1 << endl;
roll_1 = 15;
}
turnTotal_1 = roll_1 + turnTotal_1;
cout << "Your turn total is " << turnTotal_1 << endl;
cout << "Do you want to roll a dice(Y/N)?:" << endl;
cin >> user_choice;
}
if ((user_choice == 'n') || (user_choice == 'N'))
{
return turnTotal_1;
}
}
int computer_turn()
{
int turnTotal_2 = 0;
cout << "It is now computer's turn" << endl;
int roll_1 = rollDie();
while (turnTotal_2 <= 10)
{
int roll_1 = rollDie();
if ((roll_1 == 2) || (roll_1 == 5))
{
cout << "Computer rolled a " << roll_1 << endl;
roll_1 = 0;
}
else if ((roll_1 == 1) || (roll_1== 3) ||(roll_1 == 6))
{
cout << "Computer rolled a " << roll_1 << endl;
}
else if (roll_1 == 4)
{
cout << "Computer rolled a " << roll_1 << endl;
roll_1 = 15;
}
turnTotal_2 = roll_1 + turnTotal_2;
cout << "Computer turn total is " << turnTotal_2 << endl;
}
}
void scoreboard()
{
cout << human_turn << endl;
cout << computer_turn << endl;
}
void game()
{
cout << "Welcome to Jeopardy Dice!" << endl;
human_turn(0);
cout << human_turn << endl;;
computer_turn();
scoreboard();
}
int main()
{
// start the game!
game();
return 0;
}
Here is an example of how it runs.
Welcome to Jeopardy Dice!
It is now human's turn
Do you want to roll a dice(Y/N)?:
n
1
It is now computer's turn
Computer rolled a 5
Computer turn total is 0
Computer rolled a 4
Computer turn total is 15
I am currently making a quiz program. And I created a countdown, but as c++ does actions line by line I am getting what I want. I want countdown work simultaneously with the tests.
here is the one part of my program
void QUIZ::OOP2()
{
system("cls");
QUIZ("OOP2");
int oop2_time = 100;
for (int i = oop2_time; oop2_time >= 0; i--)
{
cout << "\t\t\tQuestions of OOP2\n\n";
line();
cout << "1. Switch selection structure can be used to represent any kind of if-else selection structure? \n";
line();
cout << " a) True b) False \n";
CorrectB(var);
if (oop2_time == 100)
{
cout << "You have the remaining" << oop2_time << "seconds \n" << endl;
Sleep(40000);
}
if (oop2_time == 60)
{
cout << "You have the remaining" << oop2_time << "seconds \n" << endl;
Sleep(30000);
}
if (oop2_time == 30)
{
cout << "You have the remaining" << oop2_time << "seconds \n" << endl;
Sleep(15000);
}
if (oop2_time == 15)
{
cout << "You have the remaining" << oop2_time << "seconds \n" << endl;
Sleep(10000);
}
if (oop2_time == 5)
{
cout << "You have the remaining" << oop2_time << "seconds \n" << endl;
Sleep(5000);
cout << "\nTime is out\n";
goback();
intro();
}
result("OOP2");
goback();
}
}
Without using multi-threading or std::chrono but just your base code, here's a code snippet. I have used recursive function and a time resolution of 1 second. The countdown can also be terminated prematurely in the main by setting stop = true; :
#include <iostream>
#include <windows.h>
void wait(double sec, bool& stop)
{
std::cout <<"Time remaining "<< sec << " sec\n";
if (stop || sec <= 0) return;
Sleep(1000);
wait(sec-1, stop);
}
int main()
{
bool stop = false;
wait(5, stop);
}
I am trying to add a countdown timer to this program. I would like the timer to start when the first math fact question is asked and upon expiration i want the program to give the grade. What's the code to do this in c++ if possible?
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
int main(int args, char* argv[])
{
int i;
int result;
int solution;
char fact;
bool done = false;
int correct = 0;
int count = 0;
do {
try {
cout << "Enter (m)ultiplication or "
<< "(a)ddition." << endl; /*or (s)ubstraction. */
cin >> fact;
while (!cin)
throw fact;
if (fact != 'A')
if (fact != 'a')
if (fact != 'M')
if (fact != 'm')
while (!cin)
throw fact;
cout << "Now, enter the number of the fact that
you would like to do." << endl;
cin >> i;
int wrong = 0;
int score = 0;
int j = 0;
while (!cin)
throw i;
switch (fact) {
case 'm':
case 'M':
while (j < 13) {
cout << "What's " << i << " x " << j << "?" << endl;
cin >> result;
while (!cin)
throw result;
solution = i * j;
if (result == solution) {
cout << "Great Job! That is the correct answer for the problem "
<< i << " x " << j << "." << endl;
cout << endl;
cout << endl;
cout << endl;
score++;
j++;
cout << endl;
}
if (result != solution) {
cout << "Oh no! " << result << " is NOT the correct answer for "
<< i << " x " << j << "." << endl;
wrong = wrong + 1;
count++;
}
if (count == 3) {
cout << "The correct answer is " << i * j << "." << endl;
j++;
wrong = wrong - 3;
count = 0;
}
if (count == 1) {
cout << endl;
count--;
wrong = wrong - 1;
}
if (count == 2) {
cout << endl;
count--;
wrong = wrong - 2;
}
}
case 'a':
case 'A':
while (j < 13) {
cout << "What's " << i << " + " << j << "?" << endl;
cin >> result;
while (!cin)
throw result;
solution = i + j;
if (result == solution) {
cout << "Great Job! That is the correct answer for the problem "
<< i << " + " << j << "." << endl;
cout << endl;
cout << endl;
cout << endl;
score++;
j++;
cout << endl;
}
if (result != solution) {
cout << "Oh no! " << result << " is NOT the correct answer for "
<< i << " + " << j << "." << endl;
wrong = wrong + 1;
count++;
}
if (count == 3) {
cout << "The correct answer is " << i + j << "." << endl;
j++;
wrong = wrong - 3;
count = 0;
}
if (count == 1) {
cout << endl;
count--;
wrong = wrong - 1;
}
if (count == 2) {
cout << endl;
count--;
wrong = wrong - 2;
}
}
if (j == 13) {
system("pause");
correct = score - wrong;
score = (correct * 100) / 13;
}
if (score >= 80) {
cout << "Excellent!!!!!" << endl;
cout << "You scored " << score << "%." << endl;
cout << "You got " << correct << " out of 13 correct." << endl;
cout << "Keep up the good work." << endl;
} else if (score >= 70) {
cout << "Congratulations!!!!!" << endl
cout << "You scored " << score << "%." << endl;
cout << "You got " << correct << " out of 13 correct." << endl;
cout << "Let's see if we can score even higher next time." << endl;
} else {
cout << "You scored below 70 which means that you may need some"
<< " more practice." << endl;
cout << "You scored " << score << "%." << endl;
cout << "You got " << correct << " out of 13 correct." << endl;
cout << "You might want to try the " << i << " facts again."
<< " Goodluck!!!!!" << endl;
}
}
} catch (char fact) {
cout << "Invalid input. You can only enter (m)ultiplication or"
<< " (a)ddition. Please try again." << endl;
cin.clear();
cin.ignore(100, '\n');
} catch (int i) {
cout << "Invalid input0. You can only enter a
number here. Please try again." << endl;
cin.clear();
cin.ignore(100, '\n');
} catch (...) {
cout << "Invalid input2. You can only enter a number here.
Please try again." << endl;
cin.clear();
cin.ignore(100, '\n');
}
} while (!done);
return 0;
}
The task is quite hard, but if you dare trying, I suggest doing it in two steps:
Implement inaccurate solution: timer expiration is checked between queries to user.
If there is some time left, next question is asked, otherwise statistics is shown. So program always waits for user input on the last question despite timer has run out. Not what exactly quizzes look like, but good move to start with.
Method: before starting quiz save current time, before each question take delta between saved time and current one and compare with time limit. Example with chrono (starting from C++11), example with oldschool clock
Add middle-question interruption
This part requires function, which will wait for user input not longer, than specified amount of time. So instead of using std::cin() you'll need to calculate amount of time left (time limit minus delta between cur time and start time) and call some sort of cin_with_timeout(time_left).
The hardest thing is implementing cin_with_timeout(), which requires solid knowledge of multithreading and thread synchronization. Great inspiration can be found here, but it is direction to start thinking rather than complete solution.
my program is all finished but I want to know how to add a "Play again" feature that uses "Yes" or "No" input to decide whether to run the program again or to end it. I am a little unsure of where to place it in my program since I use a handful of while loops and if/else statements. Any insight would be appreciated, thanks! Here is my code:
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;
int main() // Setting up the code to follow.
{
srand(static_cast<unsigned int>(time(0)));
int Weapon_Selection; // Creating variables for the player and computer's weapon selection.
int Comp_Weapon;
bool Battle = true; // The variable to begin the battle.
while(Battle) // The main while loop to run the program code.
{
int Player_Health = 100; // More variables for both the player and the computer.
int Comp_Health = 100;
int Cannon_Ammo = 3;
int Grenade_Ammo = 4;
int Comp_Cannon_Ammo = 3;
int Comp_Grenade_Ammo = 4;
while(Player_Health > 0 && Comp_Health > 0) // The while loop to continue running the program while both combatants are alive.
{
bool Invalid = true;
bool Comp_Invalid = true;
while(Invalid)
{
cout << "Select a weapon using number keys 1, 2, and 3.\n"; // Weapon selection input from the player.
cout << "1. Cannon (Ammo left: " << Cannon_Ammo << ")\n";
cout << "2. Grenade (Ammo left: " << Grenade_Ammo << ")\n";
cout << "3. Rifle\n";
cout << "\n";
cout << "You select: ";
cin >> Weapon_Selection;
srand(static_cast<unsigned int>(time(0)));
if (Weapon_Selection == 1 && Cannon_Ammo > 0)
{
Cannon_Ammo -= 1;
Invalid = false;
int Player_Dmg = rand() % 5 + 10; // Randomly generated damage range.
cout << "You caused " << Player_Dmg << " cannon damage to your enemy!\n";
Comp_Health -= Player_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
break;
}
else if (Weapon_Selection == 2 && Grenade_Ammo > 0)
{
Grenade_Ammo -= 1;
Invalid = false;
int Player_Dmg = rand() % 5 + 7;
cout << "You caused " << Player_Dmg << " grenade damage to your enemy!\n";
Comp_Health -= Player_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
break;
}
else if (Weapon_Selection == 3)
{
Invalid = false;
int Player_Dmg = rand() % 5 + 3;
cout << "You caused " << Player_Dmg << " rifle damage to your enemy!\n";
Comp_Health -= Player_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
break;
}
else
cout << "You are out of ammo or you have entered an invalid number." << "\n"; // Output for wrong number input or no ammo.
cout << "\n";
}
if (Comp_Health <= 0) // Break point if the computer dies in battle.
break;
while(Comp_Invalid) // The computer's random weapon selection.
{
Comp_Weapon = rand() % 3 + 1;
if (Comp_Weapon == 1 && Comp_Cannon_Ammo > 0)
{
Comp_Cannon_Ammo -= 1;
Comp_Invalid = false;
int Comp_Dmg = rand() % 5 + 10; // Randomly generated damage range for the computer.
cout << "Your enemy used a cannon and caused " << Comp_Dmg << " damage to you!\n";
Player_Health -= Comp_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
}
else if (Comp_Weapon == 2 && Comp_Grenade_Ammo > 0)
{
Comp_Grenade_Ammo -= 1;
Comp_Invalid = false;
int Comp_Dmg = rand() % 5 + 7;
cout << "Your enemy used a grenade and caused " << Comp_Dmg << " damage to you!\n";
Player_Health -= Comp_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
}
else
{
Comp_Invalid = false;
int Comp_Dmg = rand() % 5 + 3;
cout << "Your enemy used a rifle and caused " << Comp_Dmg << " damage to you!\n";
Player_Health -= Comp_Dmg;
cout << "Your health is " << Player_Health << "\n";
cout << "The computer's health is " << Comp_Health << "\n";
cout << "\n";
}
}
}
if(Player_Health < 0) // End of battle output, regardless of who wins or loses.
cout << "You have been defeated by your enemy!" << "\n" << endl;
else
cout << "Congratulations, you beat your enemy!" << "\n" << endl;
}
cin.ignore(2);
return 0;
}
To illustrate #NathanOliver's comment:
int main(void)
{
bool play_again = true;
while (play_again)
{
Play_Game();
std::cout << "\nWant to play again (y / n)?";
char answer;
std::cin >> answer;
if (tolower(answer) != 'y')
{
play_again = false;
}
}
return 0;
}
You could also use a do-while loop as well.
I'm building a Toothpick Game of 23 in C++ as an homework assignment in my Programming course. I'm almost finished with the code and the output looks exactly like the one that I am suppose to follow.
I am supposed to use a function in my code but I don't know how to use the function. Everything in the program works like it should except the function returns 0 and that 0 is the last line of the output and that's the line that is not identical to the output I am supposed to follow. So maybe someone can help my find out how I can get this right.
#include <iostream>
using namespace std;
int computerMove(int numPicksLeft, int humanNumber);
int main()
{
int a, z=0, y=0;
a = computerMove(z, y);
cout << a;
return 0;
}
int computerMove(int numPicksLeft, int humanNumber) {
int number_left=23, n, cpu_turn;
do{
cout << "There are " << number_left << " toothpicks left. Pick 1, 2 or 3 toothpicks: ";
cin >> n;
if (n <= 3)
{
number_left -= n;
if (number_left > 4)
{
cpu_turn = (4 - n); // þar sem n er fjöldi tannstöngla dregnir af notanda.
cout << "I pick " << cpu_turn << " toothpicks" << endl;
number_left -= cpu_turn;
}
else if (number_left == 2)
{
cpu_turn = 1;
cout << "I pick " << cpu_turn << " toothpicks" << endl;
number_left -= cpu_turn;
}
else if (number_left == 3)
{
cpu_turn = 2;
cout << "I pick " << cpu_turn << " toothpicks" << endl;
number_left -= cpu_turn;
}
else if (number_left == 4)
{
cpu_turn = 3;
cout << "I pick " << cpu_turn << " toothpicks" << endl;
number_left -= cpu_turn;
}
else if (number_left == 1)
{
cpu_turn = 1;
cout << "I pick " << cpu_turn << " toothpicks" << endl;
cout << "You won!" << endl;
number_left -= cpu_turn;
}
else if (number_left == 0)
{
cpu_turn = 0;
cout << "I pick " << cpu_turn << " toothpicks" << endl;
cout << "I won!" << endl;
}
}
else
cout << "Invalid input. Try again." << endl;
} while (number_left > 0);
return 0;
}
I always get this 0 in the last line and I don't want that. So my question is. How can I use this function so it won't be like this?
The function signature indicates the return type of the function is an integer (int). The function itself will finally return 0 if it reaches the end which you assign and print in your main function. If you are not interested in the result of the function why have it return something at all?
You could change the return type to void and not return/assign anything and the 0 would be left out.
void computerMove(int numPicksLeft, int humanNumber) {
// Your code
// No return statement!
}
Something like this for example.
As a side note avoid using namespace std;.