I'm making a card game and I have a few classes.
I have a Hand class, a Player Class, a "Column" class (where the cards are placed on the screen after the hand) and I need each class to have access to the other classes' variables.
class Hand
{
private:
int **Hx,Hy;** //Hand X, Hand Y
int HAmount;//Amount of cards in Hand
int HOwner; //Player 1/2
int Limit; //Limit of cards in Hand
int HContents[8]; //Card Position in 54 card deck NOT card value.
bool Removed;
public:
Hand();
void Lim();
void Get_Card();
void Show();
void Set_Values(int y, int Own);
};
Then in another class I need to have access to some of the variables above.
void Card::show()
{
if((apply == true)
{
if((Track == true)&&(SelNum == TNum)&&(TOwner == COwner))
{
ScnPos = TAmount;
x = Tx;
y = Ty + ScnPos*10;
}
if((Hand == true)&&(**HOwner** == COwner))
{
x = **Hx** + ScnPos*45;
y = **Hy;**
}
apply_surface(x,y,Cards,Screen,&Clip[Pos]);
}
}
I've tried using class friendship and other methods but I can't make it work.
(obviously I have more variables which need this same treatment)
(ignore any errors in my code)
The errors in your code are the real problem here. there is no reason that a Card will access a Hand's private member. this is design error, and your other problems are just trying to tell you that.
Well, you should make getters and setters for your variables. E.g.:
class Test {
private: int a;
public: int GetA() {
return this->a;
}
void SetA(int a) {
this->a = a;
}
}
Related
I am new to OOP and I am probably misusing some terminologies here (in which case suggestion or edits are most welcome). I would like to know how to design classes so that under some pre-defined criteria, an update to a data member automatically triggers a change in some state in the overall object.
Let's consider the following pseudocode for a concrete but over-simplistic example. It is so simple that I don't need classes here but I hope it describes the type of problem.
class X {
private:
int x;
public:
void update_x(int);
};
class Y {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs() { xs.insert(X()); }
void change_an_element_in_xs(){ call X::update_x on some element in xs }
};
Is it possible to implement X::update_x as follows?
void X::update_x(int y)
{
x = y;
if (x >= 10) {
tell the instance of Y that contains this instance of X to
change max_xs_at_least_10 to true
}
}
In simple case, when you sure that only one object should be notified about the change, you can simply hold a reference to the desired Y object:
class Y;
class X {
private:
int x;
Y& _y;
public:
X(Y& y);
void update_x(int val);
bool operator<(const X& o) const {
// Objects has to be comparable to be used in std::set
return x < o.x;
}
};
class Y {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs() { xs.insert(X(*this)); }
void change_an_element_in_xs(){ /*call X::update_x on some element in xs*/ }
void some_x_changed(int val) {
if (val >= 10) {
max_xs_at_least_10 = true;
}
}
};
X::X(Y& y) : _y(y) {}
void X::update_x(int val)
{
x = val;
_y.some_x_changed(val);
}
Note, that X shouldn't use Y::max_xs_at_least_10 directly, because it violates Encapsulation OOP principle: Y should manage its state itself, X should only use Y public interface. That ensures, that changing internal Y logic won't cause changes in X.
In more sophisticated cases, for example, when it's possible that any other objects should be also notified about changing in X, it may be a good idea to use Observer design pattern.
Simple implementation may look like:
class XObserver
{
public:
virtual void x_updated(int new_x) = 0;
};
class X {
private:
int x;
std::vector<XObserver*> observers;
public:
void add_observer(XObserver* observer) {
observers.push_back(observer);
}
void update_x(int val) {
x = val;
for (auto observer : observers) {
observer->x_updated(val);
}
}
bool operator<(const X& o) const {
// Objects has to be comparable to be used in std::set
return x < o.x;
}
};
class Y : XObserver {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs()
{
X x;
x.add_observer(this);
xs.insert(x);
}
void x_updated(int new_x) override
{
if (new_x >= 10) {
max_xs_at_least_10 = true;
}
}
void change_an_element_in_xs()
{
//call X::update_x on some element in xs
}
};
The idea is simple: if any other object should be notified, it's class should be derived from Observer class and implement void x_updated(int) method.
After that you can register a new observer using X::register_observer(Observer*) method.
After changing state of X every registered observer will be notified.
Note, that you should be careful with Observers lifetime: if X will be updated after one of observers is destroyed, you will get a crash.
This code just shows an idea: you may want to add X::deregister_observer() method, or use smart pointers -- it's up to you, your needs and creativity.
Good luck!
// UPD: Also note, that I addressed a generic idea of notifiying other objects about change; If your code really looks like that -- X is changed only by calling Y::change_an_element_in_xs() it's a way simplier just to put your logic in this method.
Greetings C++ community !
I am new to C++ i have this code example :
class Player
{
public:
int pdamage;
int phealth;
/* ... other data members and some void member functions (getName etc.) */
};
class Ennemy
{
public:
int edamage;
int ehealth;
};
**/*here i would like to use current objects parameters for calculation and return to current player instance(current player object) the health value.*/**
int playerHit(this.Player.damage,this.Enemy.ehealth)
{
ehealth = this.Ennemy.ehealth - this.Player.damage;
return ehealth;
};
int ennemyHit(this.Player.phealth,this.Enemy.edamage)
{
phealth = this.Player.phealth - this.Ennemy.edamage ;
return ehealth;
};
int main()
{
/*....*/
return 0;
}
Returning to the post question:
How i use current object parameters in a function for calculations?
/*Since i am new to stackoverflow and C++ Thanks for all advises and suggestions and critics ! */
In C++ you would pass the calles either as pointer or reference
int playerHit(const Player& player, const Ennemy& ennemy)
{
return ennemy.ehealth - player.pdamage;
};
I'm making a simple game of catching the fruit, but I've been having troubles with the collision logic and/or using the variables from the classes.
class row
{
public:
int x,y;
void setpoint (int xi, int yi)
{
x=xi;
y=yi;
}
float DownSpeed = 5;
void down () {
y = y+DownSpeed;
if (y==1000) {
y=0;
}
}
};
class fruit:public row
{
public:
void draw()
{
setcolor(11);
circle(x,y,20);
}
};
Then I have other classes to create the catcher, like so:
class catcher
{
protected:
float moveSpeed = 5;
public:
float catchX, catchY;
void setpoint (int xi, int yi)
{
catchX=xi;
catchY=yi;
}
void MoveLeft () {
catchX = catchX - moveSpeed;}
void MoveRight () {
catchX = catchX + moveSpeed;}
};
class character:public catcher
{
public:
void draw()
{
setcolor(15);
circle(catchX,catchY,50);
}
};
How do I call the variables of both circles into creating a collision function? I'm sorry if the codes are messy and ineffective, I'm just starting out and I'm stuck. Thanks!
Since both sets of variables are in the public part of the class, you should be able to create a function independent of either class and should be able to access the variables as long as they are declared.
void CheckCollision(float x, float y, float catchX, float catchY)
{
If(y =< catchY + 5)
{
//y resets
}
}
You’d want to check if it’s within a certain x range too though. I hope this solves your problem.
Since all the functions and variables are public. return the values of x, catchX from the functions modifying them. use the draw functions after you have the modified values.
for example modify your down function like this
int down()
{
y = y+DownSpeed;
if (y==1000)
{
y=0;
}
return y;
}
Modify the other function like wise and you will end up having your x,y and catchX, catchY values. create you collison function with these values.
This is the header:
class Board {
public:
friend class Game;
Board() = default;
Board(int n) : N(n) { }
Board& SetType(int, int, char);
void GetType(int, int);
Board& CreateEmptyBoard();
void BoardDisplay();
private:
int N = 0;// dimension
char Maze[15][15];
const static int MaxSize = 15;
};
class Game {
public:
Game() = default;
Game(int x, int y) : PosX(x), PosY(y) { }
void BuildGame();
void GameDisplay();
void MoveUp();
void MoveDown();
void MoveLeft();
void MoveRight();
private:
int PosX = 0;
int PosY = 0;
};
void Game::BuildGame() {
srand(time(NULL));
for (int i = 0; i < Board::N; i++) {
for (int j = 0; j < Board::N; j++) {
if (i == rand() % (Board::N) && j == rand() % (Board::N))
Board::Board& SetType(i, j, 'W');
}
}
}
In class Game's member function void BuildGame,I want to call member functionBoard& SetType(int,int,char) in class Board.I define this function in a header file and not show here. Then I build the project, I got invalid use of non-static data member 'Board::N' and 'SetType' was not declared in this scope. Like this
Where I wrong? I can't find it.
The compiler is letting you know that you are using an instance variable as a static. A static variable is associated with an entire class and not a single object, so it is called through the class name and not an object of the class. but it would need to be marked as static like so
class Board
{
public:
static Board& setType(int, int, char);
...
private:
static int N;
...
}
my instinct however tells me that you want to use it at an instance level, so you would write your void Game::buildGame() method using a Board that it creates (possibly making it an attribute of the Game class:
void Game::BuildGame() {
//make your board here. alternatively make an instance of the game
Board myBoard();
srand(time(NULL));
//in the following, use myBoard as the instance of a board.
for (int i = 0; i < myBoard.N; i++) {
for (int j = 0; j < myBoard.N; j++) {
if (i == rand() % (myBoard.N) && j == rand() % (Board::N))
myBoard.setType(i, j, 'W');
}
}
}
And a Board class that looks something like this. You will probably want your setType method to modify the instance and return void instead of returning another board reference.
class Board
{
public:
//this one will change this particular Board instance.
void setType(int, int, char);
//this one may make sense to be static if it is a factory method
//but why not use a constructor instead?
static Board& createEmptyBoard();
//maybe you meant something to reset the board to empty state.
void resetBoardToEmpty();
...
private:
int N;
...
}
while you're at it you might make it a struct (which has members public by default) as it seems to be a "hidden" holder class for the game, and this would alleviate the need to use a friend class (these are to be used judiciously as they can get messy really fast). using a struct would also allow you to make a ChessGame class that reuses the Board struct.
N isn't a static member of class Board, hence you'll need an instance of board to access it.
Your Game class actually needs to have a Board member variable to achieve that above mentioned instance.
I have my main.cpp like this:
#include <iostream>
#include "curve1.h"
#include "curve2.h"
using namespace std;
int main()
{
Curve1 curve1Obj;
Curve2 curve2Obj;
curve1Obj.enterScores();
curve1Obj.calcAverage();
curve1Obj.output();
curve1Obj.curve();
curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());
curve2Obj.curve();
return 0;
}
Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.
My base class header score.h looks like this:
#ifndef SCORE_H
#define SCORE_H
class Score
{
private:
int *ipScore;
float fAverage;
int iSize;
public:
Score(
void enterScores();
void calcAverage();
void output();
void output(float, int*);
void setSize();
int getSize();
void setScore();
int *getScore();
float getAverage();
};
#endif
You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously).
.....
The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage.
.....
How can I cause it to return the old values that are set in curve1.cpp?
Here is my curve2.cpp
#include <iostream>
#include "curve2.h"
using namespace std;
void Curve2::curve()
{
cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}
Can I use a function to simply put values from old to new variables? If yes then how?
Well, basically your problem can't be easily solved the way it is.
Like you said:
1 - Don't use constructors of any type.
2 - Don't use vectors.
3 - Using dynamic new and delete etc. etc.
Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.
There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.
If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).
Better yet... use a std::vector of int for your scores.
Why are people still using new and delete? What the hell are they teaching in schools?
What I think you want is this:
#include <vector>
class Score {
public:
Score()
: _scores()
, _average(0)
{ }
void calcAverage() {
double total = 0;
if(auto s = _scores.size() > 0) {
for (const auto& v : _scores)
total += v;
total /= s;
}
_average = total;
}
virtual void curve() = 0;
protected:
// one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
const std::vector<double>& scores() const {
return _scores;
}
// or
std::vector<double> copyScores() const {
return _scores;
}
private:
// use doubles since you'll be doing floating point arithmetic
std::vector<double> _scores;
double _average;
};
class Curve1 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores() or copyScores() if you want to make changes to the array
}
};
class Curve2 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores();
}
};
You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.
Now see this example:
#include <iostream>
class Base {
int x;
};
class A : public Base {
int a;
public:
void set_a(int arg) {
a = arg;
}
int get_a() {
return a;
}
};
class B : public Base {
int b;
public:
void set_b(int arg) {
b = arg;
}
int get_b() {
return b;
}
};
int main() {
A a_object;
a_object.set_a(4);
B b_object;
b_object.set_b(a_object.get_a());
std::cout << "a of a_object = " << a_object.get_a() << "\n";
std::cout << "b of b_object = " << b_object.get_b() << "\n";
return 0;
}
class A, has as members x and a. Class B has as members x and b.
When I create an instance of class A, I will two data members created internally, x and a.
When I create an instance of class A, I will two data members created internally, x and b.
But, the first x and the second are DIFFERENT. They are a different cell in the memory!
something like this:
class Score {
public:
Score()
: _scores(0)
, _size(0)
, _average(0)
{ }
// copy constructor
Score(const Score& rhs)
: _scores( new double[rhs._size] )
, _size(rhs._size)
, _average(rhs._average)
{
if (_size) {
for(int i = 0 ; i < _size ; ++i) {
_scores[i] = rhs._scores[i];
}
}
}
// ... and if copy constructor then always a copy operator
Score& operator=(const Score& rhs) {
// assignment in terms of copy constructor - don't repeat yourself
Score tmp(rhs);
swap(tmp);
return *this;
}
// pre c++11 we make our own swap.
// post c++11 we would make non-throwing move constructor and move-assignment operator
void swap(Score& rhs) {
// std::swap is guaranteed not to throw
std::swap(_scores, rhs._scores);
std::swap(_size, rhs._size);
std::swap(_average, rhs._average);
}
~Score()
{
delete[] _scores;
}
void calcAverage() {
double total = 0;
if(_size > 0) {
for (int i = 0 ; i < _size ; ++i)
total += _scores[i];
total /= _size;
}
_average = total;
}
virtual void curve() {};
private:
// use doubles since you'll be doing floating point arithmetic
double * _scores;
int _size;
double _average;
};
// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator