I\'m new to programming and I started to make my own Fire Emblem level up calculator, but for some reason it loops infinitely. I can\'t find an answer. Could you look for an
You have two major problems which may cause compilation error.
nr+1;
level-1;
You have to assign them into some variable. Try this:
nr = nr+1;
or
nr++;
and
level = level -1;
or
level--;
now the while
loop is not going to loop infinite.
Second problem is
if (cha[6] = 'Dieck' )
Note that, =
is an assignment operator, not an equal operator. Equal operator looks like double equal ==
. As you want to compare whether cha
is equal to Dieck
or not, try this:
if (strcmp (cha, "Dieck") == 0)
But you need to include #include<cstring>
for that.
Reference here.
level-1;
computes the value of level-1
and then throws it away, doing essentially nothing. As such, the value in level
is never updated and you're stuck with an infinite loop (you are also doing this with all of your variable updates, be careful!)
If you want to decrement the value of level (reduce it by one), you can do any of the following:
level = level - 1;
level -= 1;
level--;
Furthermore, if(cha[6] = 'Dieck')
is not correct on several fronts. You could perhaps do
if(strcmp(cha, "Dieck") == 0) { //...
If you make sure to #include <cstring>
One issue you have is cha[6] = 'Dieck'
cha[6]
is a single character such as 'D' or 'i' but not the whole thing. Also =
sets cha[6]
equal to 'Dieck'
which can't happen because 'Dieck'
is not a valid character. To compare them you'd need ==
but you can only compare one character at a time like cha[0] == 'D'
Really you should make your input a string, and use the compare() method of the string.
std::string input;
// stuff
cin >> input;
if (input.compare("Dieck") == 0)
{
// more stuff
}
std::string
s, std::bind
s initializer lists, modern random number generators, auto
variable typing. Shucks, even a few oldies-but-goodies like classes and error checking the input.
#include <iostream>
#include <random>
#include <functional>
#include <map>
// prep random number generator to simulate a 100 sided die
std::default_random_engine engine; // not being fancy here. Just using default RNG
std::uniform_int_distribution<int> uniform(1,100);// random from 1 to 100
auto d100 = std::bind ( uniform, engine ); // Convenience wrapper
void upstat(int & stat, // stat to increase
int chance, // odds of increase
int inc, // amount to increase
const std::string & statname)
{
if (d100() <= chance)
{ //less than or equal because I decided to emulate a d100.
// if the range was 0 - 99, only < would be necessary.
// such is the cost of slavishly adhering to dice conventions.
// std::cout<< statname << " increased by " << inc << std::endl;
stat += inc;
}
}
class Character
{
public:
Character(const std::string & name,
int level,
int HP,
int str,
int skl,
int spd,
int lck,
int def,
int res):
mName(name), mLevel(level), mStr(str), mSkl(skl), mLck(lck),
mDef(def), mRes(res), mHP(HP), mSpd(spd)
{
}
void levelup()
{
upstat(mHP, 90, 1, "HP");
upstat(mStr, 40, 1, "Strength/Magic");
upstat(mSkl, 40, 1, "Skill");
upstat(mSpd, 30, 1, "Speed");
upstat(mLck, 35, 1, "Luck");
upstat(mDef, 20, 1, "Defense");
upstat(mRes, 15, 1, "Resistance");
mLevel++;
}
// a couple useful getters
const std::string & getName()
{
return mName;
}
unsigned int getLevel()
{
return mLevel;
}
// out stream operator
friend std::ostream & operator<<(std::ostream & out,
const Character & ch)
{
out << "Stats " << "HP/STR/SKL/SPD/LCK/DEF/RES " <<
ch.mHP << " " <<
ch.mStr << " " <<
ch.mSkl << " " <<
ch.mSpd << " " <<
ch.mLck << " " <<
ch.mDef << " " <<
ch.mRes << std::endl;
return out;
}
private:
std::string mName;
unsigned int mLevel;
int mStr;
int mSkl;
int mLck;
int mDef;
int mRes;
int mHP;
int mSpd;
};
// name-indexed list of characters. Currently only contains Dieck.
std::map<std::string, Character> charlist{{"Dieck",{"Dieck",1, 26, 9, 12, 10, 4, 6, 1}}};
int main()
{
unsigned int finalLevel;
std::string cha; // using a string rather than a char array. Much less error prone.
std::cout << "Which character?" <<std::endl;
std::cin >> cha;
auto found = charlist.find(cha); // look in charlist for selected character
if (found != charlist.end()) // find returns end of list if not found
{
std::cout << "You chose " << found->second.getName() << "." << std::endl <<
found->second << std::endl; //optional. Print stats
for ( ; ; ) // Stay a while. Stay FOREVER! Muhuhahahahaha!
{
std::cout << "What level do you want him/her to be?" << std::endl;
if (std::cin >> finalLevel)
{
while (found->second.getLevel() < finalLevel)
{ // keep calling characer's level up routine until desired level reached
// or do nothing if the character is already a higher level.
found->second.levelup();
}
std::cout << found->second << std::endl; //optional. Print new stats
break; // breaks the infinite loop if input was good
}
else
{ // bad user input. Call user names until they get it right.
std::cout << "Valid positive numbers only, please." << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
}
}
}
else
{ // didn't find character. Do nothing.
// Should probably prompt to create new character here.
std::cout << "Character " << cha << " not found." << std::endl;
}
return 0;
}
Doesn't change much, but replaces std::bind
with a Lambda expression.
std::default_random_engine engine;
std::uniform_int_distribution<int> uniform(1,100);
auto d100 = std::bind ( uniform, engine );
is replaced with
auto d100 = [](){
// all bundled up inside the lambda. No globals leaking out
static std::mt19937 gen{std::random_device{}()};
// explicitly specified the generator. Fewer surprises.
// this can be expensive, so it might be worth exposing gen and sharing it with
// other die-rolling lamdas
static std::uniform_int_distribution<int> uniform(1,100); // random from 1 to 100
return uniform(gen); // return result
};