Inheritance Robot Race that doesn't update array - c++

I am working on a program that is suppose to have 3 different Robots racing on a track. The track is suppose to be 100 in length. I have just learned inheritance and still trying to understand how to connect data members from one .h to another. When I run my program, nothing happens when I call any of my Robots. I will show one of them as an example. Can you explain how to make their movements update the race 2D array?
robotRace.h
#ifndef ROBOTRACE_H
#define ROBOTRACE_H
using namespace std;
class robotRace {
public:
robotRace (); //constructor
static const int rows = 5;
static const int columns = 100;
protected:
int race[rows][columns]; //initial base for race floor
};// end superclass robotRace that should do no movement
#endif
robotRace.cpp
#include <iostream>
#include "robotRace.h"
using namespace std;
robotRace :: robotRace() {
for (int i = 0; i < rows; i++)
for (int j= 0; j<columns; j++)
race[i][j] = ' ';
}//end constructor
This is one of the Robots and their functions to update array. Not sure how to make it work.
FunctionRobot.h
#ifndef FUNCTIONROBOT_H
#define FUNCTIONROBOT_H
#include "robotRace.h"
using namespace std;
class FunctionRobot : public robotRace{
public:
FunctionRobot();
int position(int);
void print();
protected:
};
#endif
FunctionRobot.cpp
#include <iostream>
#include "FunctionRobot.h"
#include <cmath>
using namespace std;
FunctionRobot :: FunctionRobot (): robotRace() {
int initPos =0;
race[initPos][0] = '*';
cout <<"Initial position of Function Robot is at begin of race."<<endl;
}
int FunctionRobot :: position(int place=0){
// log with a base 2 needs to be divided by the "x"
// below is the Robots formula to determine each of their movements
double x = ( 2 * (log(place)/log(2)));
return (int) x;
}
void FunctionRobot :: print(){
for (int i;i=0; i<100; i++)
for (int j;j=0; j<1; j++)
race[position()][j];
}
this is my main file as requested. This is basic format. I am hoping to make the while loop more practical so that the user doesn't have to keep entering 1.
There is also no error coming from my code. It runs just shows nothing.
main.cpp
#include <iostream>
#include "robotRace.h"
#include "FunctionRobot.h"
using namespace std;
int main() {
int userInput;
cout << "Welcome to the Robot Race of the year!" << endl;
cout << "For our contestants we have the amazing three!" << endl;
cout << "The contestants are Robots F, R and U" << endl;
cout << "Let the games begin! \n\n";
cout << "Enter 1 to begin. " << endl;
cin >> userInput;
FunctionRobot functionObj;
//functionObj.position();
//functionObj.print();
cout << "Ready... Set... Go!!" << endl;
while (userInput == 1) {
functionObj.position(4);
functionObj.print();
} //end while
return 0;
}

Your print() goes out of bounds:
void FunctionRobot :: print(){
for (int i; i<100; i++)
for (int j; j<1; j++)
race[position()][j];
}
j is not initialized. You could try int j = 0 for a start. Similar for i.
Moreover you know that this function is named PRINT but doesn't PRINT ANYTHING, actually it doesn't do anything but calling position().
int FunctionRobot :: position(int place=0){
// log with a base 2 needs to be divided by the "x"
// below is the Robots formula to determine each of their movements
double x = ( 2 * (log(place)/log(2))); <-------- now x is a double
return (int) x; <-------- now x is an integer, are you sure about that?
}
Loss of precision happens here. Let's say that x is assigned a value of 3.14. Then you cast it (the cast would happen automatically since the return type of the function is also an int) into an integer, thus it will be converted to 3, thus you loss precision.
About main.cpp
You call the user to input 1 and then you have:
while (userInput == 1) {
functionObj.position(4);
functionObj.print();
} //end while
but userInput is not going to be modified, thus you are running into a non-ending loop.

Related

C++ Class of array of objects

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
}
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);
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 . . .

trying to simulate a soocer game shootout using arrays

