Problem
When I load game and hit ship the game shows the ship is missed.This problem doesnt show up in normal game(without load).
I have serializaiotn for loading game board for user and opponent.
I think the error is about loading in serialzation vector but i have no idea how to do this.
vector is portected object in board class.
Implementation of serialzation
ostream &operator<<(ostream &out, const Board &b) {
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
out << b.board[row][col]<< ' ';
}
out << '\n';
}
out << '\n';
return out;
}
istream & operator>>(istream & in, Board &b){
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
in >> b.board[row][col];
}
}
return in;
}
And this is my function for attack made for player:
getSpaceValue return the value of board for example M is miss,X hit etc.
recordHit return boolean,if user hitted the ship it returns true and change board value in this palce to X if not returns false(miss).
void Game::atack(Board &b){
int attemptCounter = 0;
int xEntry, yEntry;
bool goodMove=false;
string entryTemp;
while(!goodMove){
if(attemptCounter>0)
cout << "Wykonales juz ten ruch sprobuj jeszcze raz"<<endl;
cout <<"Wpisz lokalizacje statku ktory chcesz zatakowac "<<endl;
entryTemp = validLoc();
xEntry=static_cast<int>(entryTemp[0]);
yEntry=static_cast<int>(entryTemp[1]);
cout<<"Get value wartoswc: "<<(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED)<<endl;
if(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED){
b.recordHit(xEntry-A_ASCII, yEntry-N_ASCII);
goodMove = true;
}
attemptCounter++;
}
}
And thats the recordHit function on the normal game(whiut loading the board) evrything works fine but when we load its returns always false even if ship is hitted.
bool Board::recordHit(int x, int y){
for(int i=0; i<SHIPS_NUM;i++){
if(ship[i].recordHit(x,y)){
board[y][x]=HITTED;
return true;
}
}
board[y][x]=MISSED;
return false;
}
Edit:
Board::Board(){
for(int i=0; i<BOARDSIZE; i++){
for(int j=0; j<BOARDSIZE;j++){
board[i][j]=WATER;
}
}
for(int i=0;i<SHIPS_NUM;i++){
ship.push_back(Ship5(SHIP_LENGTH[i]));
}
}
Board.h
#include <iostream>
#include <vector>
#include "const.h"
#include "ship.h"
using namespace std;
/**
* Klasa planszy oraz jej metody
*/
class Board{
protected:
char board[BOARDSIZE][BOARDSIZE];
vector<Ship5> ship;
public:
Board();
Board& operator=(const Board &board1);
~Board()= default;
void printBoard();
void showUnhiddenBoard();
bool setShip(int shipID, int x, int y, bool horizontal);
bool recordHit(int x, int y);
int HitsNumber();
int HitsMiss();
char getSpaceValue(int x,int y);
friend ostream & operator<<(ostream & out,const Board & b);
friend istream & operator>>(istream & in, Board &b);
};
Posibble values of board
const char WATER = '~';
const char SHIP = '-';
const char MISSED = 'M';
const char HITTED = 'X';
const char UNKNOWN = '?';
So I ran into this issue as I was coding for the class I'm currently in, I believe the code should run fine but this came up: Binary '[': no operator found which takes a left hand operand of type 'const SortableVector'
I'm not quite sure how to tackle this, any suggestions?
I ended up looking at No '==' operator found which takes a left-hand operand of const Type to see if I could find a solution in there however I did not, it seems my issue is stemming from something that I don't personally see.
#include <iostream>
#include "SortableVector.h"
using namespace std;
int main() {
const int SIZE = 10;
SortableVector<int> intTable(SIZE);
for (int x = 0; x < SIZE; x++) {
int z;
cout << "Please enter a number with no decimals: ";
cin >> z;
intTable[x] = z;
}
cout << "These values are in intTable:\n";
intTable.print();
intTable.sortInt(intTable, SIZE);
cout << "These values in intTable are now sorted: ";
intTable.print();
return 0;
}
//SortableVector.h
#include <iostream>
#include <cstdlib>
#include <memory>
#include <vector>
using namespace std;
struct IndexOutOfRangeException {
const int index;
IndexOutOfRangeException(int ix) : index(ix) {}
};
template<class T>
class SortableVector {
unique_ptr<T[]> aptr;
int vectorSize;
public:
SortableVector(int);
SortableVector(const SortableVector &);
int size() const { return vectorSize; }
T &operator[](int);
void sortInt(SortableVector<int>, int);
void print() const;
};
template<class T>
SortableVector<T>::SortableVector(int s) {
vectorSize = s;
aptr = make_unique<T[]>(s);
for (int count = 0; count < vectorSize; count++) {
aptr[count] = T();
}
}
template<class T>
SortableVector<T>::SortableVector(const SortableVector &obj) {
vectorSize = obj.vectorSize;
aptr = make_unique<T[]>(obj.vectorSize);
for (int count = 0; count < vectorSize; count++) {
aptr[count] = obj[count];
}
}
template<class T>
T &SortableVector<T>::operator[](int sub) {
if (sub < 0 || sub >= vectorSize) {
throw IndexOutOfRangeException(sub);
return aptr[sub];
}
}
template<class T>
void SortableVector<T>::sortInt(SortableVector<int> x, int z) {
int i, j;
int temp = 0;
for (i = 0; i < z - 1; i++) {
for (j = 0; j < z - 1; j++) {
if (x[j] > x[j + 1]) {
temp = x[j];
x[j] = x[j + 1];
x[j + 1] = temp;
}
}
}
}
template<class T>
void SortableVector<T>::print() const {
for (int k = 0; k < vectorSize; k++) {
cout << aptr[k] << " ";
}
cout << endl;
}
Your operator[] returns a reference to the element, which will allow people to directly change the element. The problem happens when you try to use the operator on a const object (when you used const references to pass things to functions). This will allow someone to change the object through that reference returned by operator[], which breaks const-correctness and therefore is not allowed.
In case you're sill confused, let's say you have some class like this:
class Foo
{
private:
int numbers[100];
public:
int& operator[](const int & pos)
{
return numbers[pos];
}
};
This works fine for creating an object and using the bracket operator to access the elements. However, when you try to create a const object:
const Foo f;
You can do something like this:
f[3] = 5;
operator[] returns a reference, which can be used to directly change the data stored in f. f is declared as const though, so this must not happen and the compiler gives an error.
The solution would be to have two versions of operator[], overloaded by their const-ness:
class Foo
{
private:
int numbers[100];
public:
int& operator[](const int &pos)
{
return numbers[pos];
}
const int& operator[](const int &pos) const
{
return numbers[pos];
}
};
I have those classes and I want to sort an array of objects, considering x coordinate, and sort just those with a particular value to an attribute.
Class.h
#include <iostream>
#include <algorithm>
class Punct2D
{
protected:
int x, y;
public:
Punct2D() {};
~Punct2D() {};
int get_x() const;
int get_y() const;
void set_x(const int x);
void set_y(const int y);
friend std::ostream &operator << (std::ostream &flux, Punct2D dot);
friend std::istream &operator >> (std::istream &flux, Punct2D &dot);
};
class Punct2DColorat :public Punct2D
{
private:
char *color;
public:
Punct2DColorat() { this->color = NULL; };
~Punct2DColorat() {};
char *get_color();
void set_color(char *color);
bool operator<(Punct2DColorat dot);
};
Here I have the implementation.
#include "Class.h"
int Punct2D::get_x() const
{
return this->x;
}
int Punct2D::get_y() const
{
return this->y;
}
void Punct2D::set_x(const int x)
{
this->x = x;
}
void Punct2D::set_y(const int y)
{
this->y = y;
}
char *Punct2DColorat::get_color()
{
return this->color;
}
void Punct2DColorat::set_color(char *color)
{
this->color = new char[strlen(color) + 1];
for (int i = 0; i < strlen(color) + 1; i++) this->color[i] = color[i];
}
bool Punct2DColorat::operator<(Punct2DColorat dot)
{
return this->x < dot.get_x();
}
std::ostream &operator << (std::ostream &flux, Punct2D dot)
{
flux << "Punct(" << dot.get_x() << "," << dot.get_y() << ")\n";
return flux;
}
std::istream &operator >> (std::istream &flux, Punct2D &dot)
{
std::cout << "Introduceti x :";
flux >> dot.x;
std::cout << "Introduceti y :";
flux >> dot.y;
return flux;
}
And here is the Main.
#include "Class.h"
void main()
{
int n, it = 0; char *aux = new char[15]; bool value;
Punct2DColorat *dots;
std::cout << "Cate puncte introduceti :"; std::cin >> n;
dots = new Punct2DColorat[n];
for (int i = 0; i < n; i++)
{
std::cout << "Introduceti 0 pentru Punct2D, respectiv 1 pentru Punct2D colorat :";
std::cin >> value;
if (value)
{
std::cin >> dots[i];
std::cout << "Introduceti culoarea punctului :";
std::cin >> aux;
dots[i].set_color(aux);
}
else
{
std::cin >> dots[i];
}
}
std::sort(dots, dots + n, [](Punct2DColorat dot) { return dot.get_color() != NULL; });
for (int i = 0; i < n; i++)
{
std::cout << dots[i];
if (dots[i].get_color() != NULL)
{
std::cout << "Culoare :" << dots[i].get_color() << "\n";
}
std::cout << "\n";
}
}
I want to sort the dots with color !=NULL, I tried this, it works but I have a runtime error.
bool Punct2DColorat::operator<(Punct2DColorat dot)
{
if ((this->color != NULL) && (dot.get_color() != NULL))return this->x < dot.get_x();
return true;
}
How can I sort just the objects with color !=NULL and the other objects with color==NULL remain in the same position?
Here is an example:
//If have 3 objects in the following order stored in the dots array.
dots[0].get_x()=3;
dots[0].get_y()=3;
dots[0].get_color()="Red";
dots[1].get_x()=0;
dots[1].get_y()=0;
dots[1].get_color()=NULL;
dots[2].get_x()=1;
dots[2].get_y()=1;
dots[2].get_color()="Blue";
//After sort i want to have them like this:
dots[0].get_x()=1;
dots[0].get_y()=1;
dots[0].get_color()="Blue";
dots[1].get_x()=0;
dots[1].get_y()=0;
dots[1].get_color()=NULL;
dots[2].get_x()=3;
dots[2].get_y()=3;
dots[2].get_color()="Red";
Thanks.
The problem is, your comparison operator evaluates to true for any couple of non-colored points.
A possible solution is to construct a second vector, sort it and re-insert
std::vector<Punct2DColorat> tmp;
for (int i = 0; i < n; i++)
{
if (dots[i].get_color() != NULL)
{
tmp.push_back(dots[i]);
}
}
std::sort(tmp.begin(), tmp.end());
int j = 0;
for (int i = 0; i < n; i++)
{
if (dots[i].get_color() != NULL)
{
dots[i] = tmp[j];
++j;
}
}
I have problem with dynamic allocation in c++.
This is my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Wektor {
int rozmiar;
float *TabWe;
friend std::istream& operator >> (std::istream &Strm, Wektor &Wek);
public:
Wektor(int rozmiar) : rozmiar(rozmiar) {
TabWe = new float[rozmiar];
}
Wektor() {
for (int i = 0; i < rozmiar; i++)
{
TabWe[i] = 0;
}
}
~Wektor()
{
for (int i = 0; i <rozmiar; i++)
{
delete[] TabWe;
}
}
};
istream& operator >>(istream &Strm, Wektor &Wek)
{
cout << "Size: ";
Strm >> Wek.rozmiar;
for (int i = 0; i < Wek.rozmiar; i++)
{
Strm >> Wek.TabWe[i];
}
return Strm;
}
int main()
{
Wektor wek;
cin >> wek;
}
After I enter first value to the matrix I get this error:
I think there is problem with default constructor, because you can see on the screenshot that this matrix has no value when program starts. What is wrong with it?
I'm a beginner when it comes to C++ and have recently ran in to a very frustrating problem with my small program where I'm practicing operator overloading and templates.
I've created a template-class called SortedVector that can store instances of various types.
using namespace std;
template <class T, int size> class SortedVector {
public:
SortedVector();
bool add(const T& v);
T& median();
void sortArray();
void removeLarge(const T& v);
void print(ostream &os);
void compexch(T& x, T& y);
void sortArray(T* data, int s);
private:
T arr[size];
int arraySize;
};
template <class T, int size> SortedVector<T, size>::SortedVector() {
arraySize = 0;
for (int i = 0; i < size; i++) {
arr[i] = T();
}
}
template <class T, int size> bool SortedVector<T, size>::add(const T& v) {
if (arraySize > size - 1) {
cout << "Array is full!" << endl;
return false;
} else {
arr[arraySize] = v;
arraySize++;
sortArray(arr, arraySize);
}
return true;
}
template <class T, int size> void SortedVector<T, size>::sortArray(T* data, int s) {
for (int i = 0; i < s - 1; i++) {
for (int j = i + 1; j < s; j++) {
compexch(data[i], data[j]);
}
}
}
template <class T, int size > T & SortedVector<T, size>::median() {
}
template <class T, int size> void SortedVector<T, size>::removeLarge(const T & v) {
}
template <class T, int size> void SortedVector<T, size>::print(ostream & os) {
for (int i = 0; i < arraySize; i++) {
cout << arr[i] << endl;
}
}
template <class T, int size> inline void SortedVector<T, size>::compexch(T& x, T& y) {
if (y < x) {
T temp = x;
x = y;
y = temp;
}
}
It can store ints succesfully and it can also store Polygons (a custom made class created in a earlier assignment).
Polygon.h:
class Polygon {
public:
Polygon(Vertex vertexArray[], int size);
Polygon() : vertices(0), arraySize(0) {}
~Polygon() {delete[] vertices;}
void add(Vertex v);
float area();
int minx();
int maxx();
int miny();
int maxy();
int numVertices() const {return arraySize;}
friend ostream &operator << (ostream &output, const Polygon& polygon);
friend bool operator > (Polygon polygon1, Polygon polygon2);
friend bool operator < (Polygon polygon1, Polygon polygon2);
private:
int arraySize;
Vertex * vertices;
};
Polygon.cpp declaration:
using namespace std;
void Polygon::add(Vertex v) {
arraySize++;
Vertex * tempVertexes = new Vertex[arraySize];
for (int i = 0; i < arraySize; i++) {
if (i == arraySize - 1) {
tempVertexes[i] = v;
} else {
tempVertexes[i] = vertices[i];
}
}
delete [] vertices;
vertices = tempVertexes;
}
Polygon::Polygon(Vertex vertexArray[], int size) {
arraySize = size;
vertices = new Vertex[size];
for (int i = 0; i < size; i++) {
vertices[i] = vertexArray[i];
}
}
float Polygon::area() {
float area = 0.0f;
for (int i = 0; i < arraySize - 1; ++i) {
area += (vertices[i].getXposition() * vertices[i + 1].getYposition()) - (vertices[i + 1].getXposition() * vertices[i].getYposition());
}
area += (vertices[0].getYposition() * vertices[arraySize - 1].getXposition()) - (vertices[arraySize - 1].getYposition() * vertices[0].getXposition());
area = abs(area) *0.5;
return area;
}
ostream& operator<<(ostream &output, const Polygon& polygon) { //Kolla denna!
output << "{";
for (int i = 0; i < polygon.numVertices(); i++) {
output << "(" << polygon.vertices[i].getXposition() << "," << polygon.vertices[i].getYposition() << ")";
}
output << "}";
return output;
}
bool operator>(Polygon polygon1, Polygon polygon2) {
if (polygon1.area() > polygon2.area()) {
return true;
} else {
return false;
}
}
bool operator<(Polygon polygon1, Polygon polygon2) {
if (polygon1.area() < polygon2.area()) {
return true;
} else {
return false;
}
}
template <class T> inline void compexch(T& x, T& y) {
if (y < x) {
T temp = x;
x = y;
y = temp;
}
}
The code for the Vertex class:
class Vertex {
public:
Vertex() : y(0), x(0) {}
Vertex(int xPosition, int yPosition) : x(xPosition), y(yPosition) {}
~Vertex() {}
int getXposition() const {return x;}
int getYposition() const {return y;}
private:
int x;
int y;
};
The problem however is that the overloaded <<-operator seems print out the wrong values from the main-method:
int main() {
SortedVector<Polygon, 10> polygons;
SortedVector<int, 6> ints;
ints.add(3);
ints.add(1);
ints.add(6);
Vertex varr[10];
varr[0] = Vertex(0, 0);
varr[1] = Vertex(10, 0);
varr[2] = Vertex(5, 2);
varr[3] = Vertex(5, 5);
polygons.add(Polygon(varr, 4));
cout << "varr area:" << (Polygon(varr, 4)).area() << endl;
varr[0] = Vertex(0, 0);
varr[1] = Vertex(25, 8);
varr[2] = Vertex(10, 23);
polygons.add(Polygon(varr, 3));
cout << "var area (1):" << (Polygon(varr, 3)).area() << endl;
varr[0] = Vertex(0, 0);
varr[1] = Vertex(5, 0);
varr[2] = Vertex(5, 3);
varr[3] = Vertex(4, 8);
varr[4] = Vertex(2, 10);
polygons.add(Polygon(varr, 5));
cout << "var area (2):" << (Polygon(varr, 5)).area() << endl;
polygons.print(cout);
ints.print(cout);
cout << "MEDIAN: " << ints.median() << endl;
cout << "MEDIAN: " << polygons.median() << endl;
return 0;
}
The code that is printed is:
var area (1):247.5
var area (2):33.5
{(6029504,0)(5,0)(5,3)}
{(6029504,0)(5,0)(5,3)(4,8)}
{(6029504,0)(5,0)(5,3)(4,8)(2,10)}
1
3
6
MEDIAN: 1
MEDIAN: {(6029504,0)(5,0)(5,3)}
Firstly, the method prints out the same polygon but with varying sizes. Secondly, it points out the wrong getXPosition() for the first object in the array. Everything else (that is implemented, like the ints and the area) is correct tho. Why is this? Am I missing something important here or am I just completely of with my program?
If theres any more code needed I am happy to provide it.
Regards
Given the code you posted, the issues are clear as to what's wrong.
You're passing Polygon's by value here:
friend bool operator > (Polygon polygon1, Polygon polygon2);
friend bool operator < (Polygon polygon1, Polygon polygon2);
and you're copying and assigning values here in: compexch:
if (y < x) {
T temp = x; // copy constructor
x = y; // assignment
y = temp; // assigment
}
This means that copies will be made, and your Polygon class cannot be copied safely. You will have memory leaks and bugs when calling either of these functions.
You should implement the appropriate copy constructor and assignment operator, whose signatures are:
Polygon(const Polygon& rhs); // copy constructor
Polygon& operator=(const Polygon& rhs); // assignment operator
Both of these functions should be implemented. Please see the Rule of 3 for this information.
However, for operator < and operator >, you should pass references, not values to these functions:
friend bool operator > (Polygon& polygon1, Polygon& polygon2);
friend bool operator < (Polygon& polygon1, Polygon& polygon2);
Then the copy constructor and assignment operator are not brought into play, since the parameter type is a reference.
Let's try to implement the copy / assignment functions anyway, for completeness:
For example, the copy constructor can be implemented like this:
Polygon::Polygon(const Polygon& rhs) : vertices(new int[rhs.arraySize]),
arraySize(rhs.arraySize)
{
for (int i = 0; i < arraySize; ++i)
vertices[i] = rhs.vertices[i];
}
Then for the assignment operator, using the copy / swap idiom:
Polygon& operator=(const Polygon& rhs)
{
Polygon temp(rhs);
std::swap(temp.arraySize, arraySize);
std::swap(temp.vertices, vertices);
return *this;
}
Once you've implemented these function, plus the destructor that calls delete[], you should no longer have an issue with copying the objects.
Other issues:
In addition, you really should only overload < and ==, initially with their "full" implementation, and write the other relational operators with respect to these two operators.
Right now, you're making the classic mistake of writing one operator (operator >), and then trying to turn the logic "inside-out" when implementing operator <. What if the logic for operator > were more complex, and it took yeoman's work to figure out what is the "opposite of <"?
If you implemented ==, then operator > just becomes:
return !(polygon1 < polygon2) && !(polygon == polygon2); // <-- this can be further improved by implementing operator !=