I have a Project for my programming class, and its requiring me to set up the main functionality for the casino using functions.
First, I needed to seed the random number generator which I think I did right.
void seedRand(int seed)
{
srand(time(0));
}
Second, was to continue to set up functions. So I set the next one to print out numbers to the second decimal place.
void printMoney(double money)
{
std::cout << std::setprecision(2) << std::fixed;
}
The next one, and the one I'm not understanding, is to have the user pay, and have the casino receive the money.
Sorry if i didn't put enough information, if something is missing please ask. I'm still new to understanding everything. Any help would be appreciated. Thanks.
void payMoney(double & wallet, double amount)
{
}
which I think I did right.
No you didn't, it should rather look like
void seedRand(int seed) {
srand(seed == 0?time(0):seed);
}
If there's a parameter passed, it's probably meant to be actually used. I've chosen zero as a convention, when seed() should be called with a randomly time based value.
So I set the next one to print out numbers to the second decimal place.
Your second function sets up the output stream state well, but misses to output the value, it should look like
void printMoney(double money) {
std::cout << std::setprecision(2) << std::fixed << money << std:: endl;
// ^^^^^
}
And at least your last function is probably supposed to be implemented as
void payMoney(double & wallet, double amount) {
wallet -= amount;
}
All in all it's hard to answer what you're supposed to do with this task.
But since you tagged this question c++, I'd rather recommend to go putting these functions in context of classes like class Casino and class Player.
class Casino;
class Player {
double wallet;
public:
void payMoney(Casino& Casino, double amount);
};
class Casino {
public:
void addToBank(double money) {
bank += money;
}
private:
double bank;
};
void Player::payMoney(Casino& casino, double amount) {
wallet -= amount;
casino.addToBank(amount);
}
Related
Apologies in advance if this is below the community's paygrade. I just started learning about OOP and English is not my native language.
I just learned about using getters and setters, and the importance of data encapsulation. However, All the examples I've seen online using getters and setters all deal with static values such as the one below:
#include <iostream>
using namespace std;
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
int main() {
Employee myObj;
myObj.setSalary(50000);
cout << myObj.getSalary();
return 0;
}
I've managed to allow user input by declaring another set of variables and feeding them as parameters into the setters like below:
int main() {
Employee myObj;
int salary;
cout<<"Enter salary: " << endl;
cin>>salary;
myObj.setSalary(salary);
cout << myObj.getSalary();
return 0;
}
Is this the only way to allow user input? Is there a more elegant way of accomplishing this other than declaring another set of local variables?
Sorry if this is a beginner question. I'm new to the C++ game and am still getting my feet wet.
Is this the only way to allow user input? Is there a more elegant way of accomplishing this other than declaring another set of local variables?
(and from comment)
I was hoping I could do some variation of myObj.setSalary(cin) so cin would feed the value directly into the getter without me having to pass it into temp variables
I would not mix input from stdin with setters, better keep them as seperate methods:
class foo {
int x;
int other_member;
public:
void set_x(int a) { x = a; }
void set_other_member(int a) { other_member = a; }
void read_x(std::istream& in) {
in >> x;
}
};
This lets you write
f.read_x(std::cin);
to read x from stdin.
Note that there are many ways to accomplish the same and what is "elegant" is rather subjective. Typically you would provide an overload for operator>> to read a foo from a stream:
std::istream& operator>>(std::istream& in, foo& f) {
int a,b;
in >> a >> b;
f.set_x(a);
f.set_other_member(b);
}
Either this (using the setters) or you make the operator a friend of foo (to access privates directly) or you use foo::read_x to implement it. Then you can write
foo f;
std::cin >> f;
Note that C++ is not a "pure" OOP language, and idiomatic C++ will happily eschew certain OOP principles in favor of simpler and more effective code where applicable.
It is perfectly acceptable, if you want a datatype to just "hold" data, to use a plain old struct (with public data fields). Don't confuse the benefits of encapsulation (...of non-trivial constructs, so you can change their implementation internally) with any kind of "security". Getters/Setters or not, anyone can change your object's data if he wants to. Incidentially, this makes reading data easier.
cin >> e.salary;
If you don't want "just a struct", it is good style to have a constructor that sets meaningful initial values, so that you don't have "uninitialized" Employee objects flying around (RAII). This means that neither your client nor your destructor has to deal with the possibility that Employee might not actually be one (hold null pointers, or other kinds of uninitialized resources).
Employee e( "Mark Smith", 10000 );
Once you are at that point, Employee should be responsible for anything that happens to / with an Employee object. That implies that it should not be somebody else that's reading user input and writes it to Employee data fields (via setters or not), it should be a message sent to the Employee object that it should update its fields, from input or otherwise, as appropriate.
(Consider the possibility of someone setting a pointer member of yours to nullptr, or worse, some random value. Your destructor would throw a fit trying to free the resource, and then how you'd debug where that invalid pointer came from?)
At which point we arrive at the operator>>(), which can be overloaded for istreams and your class.
class Employee
{
public:
// ...
friend istream & operator>>( istream &, Employee & );
// ...
};
istream & operator>>( istream & in, Employee & e )
{
getline( e.name, in );
in >> e.salary;
return in;
}
int main()
{
Employee e; // For the sake of example, a default constructed employee
cout << "Enter new employee's name (on its own line), and salary:\n";
cin >> e;
}
And once there, you get an idea of what data encapsulation actually means: Employee is an object, not a data container. You should not poke around in it's innards, you should send messages.
Employee e( "Mark Smith", Role::INTERNEE, 10000 );
cout << e; // Output: "Mark Smith, Internee, with an income of 10.000 sicles."
e.promote( Role::TEAM_LEAD, 10000 ); // Exception: "Wrong pay scale for Team Leads."
e.promote( Role::TEAM_LEAD, 30000 );
cout << e; // Output: "Mark Smith, Team Lead, with an income of 30.000 sicles and a free car."
Note how the Employee class sanity-checked the new salary, and knew that a promotion to Team Lead automatically included a free car, and did that without you having to set that yourself. That is what this encapsulation is about...
As for your question "as asked", whether your implementation could do read a salary more elegantly, you could of course...
void setSalary(istream & in) {
in >> salary;
}
...and...
cout << "Enter salary:" << endl;
e.setSalary( cin );
And because that's properly encapsuled, you could add sanity checks, change the type of salary to BigNum, or start support reading in hieratic.
THIS QUESTION IS A GENERAL ANSWER WILL COVER YOU QUESTION
So in OOP, making and using only the copy or the OBJECT is a core concept, the way you are making a single copy OBJECT of a class is a standard one, but have you ever thought about MAKING AN ARRAY OF TYPE "YOUR CLASS's Objects"? because in your case the obj will only hold only one copy of Employee but if you use a data structure e.g "Array" for storing a number of objects then it will be a lot easier let me clarify for you
EXAMPLE
int a, b, c, d, e, f, g ... z;
assigning all of these alphabets a value will be a huge pain but wait you can have a data structure for it.
int arrayOfAlphabets[26];
now you want to assign values? (you can assign it dynamically but this is just an example to show you that you can just control the assigning of a variable with just a counter)
for(int x = 0 ; x < 26; x++){
arryOfAlphabets[x] = someNumber
}
Want to get Values? you can get values dynamically but this is just an example to show you that you can just control the setting & getting of a variable with just a counter)
for(int x = 0; x < 26; x++){
cout << "Value of Alphabet" + x + " is: " + arrayOfAlphabets[x] << endl;
}
now you have seen the example that making a data structure specific data type can remove a lot of pain of yours now keep in mind for the sake of understanding,
YOUR CLASS IS DATATYPE THAT YOU CREATED
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
and in main what you can do is
int main(){
Employee emp[5];
int tempSalery;
for( int i=0; i<5; i++ )
{
cin >> tempSalery;
emp[i].setSalery(tempSalery);
}
}
now to print out your result
for( int i=0; i<5; i++ ){
cout << "Employee " + x + "Salery is: " + emp[i].getSalery() << endl;
}
I have been having trouble with a simple program that utilizes seperate file classes (i'm pretty new to them). Could you please help me figure out why it won't display the changed value?
main
stats startout;
startout.beginning();
startout.start();
header
class stats
{
public:
void start();
void beginning();
//setter
void setHealth(int x){
health = x;
}
//getter
int getHealth(){
return health;
}
private:
int health;
};
implementation .cpp file
void stats::beginning(){
stats set;
set.setHealth(10);
}
void stats::start(){
stats stat;
cout << "Health: " << stat.getHealth() << endl;
}
It keeps displaying health as 0, which I assume is some sort of default since it is not being set as ten as described in my beginning() function. If anybody knows what the problem is or has suggestions on the best way to handle variables in classes and trading them between functions then please share your wisdom!
The functions start() and beginning() are still members of the class just like your getter and setter functions. That they're in a different .cpp doesn't mean you need new local instances of stats set and stat respectively, they still members of the instance declared as startout and will operate on it. You've made them operate on brand new instances.
So they should be defined as
void stats::beginning() {
setHealth(10);
}
void stats::start() {
cout << "Health: " << getHealth() << endl;
}
in my class, I have two methods that are responsible for getting and setting the value of a private variable. In another method that is outside of the class, I call the setter method and change the variable to another value. It works temporarily but always resets to the original value.
class storeItem
{
public:
void setPrice(int p)
{
price = p;
}
int getPrice()
{
return price;
}
storeItem(int p)
{
price = p;
}
private:
int price;
}
void changePrice(storeItem item)
{
int origPrice = item.getPrice();
item.setPrice(rand() % 10 + 1);
//The price is correctly changed and printed here.
cout << "This item costs " << item.getPrice() << " dollars and the price was originally " << origPrice << " dollars." << endl;
}
int main()
{
storeItem tomato(1);
changePrice(tomato);
//This would print out "This item costs *rand number here* dollars and the price was originally 1 dollars." But if I call it again...
changePrice(tomato);
//This would print out "This item costs *rand number here* dollars and the price was originally 1 dollars." even though the origPrice value should have changed.
}
I'm sure I'm making a silly beginners mistake and I appreciate any help in advance! :)
In C++, function parameters are passed by value unless you indicate otherwise. In your example, you are passing the storeItem by value to your function, so you are modifying a local copy inside of the function body. There is no effect on the caller side. You need to pass a reference:
void changePrice(storeItem& item)
^
Semantically, a reference is just an alias for an object, so you can consider the storeItem inside of your function to be the same as the one on the caller side.
When calling your function changePrice you don't call it by reference, nor with a pointer to the storeItem, so a copy is built.
Call it by reference instead:
void changePrice(storeItem& item)
{
//what you did before
}
Refer to this for further reference.
#include<iostream>
#include <string>
using namespace std;
class Car{
private:
public: Car(int, string, int);
Car(){} //default constructor
void setbrake();
void setacc();
int year,speed;
string make;
};
Car::Car(int year, string make, int speed = 0) //constructor with parameters
{
cout << "Enter your car's year." << endl;
cin >> year;
cout << "Enter your car's make. " << endl;
cin >> make;
cin.ignore();
speed = 0; }
void Car::setbrake(){ //first function
speed = speed - 5;
cout << "Your " << make << " is traveling at " << speed;
cout << " MPH.";}
void Car::setacc(){ //second function
speed = speed + 5;
cout << "Your " << make << " is traveling at " << speed;
cout << " MPH.";}
int main()
{
Car car1(0,"s");
cout << car1.make;
cout << car1.speed;
cout << car1.year;
car1.setacc();
system("pause");
return 0;
}
I'm having a problem getting my variables to display in my two member functions, and it doesn't display anything in main.
The speed variable always comes out to 49898575 <-- some randomly high number like that, and I assume I initialized it to 0.
I've been stuck on this all week.
How do I connect my class private variables and my member functions.
I thought my constructor with parameters would take care of that problem, but obviously not.
Can someone please take the time to critique this code for me. I'm going to pull my hair out.
Here's the problem that was assigned for class, and this is what I'm aiming to do, but I'm not catching on to classes and member functions, and how they work together.
Write a class named Car that has the following member variables:
• year. An int that holds the car’s model year.
• make. A string that holds the make of the car.
• speed. An int that holds the car’s current speed.
In addition, the class should have the following member functions.
• Constructor. The constructor should accept the car’s year and make as arguments
and assign these values to the object’s year and make member variables. The constructor
should initialize the speed member variable to 0.
• Accessors. Appropriate accessor functions should be created to allow values to be
retrieved from an object’s year, make, and speed member variables.
• accelerate. The accelerate function should add 5 to the speed member variable
each time it is called.
• brake. The brake function should subtract 5 from the speed member variable each
time it is called.
Demonstrate the class in a program that creates a Car object, and then calls the accelerate
function five times. After each call to the accelerate function, get the current speed of the car and display it.
Then, call the brake function five times.
After each call to the brake
function, get the current speed of the car and display it.
You're changing the values of your parameters, which shadow your members, leaving both ints uninitialized (the string will be an empty string).
The better option is to use different names:
Car::Car(int y, string m, int s = 0)
You could, however, use this:
this->speed = 0;
I'd recommend a constructor initializer list, though, which doesn't require either, and doing it in the order they're declared in the class:
Car::Car(int year, string make, int speed = 0)
: year(year), speed(speed), make(make) {}
Ideally, I would do something like this, with tweaking depending on what else it's meant to be used for (I'll keep it C++03):
class Car {
int year_;
std::string make_;
int speed_;
public:
Car(int, const std::string &, int);
void brake();
void accelerate();
void printInfo() const;
};
Car::Car(int year, const std::string &make)
: year_(year), make_(make), speed_() {} //speed should always be 0
void Car::brake() {
speed_ -= 5; //consider ensuring it stays at or above 0
}
void Car::accelerate() {
speed_ += 5;
}
void Car::printInfo() const {
std::cout << "Your " << make_ << " is traveling at " << speed_ << " MPH.";
}
You'll have to figure out exactly what the default constructor should do if you want one. I used a constructor initializer list to initialize the data members, I separated the printing from the accelerating/braking, accepted const references where reasonable, and made the printing function const since it doesn't modify the object.
Please tear this code apart, make it complex and scarcely readable, I'd rather learn the hard way once than learn the same thing many times the wrong way.
The base class is as follows:
class baseMob{
private:
int _healthMax;
int _healthCurrent;
int _manaMax;
int _manaCurrent;
int _experiencePoints;
public:
//Set max Hp
void setHealthMax(int);
//Get max Hp
int getHealthMax();
//Set Current Hp
void setCurrentHealth(int);
//Get Current Health
int getCurrentHealth();
//Set Max Mana
void setMaxMana(int);
//Get Max Mana
int getMaxMana();
//Set Current Mana
void setCurrentMana(int);
//Get Current Mana
int getCurrentMana();
//getMob Exp on kill
int getExperiencePoints();
//Set mob Exp points
void setExperiencePoints(int);
//leaving out the member functions for space conservation
};
The individual mob that I'm trying to create is a green slime, which I'm trying to create via the default constructor I've made...
class greenSlime: private baseMob{
public:
greenSlime(){
setHealthMax(100);
setMaxMana(100);
setCurrentHealth(100);
setCurrentMana(100);
setExperiencePoints(150);
}
};
My main function looks like this right now:
greenSlime slime();
for(; slime.getCurrentHealth() >= 0; slime.setCurrentHealth(-1)){
cout << "The current health of the slime is: " << slime.getCurrentHealth() << endl;
if (slime.getCurrentHealth() <= 0 ){
cout << "Player is awarded with: " << slime.getExperiencePoints() << " Experience. ";
}
}
If anyone wants to tear this up and make me look like a jackass, I'd really appreciate the help.
The error that I'm presently getting is:
Project1.cpp:107: error: request for member getCurrentHealth' inslime', which is of non-class type `greenSlime ()()'
Along with other errors of the same type.
Tl;Dr: Class implementation isn't working, posted all my source when I probably could've posted about 1/10th of this and still made sense, and would love to have someone tell me why it's not working and how bad I am.
The problem is that the compiler thinks that the slime declaration line is another type of predeclaration since greenSlime doesn't have a ctor with parameters.
You can fix it by not putting the parenthesis after slime.
// greenSlime slime();
greenSlime slime;
Here is the absolute best advice I can give regarding weird errors that you don't understand. Make a smaller example of the problem makes it easier to uncover what is actually wrong.
Here is what I wrote to test.
struct Foo {
Foo() {}
void bar() {}
};
int main(int argc, char ** argv) {
Foo foo;
foo.bar();
return 0;
}
Others have pointed out problems in terms of why your code doesn't work. I'll make a recommendation about program design.
When explaining inheritance, tutorials and programming classes frequently use toy examples that are very similar to your code. These examples show what inheritance is, but really aren't very good at showing what inheritance is useful for.
I wouldn't use inheritance in this case. I think a better design is to have a class that represents the mob type and holds all the data that is static for all that mob of that type, such as the mob name, starting/max HP, attack types, etc. And then have another class where each instance represents a specific mob and holds data that changes for that mob, such as current hp.
class Mob_type {
string name;
int max_hp;
vector<shared_ptr<Attack_type>> attacks;
public:
Mob_type(string name,int max_hp,vector<shared_ptr<Attack_type>> attacks)
: name(name),max_hp(max_hp),attacks(attacks) {}
int get_max_hp() const { return max_hp; }
};
class Mob {
Mob_type const &type;
int hp;
public:
Mob(Mob_type const &type) : type(type), hp(type.get_max_hp()) {}
Mob_type const &get_type() const { return type; }
int get_hp() const { return hp; }
};
void print_health(Mob const &m) {
cout << m.get_hp() << '/' << m.get_type().get_max_hp() << '\n';
}
int main() {
vector<shared_ptr<Attack_type>> attacks; // ...
Mob_type green_slime("Green Slime",50,attacks);
Mob green_slime_A(green_slime), green_slime_B(green_slime);
fight(green_slime_A,green_slime_B);
cout << "A: ";
print_health(green_slime_A);
cout << "B: ";
print_health(green_slime_B);
}
This way you can have a data file that contains the mob types and all you have to do to add a type is to update the data file.
class greenSlime: private baseMob{
should be:
class greenSlime: public baseMob{
Since the class that you're inheriting from is private, you can't see any of the inherited methods.
Also, what Tom Kerr said, you don't want the parentheses after you declare your object. Basically, if you don't want any parameters, don't use the parentheses when making an object.
Also, very next thing I imagine you'll encounter: you almost never want private inheritance, at least not unless you know you really want it. I'm guessing you meant for the class declaration of greenSlime to be
class greenSlime: public baseMob
First of all if you make private inheritance you won't be able to access any of base class' functions. Public inheritance allows you access base class' public and protected functions and members.
Second if you want to make a pointer of greenSlime class, you must do:
//greenSlime() with parentheses
greenSlime *slime = new greenSlime();
But if you want to make an object of greenSlime with non parameter constructor (default constructor) you must do:
//without parentheses
greenSlime slime;