I have to create a game of 5 rounds simulating a soccer shootout using a 2x3 array that represents the goal. The computer randomly picks 3 places to block and the user chooses one place to shoot. If the user chooses a coordinate that is not blocked then its a goal. Two functions are needed, one where the computer picks 3 random places to block and the other function is prints out the goal every round. If the user scores 3 times then they win, otherwise they lose.
The output should look like this(B=Blocked, G=Goal, "-" = empty space):
B - B
B - G
Ive been stuck on my code and have gotten an error that I just cant seem to fix within both functions
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <ctime>
using namespace std;
void computerPick(char soccer[]);
void shot(char shooter[]);
int main()
{
int userInputX;
int userInputY;
srand(time(NULL));
char soccer[2][3];
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
soccer[i][j]='-';
}
}
cout<<"Pick a X coordinate to shoot at: "<<endl;
cin>>userInputX;
cout<<"Pick a Y coordinate to shoot at: "<<endl;
cin>>userInputY;
computerPick(soccer);
shot(soccer,userInputY,userInputX);
}
void computerPick(char soccer[])
{
int x = rand()%3;
int y = rand()%2;
soccer[x][y]='B';
}
void shot(char shooter[], int userInputY, int userInputX)
{
int score=0;
if(shooter[userInputX][userInputY]!='B')
cout<<"shot is good"<<endl;
else
cout<<"shot is blocked"<<endl;
}
You have to use correct types for arguments and have to match the prototype declaration and definition of functions.
This code compiles:
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <ctime>
using namespace std;
void computerPick(char soccer[][3]);
void shot(char shooter[][3], int userInputY, int userInputX);
int main()
{
int userInputX;
int userInputY;
srand(time(NULL));
char soccer[2][3];
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
soccer[i][j]='-';
}
}
cout<<"Pick a X coordinate to shoot at: "<<endl;
cin>>userInputX;
cout<<"Pick a Y coordinate to shoot at: "<<endl;
cin>>userInputY;
computerPick(soccer);
shot(soccer,userInputY,userInputX);
}
void computerPick(char soccer[][3])
{
int x = rand()%3;
int y = rand()%2;
soccer[x][y]='B';
}
void shot(char shooter[][3], int userInputY, int userInputX)
{
int score=0;
if(shooter[userInputX][userInputY]!='B')
cout<<"shot is good"<<endl;
else
cout<<"shot is blocked"<<endl;
}
You might want to look at these parts again:
char soccer[2][3];
and
int x = rand()%3;
int y = rand()%2;
soccer[x][y]='B';
Also note that booleans would be clearer in your two dimensional array instead of chars of 'B' or 'G'.
Also when using multidimensional arrays as parameters, you can pass them as
int foo(int (*array)[5][10])
Which means that you are passing a pointer to an array of fixed size 5-10

'fArray' was not declared in this scope

