Question

I know this problem is assessed many times on these forums, but they really are unique to their specific cases most times.

This is a project for a class (on C++ no less), and the point of the project was to remake the classic board game Reversi.

I have toiled through code for hours and finally made a program that will work, or so I thought!

The big problem I am having seems to come from my deconstructor as it's giving me this error many of us have seen. My code is posted below and from my own debugging code (using helpful cout messages) I have determined that the program manages to run to the end of the the Game.cpp class. Only, it stumbles on the deconstructor and crashes before finally "ending nicely".

Board.h

#include <iostream>
#include <cstdlib>
#include <vector>
#ifndef BOARD_H
#define BOARD_H
using namespace std;

enum Piece {LIGHT, DARK, EMPTY, BORDER};
typedef int Move;
Move const NullMove = -1;
int const MAX_SQUARES = 100;
enum Direction {N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7};


class Board
{
public:
    Board();
    void reset();
    void display();
    void makeMove(Piece, Move);
    bool isLegal(Piece, Move);
    Piece getWinner();
    Piece getPlayer();
    void genMoves();
    int numMoves();
    Move getMove(int) const;
    bool gameOver;

private:
    Piece board[MAX_SQUARES];
    int lightPieces;
    int darkPieces;
    vector<Move> goodMoves;
    static Piece currentPlayer;
    vector <int> offset;
};

#endif

Board.cpp

#include <iostream>
#include <cstdlib>
#include <vector>
#include "Board.h"
using namespace std;


Board::Board()
{
    reset();
    for(int i=0;i<MAX_SQUARES;++i)
    {
        if(i<11 || i>88 || i%10==0 || i%10==9)
            board[i]=BORDER;
    }

    offset.push_back(10);
    offset.push_back(11);
    offset.push_back(1);
    offset.push_back(-9);
    offset.push_back(-10);
    offset.push_back(-11);
    offset.push_back(-1);
    offset.push_back(9);

    board[44] = LIGHT;
    board[45] = DARK;
    board[54] = DARK;
    board[55] = LIGHT;

    gameOver=false;
}

void Board::reset()
{
    for(int i=0; i<MAX_SQUARES;++i)
        board[i] = EMPTY;
}

void Board::display()
{
    for(int i=0;i<MAX_SQUARES;++i)
    {
        switch(board[i])
        {
            case LIGHT:
                cout << "|LG|";
                break;
            case DARK:
                cout << "|DR|";
                break;
            case EMPTY:
                cout << "|  |";
                break;
            case BORDER:
                if(i<9)
                    cout << "<0" << i << ">";
                else if(i==9)
                    cout << "<09>\n----------------------------------------\n";
                else if(i%10==9)
                    cout << "<$$>\n----------------------------------------\n";
                else if(i%10==0)
                    cout << "<" << i << ">";
                else if(i<11 || i>90)
                    cout << "<$$>";
                break;
        }

    }
}

void Board::makeMove(Piece p, Move m)
{
    genMoves(); //generate valid moves
    cout << "generated moves\n";
    int good = numMoves();  //gets number of moves
    if(good>0)  //if there are valid moves
    {
        cout << "more than 0\n";
        for(int i=0;i<goodMoves.size();++i) //checking the valid move list
        {
            if(m==goodMoves[i]) //if our move is in the list
            {
                cout << "move was in list\n";
                board[m]=p; //change square
                if(board[m]==DARK)
                    cout << "ITS DARK\n";
                else if(board[m]==LIGHT)
                    cout << "ITS LIGHT\n";
                else if(board[m]==EMPTY)
                    cout << "ITS EMPTY WTF WTF WTF\n";
                for(int i=0;i<8;++i)    //checking directions
                {
                    Piece opp =(p==LIGHT)? DARK : LIGHT;    //Making an opposite piece
                    cout << "made opp\n";
                    int counter=0;
                    int toCheck = m+offset[i];  //making the next square to check
                    if(board[toCheck]==opp) //if it's the opposite colour from player
                    {
                        cout << "it was the opposite piece\n";
                        while(board[toCheck]!=BORDER && board[toCheck]!=EMPTY)  //while it's a piece
                        {
                            cout << "there was a piece to check\n";
                            if(board[toCheck]==p && counter>0)  //if it's player's piece and counter is higher than 0
                            {
                                cout << "this should flip stuff\n";
                                for(int k=m;k!=toCheck;k = k+offset[i])
                                {
                                    board[k]=p;
                                    cout << k;
                                }
                                break;
                            }
                            else
                            {
                                cout << "found nothing, keep trying..\n";
                                toCheck += offset[i];   //if not, step in direction
                                counter++;
                            }
                        }
                    }
                }
            }
            cout << "move wasn't in list\n";
        }
    }
    currentPlayer=(p==LIGHT)? DARK : LIGHT;
}

