I am learning C and for that, I try to do a simple game project (having the same rows as columns and randomly distributed numbers from 0-blank to rows*rows-1. Target is for player to change numbers to be in numeric order by rows). Then 0-blank can be switched with any neighborhood horizontally or vertically) I code it through procedural code and it works fine. Now I am trying to redo it using object-oriented programming and classes.
For that reason I have 2 classes: Number - stores 2 integers with position x and y Deck - stores array of Numbers, practically s index of an array is the number itself and Number object just store position.
Deck deck (rows) creates sorted numbers with position and is checked by std::cout. Now I am trying to implement the shuffle function which will take randomly 2 Numbers and switch their positions (m_posX and m_posY) however trying the same principle to get m_posX is not correct and gives different large numbers compared to the creation of the position. getNumber just does not work as I intended. Practically I need to return m_posX and m_posY from exact Number object in array of m_game deck.
Any suggestions what am I doing wrong is welcome.
I have this code:
Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <array>
class Number
{
public:
// Number(int x, int y, int d);
setPosition (int x, int y);
setPosition (std::array <int,2> &xy ); // std::array [2]
setDigits (int d);
switchPosition (Number &c1, Number &c2);
std::array<int,2> getPosition (); // std::array [2]
int getPositionX ();
int getPositionY ();
int getDigits(); // int
protected:
int m_posX;
int m_posY;
int m_digits;
};
#endif // NUMBER_H
Number.cpp
Number::setPosition (int x, int y)
{
m_posX = x;
m_posY = y;
}
Number::setPosition (std::array <int,2> &xy )
{
m_posX = xy [0];
m_posY = xy [1];
}
Number::setDigits (int d)
{
m_digits=d;
}
Number::switchPosition (Number &c1, Number &c2)
{
int tempX {c1.m_posX};
int tempY {c1.m_posY};
c1.setPosition (c2.m_posX, c2.m_posY);
c2.setPosition (tempX, tempY);
}
std::array<int,2> Number::getPosition ()
{
static std::array <int,2> position;
position [0] = m_posX;
position [1] = m_posY;
return position;
}
int Number::getDigits ()
{
return m_digits;
}
int Number::getPositionX ()
{
return m_posX;
}
int Number::getPositionY ()
{
return m_posY;
}
deck.h
#ifndef DECK_H
#define DECK_H
#include "number.h"
class Deck
{
public:
Deck(int rows=3);
shuffleDeck (int rows);
Number & getNumber (int elementNumber);
protected:
std::array <Number,100> m_game;
};
#endif // DECK_H
deck.cpp
#include "deck.h"
#include "number.h"
#include "rnd.h"
#include <iostream>
Deck::Deck(int rows)
{
std::array <Number,100> m_game;
for (int j {0}; j < (rows); j)
{
for (int i {0}; i < (rows); i)
{
m_game[i j*rows].setPosition (i,j);
std::cout << "Number: " << (i j*rows) << '\t' << "Coordinates: " << '\t' << m_game[i j*rows].getPosition()[0] <<"," << m_game[i j*rows].getPosition()[1] << '\n' ;
};
};
std::cout << "fc Deck::Deck (int rows) Number10 posX: "<< m_game[10].getPosition()[0] << '\n';
std::cout << "fc Deck::Deck (int rows) Number10 posY: "<< m_game[10].getPosition()[1] << '\n';
}
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
game.cpp running code
#include "game.h"
#include "gmath.h"
#include "constant.h"
#include "graphics.h"
#include "number.h"
#include "deck.h"
#include <iostream>
int game (int rows)
{
int steps = 0;
Graphics piece {};
Deck deck(rows);
Number temp = deck.getNumber(10);
int tempI = temp.getPosition()[10];
//
// THIS DOES NOT WORK GETTING printed large number as 28573728
// [10] has m_posX set to 2 and m_posY set to 2 by Deck deck (rows);
//
std::cout << "CHECK game.h Number10 positionX: "<< tempI << '\n';
return steps; // for future counting score
}
CodePudding user response:
Try return by value and not by reference here:
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
like this:
Number Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
and of course do not forget to change the declaration:
Number getNumber (int elementNumber);
CodePudding user response:
The problem is very obvious.
In function game
you are writing int tempI = temp.getPosition()[10];
.
The function getPosition()
returns a std::array<int, 2>
. So, an array having 2 elements. One for x and one for y position. But with [10]
your are trying to access the element number 10 from your array (which has only 2 elements). This is an out of bounds error. So, It will read some random nonesense value and show that. This is undefined behaviour.
I am not sure, which compiler you have, but in debug mode, it should throw an exception and inform you about the problem.
Correct it to
int tempx = temp.getPosition()[0];
int temp< = temp.getPosition()[1];
You anyway need to enable ALL compiler warnings. It did it and got dozens of messages.
You define many functions without return type. You must use void
for this, e.g. function setPosition(int x, int y);
must be defined as void setPosition(int x, int y);
. And so on.
Also in constructor of Deck
you are redefining and with that overwriting the already defined array std::array <Number, 100> m_game;
in class deck. Delete the line in the constructor.
You may also consider to replace the std::array <int, 2>& xy
by a std::pair
or a simple struct
like:
struct Position{
int x;
int y;
};
That would be more intuitive . . .