Hello I'm having this issue with my C++ problem I'm working on.
Here is the code
Cell.h
#ifndef CELL_H
#define CELL_H
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Cell
{
private:
int level;
int row;
int column;
//declares a variable called ptrFunction_array which is an array of 3 function pointers.
typedef void (*ptrFunction[])(void);
static void function1()
{
cout << "I'm function 1";
}
static void function2()
{
cout << "I'm function 2";
}
static void function3()
{
cout << "I'm function 3";
}
public:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
ptrFunction = new *fArray[3];
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
}
virtual ~Cell();
void tick()
{
int randomNumber = rand() % 3;
cout << "Cell(" << level << ", " << row << ", " << column << ") ";
fArray[randomNumber];
}
};
#endif // CELL_H
Main.cpp
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include "Cell.h"
using namespace std;
Cell ****myArray;
int main()
{
int level = 0;
int row = 0;
int column = 0;
char userInput = 'y';
srand (time(NULL));
do
{
cout << "Please input the amount of levels: ";
cin >> level;
cout << "Please input the amount of rows: ";
cin >> row;
cout << "Please input the amount of columns: ";
cin >> column;
cout << endl;
myArray = new Cell *** [level];
// Set random number to the elements of the array
for (int currentLevel = 0; currentLevel < level; currentLevel++)
{
myArray [currentLevel] = new Cell ** [row];
for (int currentRow = 0; currentRow < row; currentRow++)
{
myArray [currentLevel][currentRow] = new Cell * [column];
for (int currentColumn = 0; currentColumn < column; currentColumn++)
{
myArray [currentLevel][currentRow][currentColumn] = new Cell (currentLevel, currentRow, currentColumn);
myArray [currentLevel][currentRow][currentColumn] -> tick();
cout << " ";
}
cout << endl;
}
cout << endl;
}
cout << "Do you want to try again? (y / n) ";
cin >> userInput;
cout << endl;
if ((userInput == 'y') || (userInput == 'Y'))
{
for (int currentLevel = 0; currentLevel < level; currentLevel++)
{
for (int currentRow = 0; currentRow < row; currentRow++)
{
for (int currentColumn = 0; currentColumn < column; currentColumn++)
{
delete[] myArray[currentLevel][currentRow][currentColumn];
}
delete[] myArray[currentLevel][currentRow];
}
delete[] myArray[currentLevel];
}
delete[] myArray;
myArray = NULL;
}
}while (userInput != 'n');
return 0;
}
I notice that my fArray isn't inside the scope. the Line ptrFunction = new *fArray[3]; is where my error is. I've recently started learning C++ so I'm in the process of trying to understand why my typedef void (*ptrFunction[])(void); isn't correctly initializing the fArrayfor my program. The goal of my program is to be able to create a 3 dimensional array and be able to point to the Cell Objects and be able to track the location x,y,z.
Why does an error like this happen?
I'm going to ignore the four star pointer for now and stick to what's giving OP the most immediate grief.
A quick walk-through:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
Not bad to here. But...
ptrFunction = new *fArray[3];
This says assign to the variable ptrFunction, which must already exist and doesn't, a newly allocated array of 3 fArrays. The problem here is ptrFunction has been defined as a type, not a variable. fArray is not a type.
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
Use fArray as a variable, making what's gone wrong here somewhat clear.
}
Cell needs to look a bit more like this, but not exactly. More on that later.
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
ptrFunction * fArray = new ptrFunction[3];
Now fArray is a variable that points to one or more objects of type ptrFunction (but the definition of ptrFunction is somewhat broken), and points fArray at three ptrFunctions. Technically it points at the first of three ptrFunctions.
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
}
Now we have an fArray, but it is a local variable and it only exists between the curly braces of Cell's constructor. When the constructor exists, the pointer goes away. The memory allocated does not and is lost. Without fArray pointing to it, you can't easily find it to use or delete it. fArray needs wider scope so that A) the memory isn't lost, and B) so that tick and other members of Cell can see it.
class Cell
{
private:
ptrFunction * fArray;
int level;
and in the constructor:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
fArray = new ptrFunction[3];
That fixes the can't find fArray.
My recommendation is to get one Cell working and then take a stab at getting a 1 dimensional array of Cells working. When you have one dimension, then try two. You might find that's all you need.
Edit
Forgot to mention this: Function pointers to members functions are an absolute expletive deleted to get right. Here is a page on common pitfalls and how to avoid them.
And here is how we avoid this smurf in the here and now of Modern C++: std::bind and std::function. The tutorials at the bottom of the linked document pages probably describe how to use them for simple cases better than I can.

Why am i getting out-of-range error?

I can't seem to find where my issue is. Its a three file program with aDie class in one file, aHistogram class in another file, and the main.cpp file. It is supposed to print a histogram constructed with X's to show how many times the die landed on each of the six faces. I cant move forward because of the vector error... There may be other issues with the program that i haven't worked out yet, but I just want to know about the vector error. Thank you.
main.cpp:
#include <iostream>
#include <stdlib.h> //srand and rand
#include <time.h> //Time
#include <vector>
#include <algorithm>
#include "aHistogram.h"
#include "aDie.h"
using namespace std;
int main()
{
srand (time(NULL));
int numRolls;
const int maxLengthOfLine = 50;
cout << "How many rolls? " << endl;
cin >> numRolls;
aDie fairDie;
aHistogram fairHistogram;
//For Loop rolls the die and updates the histogram vector ~~binHistogram.
for(int i = 0; i < numRolls; i++)
{
int face = fairDie.roll();
fairHistogram.update(face);
}
cout << "*******************" << endl;
cout << "*****Histogram*****" << endl;
cout << "*******************" << endl;
fairHistogram.display(maxLengthOfLine);
}
aDie.h:
#ifndef ADIE_H_INCLUDED
#define ADIE_H_INCLUDED
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
/********************************************/
/*******Definition of aDie class*************/
/********************************************/
class aDie
{
public:
int roll(); //return an integer between 1 and 6 to represent what face appears when the die is rolled.
aDie(); //Default constructor
~aDie(); //Destructor
private:
int numFaces = 6;
};
int aDie::roll()
{
return ((rand() % numFaces) + 1); //returns a random number between 1 and 6
}
aDie::aDie()
{
cout << "Dice Roll...." << endl;
return;
}
aDie::~aDie()
{
return;
}
#endif // ADIE_H_INCLUDED
aHistogram.h:
#ifndef AHISTOGRAM_H_INCLUDED
#define AHISTOGRAM_H_INCLUDED
#include <algorithm>
#include <stdlib.h>
#include <vector>
using namespace std;
/********************************************/
/*******Definition of aHistogram class*******/
/********************************************/
class aHistogram
{
public:
void update(int face);
void display(int maxLengthOfLine);
int Count(int face);
void clear();
aHistogram(); //Constructor
~aHistogram(); //Destructor
private:
vector<int> binHistogram;
const int numFaces = 6;
int totalRolls;
int largeBin = 0;
double xScale;
};
//Adds a count to each face every time the die lands on said face.
void aHistogram::update(int face)
{
binHistogram.at(face) += 1;
return;
}
//Displays the histogram with X's
//maxLengthOfLine represents the maximum number of x’s to be printed for the largest bin count.
void aHistogram::display(int maxLengthOfLine)
{
xScale = maxLengthOfLine / largeBin;
for(int i = 1; i <= 6; i++)
{
cout << i << " : " << Count(i) << " : ";
int numXs = xScale * binHistogram.at(i);
for(int j = 0; j < numXs; j++)
{
cout << "X";
}
}
}
//To be called AFTER aHistogram::update
//Returns a count of how many times for each face of the die
int aHistogram::Count(int face)
{
//For Loop determines the largest bin count
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
//
return binHistogram.at(face);
}
void aHistogram::clear()
{
binHistogram.clear();
return;
}
//Defines the DEFAULT CONSTRUCTOR. Sets all elements of the histogram to zero.
aHistogram::aHistogram()
{
return;
}
//Defines the DESTRUCTOR. Clears vector after use.
aHistogram::~aHistogram()
{
binHistogram.clear(); //Clears vector
return;
}
#endif // AHISTOGRAM_H_INCLUDED
I didnt find the place where you initialize the histogram this might be the problem. But even if you fix that, you will hit two other bugs:
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
you are accessing elements 1....6 when probably it should be 0...5. Same problem in the line where you have
largeBin = binHistogram.at(i);
which is most likely the line that causes the error (the one above wont be so nice to tell you what is the problem but just crash your program).
You never change the size of the vector in the aHistogram class, which means its size will always zero. Any index will be out of bounds.
For things like histograms I would actually recommend you to use std::unorderd_map instead of std::vector, with the "face" being the key and the count being the data. Then you could do e.g.
binHistogramMap[face] += 1;
without worrying about the element for face not existing (it will be created and initialized to zero if the entry doesn't exist).

Class Rolling Dice program

I need to write C program for rolling dice using class Dice. The main requirement is that I need to use this main, editing it:
int main()
{
Dice* ptrDice;
???
for (int i = 0; i < 5; i++)
{
???? // roll the 5 dice
???? // print the outcome
}
}
I just cannot get how to use pointers here. Can anyone help, pls?!
Here is my code but it's not working :(
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
class Dice{
public:
Dice();
int getNums();
void Roll();
private:
int nNums;
};
Dice::Dice(){
nNums=5;
}
int Dice::getNums()
{
return nNums;
}
void Dice::Roll()
{
nNums = rand()%6 + 1;
}
int main()
{
Dice* ptrDice = new Dice;
ptrDice -> getNums();
for (int i = 0; i < 5; i++)
{
getNums[i] = rand()%6 + 1; // roll the 5 dice
cout << "You rolled: ";
cout << ptrDice->getNums() << setw(4);
cout << endl; // print the outcome
}
}
My main trouble is to use that ptrDice and printing it in main function, I guess!
You're making this more complicated than it needs to be.
A simple Dice object needs no data members and only one member function. If you're using the rand() function, the constructor should seed the random number generator with srand(seed). The Roll() function should return the number rolled as an int. You don't need the getNums() function at all, which will only return 5 as your class is defined.
class Dice() {
public:
int roll() { return rand() % 6 + 1; }
};
...
int main() {
Dice* ptrDice = new Dice;
for (int i=0; i<5; i++) {
cout << "You rolled" << ptrDice->roll() << '\n';
}
delete ptrDice;
}
You could expand this class to simulate multiple dice with any number of sides. Then you could use integer data members to retain the number of dice and their number of sides.