bool Board::isLegal(Piece p, Move m)
{
    Piece opp =(p==LIGHT)? DARK : LIGHT;    //Making an opposite piece
    if(board[m]==EMPTY) //Checking that the space we're going is empty
    {
        for(int i=0;i<8;++i)    //checking directions
        {
            int toCheck = m+offset[i];  //making the next square to check
            if(board[toCheck]==opp) //if it's the opposite colour from player
            {
                while(board[toCheck]!=BORDER && board[toCheck]!=EMPTY)  //while it's a piece
                {
                    if(board[toCheck]==p)   //if it's player's piece
                        return true;    // if move is valid
                    else
                        toCheck += offset[i];   //if not, step in direction
                }
            }
        }
        return false;   // if there's no valid direction moves
    }
    else    // if it's not empty
        return false;
}

Piece Board::getWinner()
{
    bool gameDone = true;

    for(int i=0;i<MAX_SQUARES;++i)
    {
        if(board[i]==EMPTY)
            gameDone = false;
    }

    if(gameDone==false)
        return EMPTY;
    else if(lightPieces>darkPieces)
        return LIGHT;
    else
        return DARK;
}

Piece Board::getPlayer()
{
    return currentPlayer;
}

void Board::genMoves()
{
    goodMoves.clear();
    cout << "generating shit\n";
    for(int i=0;i<MAX_SQUARES;++i)
    {
        if(isLegal(currentPlayer, i))
            {goodMoves.push_back(i);
        cout << i << " twas a good move\n";}
    }
    if(goodMoves.size()==0)
        gameOver=true;
}

int Board::numMoves()
{
    return goodMoves.size();
}

Move Board::getMove(int i) const
{
    return goodMoves[i];
}

Piece Board::currentPlayer=DARK;

Player.h

#include <iostream>
#include <cstdlib>
#ifndef PLAYER_H
#define PLAYER_H
#include "Board.h"
using namespace std;



class Player
{
public:
    Player(const string&, Piece);
    Piece getPiece() const;
    virtual void makeMove(Board&)=0;
    void setName(string&);
    string getName();
private:
    string name;
    Piece color;
};

#endif

Player.cpp

#include <iostream>
#include <cstdlib>
#include "Player.h"
using namespace std;

Player::Player(const string& n, Piece c)
{
    name = n;
    color = c;
}

Piece Player::getPiece() const
{
    return color;
}

void Player::setName(string& n)
{
    name = n;
}

string Player::getName()
{
    return name;
}

HumanPlayer.h

#include <iostream>
#include <cstdlib>
#include "Player.h"
#ifndef HUMANPLAYER_H
#define HUMANPLAYER_H
using namespace std;

class HumanPlayer: public Player
{
public:
    HumanPlayer(const string&, Piece);
    void makeMove(Board&);
};

#endif

HumanPlayer.cpp

#include <iostream>
#include <cstdlib>
#include "Player.h"
#include "HumanPlayer.h"
using namespace std;

HumanPlayer::HumanPlayer(const string& n, Piece c): Player(n,c) 
{

}

void HumanPlayer::makeMove(Board& b)
{
    Move goTo;
    cout << "Please enter the number for the square you would like to move: ";
    cin >> goTo;
    if(!b.gameOver)
        b.makeMove(getPiece(),goTo);
}

ComputerPlayer.h

#include <iostream>
#include <cstdlib>
#include "Player.h"
#ifndef COMPUTERPLAYER_H
#define COMPUTERPLAYER_H
using namespace std;

class ComputerPlayer: public Player
{
public:
    ComputerPlayer(Piece p);
private:
    static int counter;
    //string name;
};

#endif

ComputerPlayer.cpp

#include <iostream>
#include <cstdlib>
#include "ComputerPlayer.h"
using namespace std;

ComputerPlayer::ComputerPlayer(Piece p) : Player("", p)
{
    string name = "ComputerPlayer" + char(65+counter);
    setName(name);
}

