I am compiling a program with gcc and when I run a.out I get this error:
Segmentation fault: 11
I think it has to do with Board::display, but I don't see anything wrong with it..
#include <iostream>
using namespace std;
const bool WHITE = 0;
const bool BLACK = 1;
//-----------------------------
class Piece
{
public:
// constructors
Piece();
Piece(bool color);
// functions
char getColor() const {return color; }
bool getSymbol() const {return symbol;}
protected:
bool color;
char symbol;
};
ostream& operator << (ostream& out, const Piece & piece)
{
out << piece.getSymbol();
return out;
}
Piece::Piece() { }
Piece::Piece(bool color)
{
this->color = color;
}
//-----------------------------
class King : public Piece
{
public:
King(bool color);
};
King::King(bool color) : Piece(color)
{
this->symbol = 'K';
}
//-----------------------------
class Tile
{
public:
// constructors/destructors
Tile();
Tile(Piece piece, int row, int col);
// functions
bool getColor() const {return color;}
void display();
private:
Piece piece;
int row, col;
bool color;
};
Tile::Tile() { }
Tile::Tile(Piece piece, int row, int col)
{
this->row = row;
this->col = col;
}
void Tile::display()
{
if (getColor() == BLACK)
{
if (piece.getColor() == BLACK)
cout << "\E[30;47m " << piece << " \E[0m";
else
cout << "\E[37;47m " << piece << " \E[0m";
}
else
{
if (piece.getColor() == BLACK)
cout << "\E[30;41m " << piece << " \E[0m";
else
cout << "\E[37;41m " << piece << " \E[0m";
}
}
//---------------------------
class Board
{
public:
// constructor
Board();
// functions
void display();
private:
Tile *tiles[8][8];
};
Board::Board()
{
for (int r = 0; r < 8; r++)
for(int c = 8; c < 8; c++)
tiles[r][c] = new Tile(King(BLACK), r, c);
}
void Board::display()
{
for (int r = 7; r >= 0; r--)
{
for(int c = 7; c >= 0; c--)
tiles[r][c]->display();
cout << endl;
}
}
//---------------------------
int main()
{
Board board;
board.display();
}
In Board::display(), r++ should be r--, and ditto for c++.
If (like me) you prefer unsigned variables for array indices, you would write the loop like this:
for (std::size_t i = 0; i != N; ++i)
{
array[N - 1 - i] = something();
}
Or, if you find that to cumbersome but you still really don't like <= and prefer iterator-style "not-equals" termination (like me), you can stick with unsigned types and say:
for (std::size_t i = N; i != 0; --i)
{
array[i - 1] = anotherthing();
}
Your next mistake is to store a polymorphic object by value of the base. That can't work! Instead, you might want to save a pointer (or reference). While we're at it, it's time for you to learn constructor initializer lists:
class Tile
{
Piece * piece; // must be a polymorphic handle!
int row;
int col;
public:
Tile(Piece * p, int r, int c) : piece(p), row(r), col(c) { }
Tile() : piece(NULL), row(0), col(0) { }
};
If you store a polymorphic object by value, you end up slicing it. You could have saved yourself the trouble by making Piece abstract.
As you can see, you should also make sure the default constructor does something useful. In fact, I would argue that the default constructor doesn't actually make sense, and that you should just remove it.
Finally, I should add that the Tile class design is a terrible problem, because you don't manage the lifetime of the Piece objects, which currently just leak. If you were to manage them, you'd need to delete the piece in the destructor of Tile, but then you'd need to implement the Rule of Three, and now you realise that Piece needs a virtual destructor...
I'm realising that this is turning into a full-blown chapter of "How to do C++", so I'll stop now. I think we have several good books on our recommended list; please consult those.
In Board::display, you are incrementing your variables in the loops instead of decrementing them.
You also aren't assigning piece to Tile::piece in Tiles constructor. (this->piece = piece)
Surely you mean:
for (int r = 7; r >= 0; r--)
{
for(int c = 7; c >= 0; c--)
to be
for (int r = 6; r > 0; r--)
{
for(int c = 6; c > 0; c--)
Unless it is just a typo the line:
for(int c = 8; c < 8; c++)
in the Board constructor is wrong and will result in none of tiles being allocated with the ultimate result of "bad" things happening when you try to use them.
Change it to:
for(int c = 0; c < 8; c++)
At some point you'll want to delete these although a better option might to be not use pointers at all in this case, just Tile tiles[8][8]; or a vector<vector<Tile> > tiles.
Related
I have class A and method call a_method, I have class B with and object b_object, and I wanted to pass object b_object as an argument into a_method, but how do I declare it in a_method?
#include <iostream>
#include <vector>
class Board{
int sizeofboard;
std::vector<std::vector<int>> board;
public:
Board(int sizeofboard){
this->sizeofboard = sizeofboard;
int n = 1;
for (int i = 0; i < sizeofboard; i++){
board.push_back(std::vector<int>());
for (int j = 0; j < sizeofboard; j++){
board[i].push_back(n);
n++;
}
}
}
display(){
for (int i = sizeofboard-1; i >= 0; i--){
std::cout << " ";
for (int j = 0; j < sizeofboard; j++){
if (j == sizeofboard-1){
std::cout << board[i][j];
continue;
}
std::cout << board[i][j] << " | ";
}
std::cout << std::endl;
if (i == 0)continue;
std::cout << "---+---+---" << std::endl;
}
}
draw(int position, Player &player){
int i, j;
int i = position/3;
if (i == 0)i = 2;
j = position%3;
}
};
class Player{
char symbol;
public:
};
int main()
{
Board board(3);
Player player1;
board.display();
return 0;
}
so the part of draw I am confused on how to declare it. it says Player has not been declared
draw(int position, Player &player){
A C++ compiler compiles a C++ program from beginning to the end. At this point, your C++ compiler does not know anything about this mysterious class called Player, which has not been declared yet.
You can simply move the definition of Player before this class. In other cases a forward declaration is all that's needed.
In situations involving complex dependencies between classes it might be necessary to merely declare all classes, first, then defer the definition of all class members until everything is fully defined.
In this case moving the declaration first will solve this particular error (but not other, unrelated compilation errors). This may change, depending on any code that's not shown here.
The below working example shows what you want:
#include <iostream>
#include <vector>
class Player{
public:
char symbol = 'A';
};
class Board{
int sizeofboard;
std::vector<std::vector<int>> board;
public:
Board(int sizeofboard){
this->sizeofboard = sizeofboard;
int n = 1;
for (int i = 0; i < sizeofboard; i++){
board.push_back(std::vector<int>());
for (int j = 0; j < sizeofboard; j++){
board[i].push_back(n);
n++;
}
}
}
//this display function takes Player be reference
void display(Player &player){
for (int i = sizeofboard-1; i >= 0; i--){
std::cout << " ";
for (int j = 0; j < sizeofboard; j++){
if (j == sizeofboard-1){
std::cout << board[i][j];
continue;
}
std::cout << board[i][j] << " | ";
}
std::cout << std::endl;
if (i == 0)continue;
std::cout << "---+---+---" << std::endl;
}
std::cout<<player.symbol<<std::endl;//this prints the player1 symbol value
}
void draw(int position, Player &player){
int j;
int i = position/3;
if (i == 0)i = 2;
j = position%3;
}
};
int main()
{
Board board(3);
Player player1;
board.display(player1);//pass player1 object by reference.
return 0;
}
Note that from inside the display() method we have printed out the symbol data member's value.
I have to create a Battleship game where the first part asks to create a Ship class and initialize five instance of the ship class:
Frigate(len 2),
Sub (len 3),
Destroyer (len 3),
Battleship (len 4),
Aircraft Carrier (len 5)
Ships have to take random spots on the board and show each ship position using the first letter of the ship name.
No hit or miss functions yet.
I feel like I have no idea how to approach this.
So far, I've created the board successful. I feel like I might have to make an area for the placements of ships on the board.
I'm so sorry. My code looks like garbage and I really need some guidance :(
Edit: I've made a ship placement function and fixed my class, but not sure if they're correct
#include <iostream>
#include <ctime>
using namespace std;
const int ROWS = 10;
const int COLS = 10;
const int SHIPTYPE = 5;
string array[ROWS][COLS];
// Create struct with horizontal and vertical coordinates
struct Arr{
int x;
int y;
};
class Ship(){
// Declare ship type
string type;
// Declare length of int type for points on grid
int length;
// Coordinates of grid with max length of ship (0-4)
Arr board[5];
Ship[SHIPTYPE];
enum direct h, v;
struct Placeship{
direct dir;
Ship shipType;
};
};
void Board()
{
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
array[i][j] = '-';
}
}
}
void VBoard()
{
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
cout << array[i][j] << " ";
}
cout << endl;
}
}
// Make a function that allows for ship placement
Placeship(){
int x, y, z;
Placeship sp;
// Bad return
sp.shipType.board[0].X = -1;
// User input for integers
cin >> x >> y >> z;
if(x!=0 && x! = 1){
return sp;
}
else if (y < 0 || y >= ROWS){
return sp;
}
else (y > 0 || y >= COLS){
return sp;
}
// Include direction: Horizontal and Vertical
sp.direction = (direct)x;
sp.shipType.board[0].X = y;
sp.shipType.board[0].Y = z;
return sp;
}
// Create function to set or load ships
void setShip(){
// Include data for ships
ship_t[0].type = "Frigate"; ship_t[0].length = 2;
ship_t[1].type = "Sub"; ship_t[1].length = 3;
ship_t[2].type = "Destroyer"; ship_t[2].length = 3;
ship_t[3].type = "Battleship"; ship_t[3].length = 4;
ship_t[4].type = "Aircraft Carrier"; ship_t[4].length = 5;
}
int main()
{
//Call functions
Board();
VBoard();
Placeship();
setShip();
return 0;
}
Is this a homework? It is asking you to define a class for the Ship object with two (so far) properties: a type/name (can be reduced to a single character), and a length. Here is one way of doing this:
class Ship
{
public:
Ship(char n) : n_(n)
{
switch(n_)
{
case 'F': len_ = 2; break;
case 'S': len_ = 3; break;
case 'D': len_ = 3; break;
case 'B': len_ = 4; break;
case 'A': len_ = 5; break;
default: // process bad input
}
}
private:
char n_;
int len_;
}
However, being familiar with the game, I know that ships don't play any role in it: the board is responsible for hit / miss response, and everything else. So I don't think you need that Ship class at all!
Please ask another question
I have created a 3d array into main function because one of its size came from used input. I am using C++
std::cin >> size;
typedef int T[8][3];
T* tables = new T[size];
It is basically tables[size][8][3]
Now I have to use this 3d table in different functions and have to store values into it. The best way to do it by make this table as a global variable. But I am not sure that I can do it after main function. The other option I have, that I have to pass this table as a parameter and have to return that at the end of the function.
I have tried both the approach but I am having error. Please help me about this issue. I don't know which approach to choose and how to do it.
Thank you in advance.
**Example:**This an example what I really want to do. Here I create a 3d array in main function and through another function I gave some input into that array and again print that in main function.
#include <iostream>
#include <conio.h>
using namespace std;
class M
{
public:
int i,j,k;
public:
int pass(int (*table)[8][3],int size);
}
int M:: pass(int (*table)[8][3],int s)
{
for (i=0;i<s;i++)
{
//int a = tables[i][2][1];
for(j=0;j<8;j++)
{
for(k=0;k<3;k++)
{
table[i][j][k]=i;
}
}
}
return (*table)[8][3]; // not sure about this
}
int main()
{
int size,i,j,k;
std::cin >> size;
typedef int T[8][3]; // T is your 2d array type
T* tables = new T[size];
cout << "test";
M mx;
mx.pass(tables,size); // not sure
for (i=0;i<size;i++)
{
for(j=0;j<8;j++)
{
for(k=0;k<3;k++)
{
cout<<tables[i][j][k];
cout<<" ";
}
cout<<endl;
}
cout<<endl;
cout<<"..........." << i <<endl;
}
getch();
}
I don't know if I completely understand your problem. But you can definitely store the pointer locally in your object and reference it elsewhere. Something like this:
class M
{
public:
M(int(*tbl)[8][3]) : table(tbl) { }
int(*table)[8][3];
int i, j, k;
public:
void pass(int size);
};
void M::pass(int s)
{
for (i = 0; i<s; i++)
{
for (j = 0; j<8; j++)
{
for (k = 0; k<3; k++)
{
table[i][j][k] = i;
}
}
}
}
int main()
{
int size, i, j, k;
std::cin >> size;
typedef int T[8][3]; // T is your 2d array type
T* tables = new T[size];
cout << "test";
M mx(tables);
mx.pass(size); // not sure
for (i = 0; i<size; i++)
{
for (j = 0; j<8; j++)
{
for (k = 0; k<3; k++)
{
cout << tables[i][j][k];
// or you can also:
// cout << mx.table[i][j][k];
cout << " ";
}
cout << endl;
}
cout << endl;
cout << "..........." << i << endl;
}
_getch();
}
Since you are creating a dynamic 3D array whose two dimensions are fixed, Use a std::array<std::array<int, 3>, 8> as your 2D array. Use a std::vector<__2D_ARRAY_TYPE> to create the 3D array.
#include <iostream>
#include <array>
#include <vector>
int main() {
std::array<std::array<int, 3>, 8> array_2d ;
std::vector<decltype(array_2d)> array_3d ;
int size = 4 ;
for(int i = 0; i < size; ++i)
{
for(int j = 0; j < 8; ++j)
for(int k = 0; k < 3; ++k)
array_2d[j][k] = j + k ;
array_3d.push_back(array_2d);
}
return 0;
}
Something like this you can use easily which does the job more easily without any manual memory management.
You can pass it to a function. The signature would be :
return_type function_name(const std::vector<std::array<std::array<int, 3>, 8>>& array_3d)
{ .... }
In
class M
{
public:
int i,j,k;
public:
int pass(int (*table)[8][3],int size);
}
you don't have to write public twice. You can simply put all of the public member data under the keyword public.
Also, you seem to be re-writing your function over again at the very end. Instead of
cout<<tables[i][j][k];
You can write
cout<<*tables
I'm in need of some assistance regarding c++ and objects\references\pointers. I'm writing a simple Chess program that has several classes. In particular I have a problem with the following two classes Board and Cell:
The board has a vector of vectors of Cells (basically a matrix). Each cell holds a pointer to the current piece that is occupying it.
class Board
{
public:
Board();
void drawBoard();
bool makeMove(int startRow, int startCol, int destRow, int destCol);
private:
vector< vector<Cell> > _board;
void initBoard();
void initPieces();
};
Board::Board()
{
initBoard();
}
void Board::initBoard()
{
for (int i = 0; i < BOARD_SIZE; i++)
{
vector<Cell> row; //create empty row
for (int j = 0; j < BOARD_SIZE; j++)
{
row.push_back((Cell(i, j)));
}
_board.push_back(row);
}
initPieces();
}
void Board::initPieces()
{
//Set Pawns
for (int i = 0; i < BOARD_SIZE; i++)
{
_board[1][i].setOccupying(new Pawn(White));
_board[6][i].setOccupying(new Pawn(Black));
}
}
void Board::drawBoard()
{
drawLettersCoord();
for (int i = BOARD_SIZE-1; i >= 0; i--)
{
std::cout << i + 1 << " ";
for (int j = 0; j < BOARD_SIZE; j++)
{
_board[i][j].draw();
}
std::cout << " " << i + 1 << std::endl;
}
std::cout << "\n";
}
bool Board::makeMove(int startRow, int startCol, int destRow, int destCol)
{
_board[startRow][startCol].getOccupyingPiece()->isLegalMove(
startRow, startCol, destRow, destCol);
return true;
}
here is the Cell class:
class Cell
{
public:
Cell();
Cell(int row, int col);
Cell(int row, int col, ChessPiece * occupying);
void draw();
ChessPiece * getOccupyingPiece();
void setOccupying(ChessPiece *occupying);
private:
int _row;
int _col;
bool _occupied;
ChessPiece * _pieceOccupying;
};
Cell::Cell()
:Cell(0, 0)
{
setColour();
}
Cell::Cell(int row, int col)
: _row(row), _col(col), _occupied(false)
{
setColour();
}
Cell::Cell(int row, int col, ChessPiece * occupying)
: _row(row), _col(col), _pieceOccupying(occupying), _occupied(true)
{
setColour();
}
void Cell::setOccupying(ChessPiece *occupying)
{
_occupied = true;
_pieceOccupying = occupying;
}
void Cell::draw()
{
int foregroundText;
if (!_occupied)
{
foregroundText = 37;
}
else
{
foregroundText = _pieceOccupying->getPlayer();
}
cout << "\33[" << foregroundText << ";" << _colour << "m"
<< (_occupied ? _pieceOccupying->getPieceCode(): " ") << "\33[0m";
}
ChessPiece * Cell::getOccupyingPiece()
{
return _pieceOccupying;
}
When I run the game, I create and draw a new Board by calling
Board _board;
_board.drawBoard();
The drawing seems to work OK without any issues.
However, when I call
_board.makeMove(1,0,2,0);
to check if the pawn can make such a move, I get a memory error. Upon debugging I see that the Cell object which is being called has junk in it and not actual data. When I try to look at the pointer to the occupying piece it shows "Unable To Read Memory", so when I call the occupying piece's isLegalMove function, it crashes.
I can't seem to find out what the problem is. I don't understand why a cell inside the vector would have junk in it, it is defined in the class (without new) so as per my understanding it should be available so long as the current instance of the board is alive.
Can anyone shed some light as to what I am doing wrong?
Not all constructors of Cell initialise _occupied and _pieceOccupying, which means that these can have garbage values in some Cell objects.
Furthermore, your makeMove dereferences getOccupyingPiece() unconditionally - it doesn't check for null.
Finally, you only have pawns on your board, which means (0, 0) does not contain a piece - and because of 1., the Cell object contains a garbage value in its _pieceOccupying, so you access random memory and crash.
Alright, I'm trying to implement a simple 2D matrix class right now. This is what it looks like so far:
template <typename Type>
class dyMatrix {
private:
Type *mat;
int width, height;
int length;
public:
dyMatrix (int _width, int _height)
: width(_width), height(_height), mat(0)
{
length = width * height;
mat = new Type[length];
};
// ---
int getWidth() {
return width;
};
int getHeight() {
return height;
};
int getLength() {
return length;
}
// ---
Type& operator() (int i, int j) {
return mat[j * width + i];
};
Type& operator() (int i) {
return mat[i];
};
// ---
~dyMatrix() {
delete[] mat;
};
};
To test it, and compare with static multi-dimensional arrays, I wrote the following snippet of code:
#include <iostream>
using namespace std;
/* matrix class goes here */
struct Coord {
int x, y;
Coord()
: x(0), y(0)
{};
Coord (int _x, int _y)
: x(_x), y(_y)
{};
void print() {
cout << x << ", " << y;
};
};
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
int i = 5, j = 0;
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
adabo(i, j).print();
return 0;
}
"Adabo" and "Inakos" being arbitrarily chosen names. Upon execution, inakos prints its contents but the program crashes before adabo can do anything. Another interesting thing is that, if I give i and j values other than 5 and 0, like 5 and 1, respectively, it works fine.
I don't know what exact numbers work and which make the program go haywire, I only know that there's a irregularity here. What am I possibly doing wrong? I'm an amateur at C++, so I may or not have misused something in any of the structures.
If anyone also has the time, I'd very much like to know if there's any other error of notice in my matrix class. Anything that's not possibly related to the problem, but is a fallacy nevertheless.
I've also tested it with the following main(), but it still crashes after inakos prints its contents in [5][1]. Maybe it has to do not with dyMatrix, but a loosely-implemented Coord?
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
for (int i = 0; i < adabo.getHeight(); i++) {
for (int j = 0; j < adabo.getWidth(); j++) {
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
cout << "; ";
}
cout << "\n\n";
}
cout << "\n\n\n";
Coord temp;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
temp = adabo(i, j);
temp.print();
cout << "; ";
}
cout << "\n\n";
}
return 0;
}
edit: It hasn't to do with Coord. Just tested with a dyMatrix of ints and static matrix of ints, and it crashes after [5][0] nevertheless.
In your first example, you declared inakos[5][7] so the indices range from 0 to 4 and 0 to 6. inakos[5][0] and inakos[5][1] could therefore crash.
In your second example, you again declare inakos[5][7] yet you let the first index loop from 0 to 6. Again inakos[i][j] can crash. One fix is to switch your indices (ie, change to i<adabo.getWidth() and j<adabo.getHeight()).