How to uses two member functions sequentially on a base class pointer? - c++

I am having some trouble using two memeber functions on a base class pointer. I have the following code;
cout << "Please input the translation vector. (x value ' ' y value)" << endl;
cin >> Xtrans >> Ytrans;
cout << endl;
new_shape = Trans + user_input; // adds Tranaslated to the key
for(it = shape_map.begin(); it != shape_map.end(); ++it){// loops over map (it is defined earlier)
cout << endl;
if( it->first == user_input){
cout << "ID " << new_shape << " = " << endl; // ouput the key witch also id's the shape
it->second->translate(matrix(Xtrans, Ytrans))->printshape(); //<-this one
}
}
The purpose of the code is to translate a shape (I have different classes for several types that are derived from an abstract base class called polygon) and then print the new shape. I have a translate and a print function that work separately but when I combine them the code runs but crashes when it gets to the marked line.
When I debug the code a line in my translate function is highlighted.
Is this the right way to combine two functions? Should I have some intermediate step?
MORE INFO
shape_map is <string, polygon*>
when I do,it->second->printshape(); or it->second->translate(matrix(Xtrans, Ytrans); it doesn't crash and prints the original shape but I don't know if translate works.

Related

Variable vector size in all class instantiations in c++

I'm trying to code a chess game for usage in terminal. A game consists of a Board class, consisting of Piece classes. For each piece I want to determine the allowed moves if no other pieces where on the board and put this in a vector<pair<int,int>> (a1 = 1,1).
You can image that for a Queen you have more allowed moves than for a pawn. Ideally I would like my Piece to have a variable size vector so it is just filled with moves for that specific Piece.
This is my Piece instantiation:
class Piece{
private:
int row;
int col;
// number of moves made by the piece
int moveCnt;
// white = 1, black = -1
int color;
// 'p', 'n', 'b', 'r', 'q', 'k'
char type;
// permissable moves for the piece
vector<pair<int,int>> permMoves;
// allowable moves for the piece, taking the entire board into account (1. Ke2 is not allowed but permissable)
vector<pair<int,int>> allowedMoves;
and then for the allowed permissable moves I do this:
void Piece::computePermMoveS(){
vector<pair<int,int>> emptyPermMoves {{0,0}};
permMoves.swap(emptyPermMoves);
// PAWN
if (getType() == 'p'){
// add move to one row ahead
pair<int,int> add_pair (getCol(),getRow()+1*getColor());
permMoves.push_back(add_pair);
if (getMoveCnt() == 0){
// add move to two rows ahead
pair<int,int> add_pair (getCol(),getRow()+2*getColor());
permMoves.push_back(add_pair);
}
cout << "new pawn at " << getCol() << ", " << getRow() << endl;
for (int i=0; i<sizeof(permMoves)/sizeof(permMoves[0]); i++){
cout << permMoves[i].first << ", " << permMoves[i].second << endl;
}
}
The last printing statement is for debugging purposes. If I compile and run this, I get that each piece (pawn, rook) has three permissible moves (as a pawn, which is first in the loop has -> 0 0, a3, a4).
Could anyone tell me how to fix this? I tried reserving 21 moves (the most possible) with
Piece(){
permMoves.reserve(21);
allowedMoves.reserve(21);
}
but this is not the solution I want and I don't get this working either. So I would really like to use the original approach of each piece having their unique allowed moves.
for (int i=0; i<sizeof(permMoves)/sizeof(permMoves[0]); i++)
This line is incorrect. The number of entries in a std::vector is given by the size() member function:
for (size_t i=0; i<permMoves.size(); i++){
cout << permMoves[i].first << ", " << permMoves[i].second << endl;
}
What you are doing is assuming that std::vector works the same as an array, but that is not true.
A much easier way to perform the loop is to use a ranged-based for loop instead:
for (auto& p : permMoves)
cout << p.first << ", " << p.second << endl;

(C++)1 dimensional battleship game help? advice for improvement

Unfortunately I do not have the Instructor to aid me with this assignment over the weekend and I am stuck. I'm just learning C++ and I've taken a Logic and Design class for Programming but like I said I'm very new to C++. I'm having a hard time catching up to the rest of the students.
I'd like if someone could list improvements and maybe clarify if I've done anything wrong in comparison to the assignment statement. I do really appreciate the help!
My code is repetitive and I'm sure I could go another way into displaying the array values without all that code. An error also pops up after use of the application that says:
"Run-Time Check Failure #2 - Stack around the variable 'enemy' was corrupted.
If there is a handler for this exception, the program may be safely continued."
The assignment is:
"Create a Battleship struct containing 5 one-dimensional integer coordinates representing its location within a region (of any size). Instantiate 2 copies of the struct and have the user enter a single coordinate for each Battleship. Design your code to take this single coordinate and use it to populate the remaining 4 coordinates for each ship. Do this for both ship structs. Then, have your code calculate the numeric distance between the 2 ships based on their respective coordinates. Finally, display the resulting distance to the user with an English language sentence."
My code as for right now is :
#include <iostream>
#include <string>
using namespace std;
struct Ship
{
int x[5];
int y[5];
};
int main()
{
Ship good;
Ship enemy;
good.x[0] = 0;
enemy.y[0] = 0;
cout << "Enter a coordinate (out of 100) for good ship: "<< endl;
cin >> good.x[0];
good.x[1] = good.x[0] + 1;
good.x[2] = good.x[1] + 1;
good.x[3] = good.x[2] + 1;
good.x[4] = good.x[3] + 1;
cout << "Good ship coordinates:" << endl;
cout << good.x[0]<< "*" << endl;
cout << good.x[1]<< endl;
cout << good.x[2]<< endl;
cout << good.x[3]<< endl;
cout << good.x[4]<< endl;
cout << "Enter a coordinate (out of 100) for enemy ship: "<< endl;
cin >> enemy.y[0];
enemy.y[1] = enemy.y[0] + 1;
enemy.y[2] = enemy.y[1] + 1;
enemy.y[3] = enemy.y[2] + 1;
enemy.y[4] = enemy.y[3] + 1;
cout << "enemy ship coordinates:" << endl;
cout << enemy.y[0]<< "*" << endl;
cout << enemy.y[1]<< endl;
cout << enemy.y[2]<< endl;
cout << enemy.y[3]<< endl;
cout << enemy.y[4]<< endl;
int distance=0;
distance = good.x[1] - enemy.y[1];
cout << "The distance between good ship and enemy ship is: " << distance << endl;
system("pause");
return 0;
}
The error probably comes from having only 4 coordinates in each struct, not 5. When you declare an array with int x[4];, it will only have 4 elements, namely x[0] to x[3].
There are a number of other problems:
You do not need two structs for two ships. Use just one. That's the whole point of structs/classes: to represents classes of objects. Use only one struct (named e.g. Ship) and declare both your ships good and enemy to have that type.
Don't be afraid of both the enemy ship and the good ship having x coordinates. The compiler and the computer won't get confused at that, and neither should you.
Learn to use loops. Even if you get confused at first, remember that loops are one of the most (if not the most) important tools at a programmers disposal. Think what would happen if you had 100 ships, each with 100 coordinates...
Remember, again, that the first element of an array is at index 0, not index 1. (And the last element is at index N-1.)
Calculating the distance is a little more complex than you've written. Can the distance between two objects ever be negative? What happens if the enemy ship's coordinate is greater than the friendly ship? What's the actual formula for one-dimensional distances?
Remove unused code. What's the use of that region variable? Have you used it anywhere?
UPDATE: (For anyone reading in the future, remember that OP has updated and modified their question and code, to the point that some of my point would not apply or would apply differently.)
Do you REALLY need both xs and ys in Ship?
Not sure if the use of system("PAUSE") is something your instructor taught, but that's definitely something you could improve on, too. Explained here
So starting with
Create a Battleship struct containing 5 one-dimensional integer coordinates representing its location within a region (of any size). Instantiate 2 copies of the struct and have the user enter a single coordinate for each Battleship
You need a single struct:
struct Ship
{
int x[5];
};
Now make 2 copies
int main()
{
Ship good;
Ship bad;
...
Then the rest looks good, it compiles and runs without any issues on my computer. You can add a function to populate the ship to reduce the number of code
Ship createShip(int startPos) {
Ship newShip;
newShip[0] = startPos;
// ... <- rest of your code that you have to populate
return newShip;
}
int main()
{
int pos;
cout << "Enter a coordinate (out of 100) for good ship: "<< endl;
cin >> pos;
Ship good = createShip(pos);
//...
//... <- Get pos of bad ship
Ship bad = createShip(pos);
}
Then you can also create a simular function that prints the location of the ship

I can't create proper std::vector in c++

I have to create a list of objects, so to keep it as smooth as possible I wanted to use std::vector instead of regular array of objects. However I don't exactly know how to use them properly. Here is sample code from my class in which I try to add objects to vecor and in 2nd method to display them.
private:
vector <Student> stud;
public:
void Student::dodaj(){
stud.push_back(Student(getNaz(), getImie(), getLeg(), getRok()));
}
void Student::wypisz(){
cout << "Lista osob:\n";
for (int i = 0; i < 1; i++)
{
cout << endl;
cout << "Nazwisko: " << stud[i].nazwisko << endl;
cout << "Imie: " << stud[i].imie << endl;
cout << "Numer indeksu.: " << stud[i].legitymacja << endl;
cout << "Rok studiow: " << stud[i].rok << endl;
}
And my main:
Student st("Kowalski", "Jan", 123455, 2);
Student test1("Nowak", "Jan", 123, 2);
st.dodaj();
test1.dodaj();
test1.wypisz();
However the output result is only one object for wich I use wypisz(print/display) method, in this case test1, that is displayed instead of two of them - st and test1. Any ideas how to fix that?
It appears that stud is a member of Student, which means that each Student object contains its own vector. When you call dodaj on a particular student, it just adds its own details to the vector it contains.
st.dodaj(); // Adds details of st to st's own vector
test1.dodaj(); // Adds details of test1 to test1's own vector
// Now we have one vector inside st containing a single element
// and one vector inside test1 containing a single element
test1.wypisz(); // Prints elements from test1's vector
Instead, your vector should be outside of your Student class (or at least static). One option would be to do this:
Student st("Kowalski", "Jan", 123455, 2);
Student test1("Nowak", "Jan", 123, 2);
std::vector<Student> stud;
std.push_back(st);
std.push_back(test1);
You may want to have another class (maybe School?) which contains this vector.

Do-while loop running twice when it should run only once (C++)

friends. I have a problem.
Problem: the computer must pick randomly one string out of an array of 36 strings. If by any chance it picks strings #34 or #35 (the two last ones), it has to draw two more random strings from the same array. I tried a do-while solution, and it "almost" works (see code below).
The randomization works fine - called srand inside main(). There is a forced "x2" draw (for testing reasons), so the computer draws two more strings. These two new random picks are NOT "x2", but still the loop kicks again - but just one more time! This time the computer picks two more "chits", which aren't "x2" either, so, as expected, it returns the "The chits have been drawn" sentence and the function is terminated. Why is the same code running twice with the same results but different if/else behavior? Thank you very much in advance.
string mortalityCalc ()
{
string mortalityChits[36] = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","-","-","-","-","x2","x2"};
int mortalityResult;
// mortalityResult = rand() %36;
mortalityResult = 35; // for testing only. Delete afterwards.
string drawnChit = mortalityChits[mortalityResult];
string drawnChit1;
string drawnChit2;
if (drawnChit != "-" && drawnChit != "x2")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'.";
return returnText;
}
else if (drawnChit == "-")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'. No senators died this year.";
return returnText;
}
do
{
cout << "The computer has drawn the 'x2' chit." << endl;
cout << "Two more chits will be drawn.\n" << endl;
mortalityResult = rand() %36;
drawnChit1 = mortalityChits[mortalityResult];
cout << "The first draw is the chit '" << drawnChit1 << "'. ";
mortalityResult = rand() %36;
drawnChit2 = mortalityChits[mortalityResult];
cout << "The second draw is the chit '" << drawnChit2 << "'." << endl;
} while (drawnChit1 == "x2" || drawnChit2 == "x2");
return "The mortality chits have been drawn. The corresponding senators are dead.";
}
UPDATE: Tried running this code isolated from the rest of the program and it behave as expected. So I guess it's important to post what comes before it:
cout << "If you are a lazy bastard, the computer can pick one senator randomly for you.\nAre you a lazy bastard? [y/n]" << endl;
string lazyBastard;
cin >> lazyBastard;
cout << endl;
if (lazyBastard == "y" || lazyBastard == "Y" || lazyBastard == "yes" || lazyBastard == "YES" || lazyBastard == "Yes")
{
mortalityCalc ();
cout << mortalityCalc () << endl;
cout << "Very well. Now, imminent wars become active (Only one of each match)." << endl;
cout << "Get ready for the next phase." << endl;
My guess, from reading some other questions here, is that somehow the cin is messing with the loop behavior, even though they are not related and there's no user input whatsoever in the loop's statements or conditions. Is that possible? If so, why and how to remedy it?
Thank you again.
In the first loop you are forcing an 'x2' so your are entering the do-while loop. The result of the two calls for 'rand())%36' is always 19 and a number between 30 and 34. The point is that the random number generator generates always the same sequence of numbers, if you don't give him a seed 'srand(...)'.
do {
// ...
cout << rand()%36;
// ...
} while( /*...*/ )
See http://ideone.com/zl8ggH
You have to create random numbers and your code does what you expect.
Finally! I thought it would be a stupid thing! I just realized that I called the mortalityCalc() function twice! That's why it was looping twice!
Thanks to all who tried to help!

My array takes random values despite user input

Excuse me again, I'm not any genius in Programming.
First of all, a summary: array input. Two 3D vectors...ha ha, let's use vectors to calculate MORE vectors. Anyway: dot product is just and plain ridiculous (nine numerals before decimals; I mean, seriously, I didn't ever thought that 1x8+7x5+4x2 could have NINE numerals). Cross product is...even worse.
I made the...uhm...how could I call it? Well, we call it "traza". I'll translate a definition ir order to get understood: a code's "traza" tell us the sequence of instructions of its execution, and how do the variables change after every line of code. You know, the table with variables and number marks referred to code lines where we look if the code is doing something unexpected. Getting to the point: it's everything fine as far as I could see.
Then, I made an unexpectedly "pseudotraza" with a print command and every value from the vectors. Just after input and just before te dot product (in a function). Guess what:
1) it's not my input, in either of them
2) they are not even the same values
3) first values are far away from my input, but the following ones at least were more logic (less difference to the input).
I learned this morning, 12 hours ago, to use arrays/vectors/whatever. I didn't ever have any need to set as 0 as default any value before its input. But it's the only thing I have known to do when things like this happened to me before.
(Someday any of you will be my Programming teacher, you are learning me more than himself...and excuse my awful grammar, English teaching in Spain is just "take some grammar rules and no more than 50 exercises in last High School year...it's all you need to pass the University Entrance Exam!")
#include <iostream>
using namespace std;
#include <stdlib.h>
const int N = 3;
typedef int Vector[N];
void introduirVector (Vector);
float producteEscalar (const Vector, const Vector); /*Input vector and dot product*/
int main (void)
{
Vector v1, v2;
float p_esc;
cout << "Introduim les dades del vector A: "; /* Input */
introduirVector (v1);
cout << "Introduim les dades del vector B: "; /* 2x Input combo */
introduirVector (v2);
cout << v1[0] << "\n" << v1[1] << "\n" << v1[2] << "\n" << v2[0] << "\n" << v2[1] << "\n" << v2[2] << endl; /* "Puseudotraza*/
p_esc= producteEscalar (v1, v2); /*Dot product*/
cout << "El producte escalar: " << p_esc; /*Dot product is...*/
system ("PAUSE");
return 0;
}
/*3x Input combo*/
void introduirVector (Vector)
{
int i;
Vector v;
for (i = 0; i < N; i++)
{
cin >> v[i];
}
return;
}
/* Dot product (why all the Vectors are set as constants but another after this is not set? It's the hint given by the teacher, my (not) beloved teacher...they gave us the main function and the other function's prototypes, but that's all) */
float producteEscalar (const Vector, const Vector)
{
float escalar;
Vector v1, v2;
/* Pseudotrazas for all*/
cout << v1[0] << "\n" << v1[1] << "\n" << v1[2] << "\n" << v2[0] << "\n" << v2[1] << "\n" << v2[2] << endl;
/* Dot product and all that */
escalar = (v1[0]*v2[0])+(v1[1]*v2[1])+(v1[2]*v2[2]);
return escalar;
}
The problem is this:
/*3x Input combo*/
void introduirVector (Vector)
{
int i;
Vector v;
This function takes a Vector as a parameter, but the Vector has no name so it cannot be used inside the function.
Then you declare a new, local Vector v. You read your user's input into this vector.
The function then ends, at which point the vector into which you read user input goes away.
Firstly, you should be using the parameter you were called with, not a local variable. But your second problem is that you are using pass by value. When you call this function, introduirVector (v1); it is not the "v1" you know and love from main that you are working with inside introduirVector, but a local copy of it that ceases to exist when your function returns.
What you need to do is make your function accept a pointer or a reference to the Vector it is being called with:
void introduirVector(Vector& v)
{
for (size_t i = 0; i < 3; ++i) {
cin >> v[i];
}
}
This does not fully solve all of the problems with your code, but it should get you moving forward.
I'm not seeing any input, which would be why you are not receiving any input.
Try using:
string inpt;
int a, b, c;
cin >> inpt;
a = atoi( inpt.c_str());
inpt = "";
cin >> inpt;
b = atoi( inpt.c_str());
// etc...
// Make your vector in this fashion, grabbing each integer separately then loading them
// into a vector