int ComputerPlayer::counter=0;

RandomPlayer.h

#include <iostream>
#include <cstdlib>
#include "ComputerPlayer.h"
#ifndef RANDOMPLAYER_H
#define RANDOMPLAYER_H
using namespace std;

class RandomPlayer : public ComputerPlayer
{
public:
    RandomPlayer(Piece);
    void makeMove(Board&);
};

#endif

RandomPlayer.cpp

#include <iostream>
#include <cstdlib>
#include "RandomPlayer.h"
using namespace std;

RandomPlayer::RandomPlayer(Piece p) : ComputerPlayer(p)
{

}

void RandomPlayer::makeMove(Board& b)
{
    cout << "Player 2 making move in stuff\n";
    b.genMoves();
    int temp1 = b.numMoves();
    cout << "This is temp1: " <<temp1 << '\n';
    int temp2;
    if(temp1>0)
    {
        temp2 = rand()%temp1;
    }
    //cout << "This is temp2: " <<temp2 << '\n';
    if(!b.gameOver)
        b.makeMove(getPiece(),b.getMove(temp2));
}

Game.h

// Name: James St-Germain
// Student #: 0270250

#include <iostream>
#include <cstdlib>
#include "Board.h";
#include "HumanPlayer.h"
#include "RandomPlayer.h"
#ifndef GAME_H
#define GAME_H
using namespace std;

class Game
{
public:
    Game();
    ~Game();
    void selectPlayers();
    Player* nextPlayer();
    void play();
    void announceWinner();
private:
    Board b;
    Player *p1;
    Player *p2;
    bool isRunning;
};

#endif

Game.cpp

// Name: James St-Germain
// Student #: 0270250

#include "Game.h"
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

Game::Game(): b(), p1(NULL), p2(NULL), isRunning(true){}

Game::~Game()
{
    delete &b;
    delete &p1;
    delete &p2;
}

void Game::selectPlayers()
{
    string choice[2];
    cout << "Is player 1 a human player or computer player? (H/C): \n";
    cin >> choice[0];
    cout << "Is player 2 a human player or computer player? (H/C): \n";
    cin >> choice[1];
    for(int i=0;i<2;++i)
    {
        if(choice[i]=="H")
        {
            string n;
            char* c;
            cout << "What is your name?: \n";
            cin >> n;
            if(i==0)
                p1 = new HumanPlayer(n, LIGHT);
            else
                p2 = new HumanPlayer(n, DARK);
        }
        if(choice[i]=="C")
        {
            if(i==0)
                p1 = new RandomPlayer(LIGHT);
            else
                p2 = new RandomPlayer(DARK);
        }
    }
    cout << "Player 1 is " << p1->getName() << '\n';
    cout << "Player 2 is " << p2->getName() << '\n';


}

Player* Game::nextPlayer()
{
    if(b.getPlayer()==LIGHT)
        return p2;
    else
        return p1;
}

void Game::play()
{
    while(isRunning)
    {
        b.display();
        Piece temp = b.getPlayer();
        if(temp==LIGHT)
        {
            cout << "Player 1 moves!\n";
            p1->makeMove(b);
        }
        else
        {
            cout << "Player 2 moves!\n";
            p2->makeMove(b);
        }

        if(b.gameOver==true)
            break;
    }
}

void Game::announceWinner()
{
    Piece winner = b.getWinner();
    string name = (winner==LIGHT) ? p1->getName() : p2->getName();
    cout << "The winner is " << name << "! Congratulations!\n";
}

main.cpp

#include <iostream>
#include <cstdlib>
#include "Game.h"
using namespace std;

int main()
{
    Game Reversi = Game();
    Reversi.selectPlayers();
    Reversi.play();
    Reversi.announceWinner();   
}

I apologize for the extreme amount of code, but at this point, I don't know what to fix. I know there might also be bad coding habits here, so if you see any, I would love the constructive criticism.

Thank you in advance for all your help!!

Was it helpful?

Solution

This is probably because you have these declarations in the Game class:

Board b;
Player *p1;
Player *p2;

and this code in the destructor:

delete &b;
delete &p1;
delete &p2;

First of all, the Board member b is not a pointer so should not be deleted. Second of all, you're using the address-of operator to get the address of the pointer (and it will be a value of type Player**), which you don't allocate. Drop the &.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top