调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

时间:2013-11-29 05:56:38

标签: c++ debugging inheritance virtual-functions dynamic-arrays

我知道这些问题在这些论坛上经过多次评估,但它们在大多数情况下都是独特的。

这是一个类的项目(在C ++上也不少),项目的重点是重制经典的棋盘游戏Reversi。

我已经通过代码工作了几个小时,最后制作了一个可以工作的程序,或者我想到了!

我遇到的一个大问题似乎来自我的解构主义者,因为它给了我许多人看到的这个错误。我的代码发布在下面,来自我自己的调试代码(使用有用的cout消息)我已经确定程序设法运行到Game.cpp类的末尾。只是,它在解构器上发现并且在最终“很好地结束”之前崩溃了。

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

我为极端数量的代码道歉,但在这一点上,我不知道该解决什么问题。我知道这里可能还有不良的编码习惯,所以如果你看到了,我会喜欢建设性的批评。

提前感谢您的帮助!!

1 个答案:

答案 0 :(得分:3)

这可能是 因为你在Game类中有这些声明:

Board b;
Player *p1;
Player *p2;

和析构函数中的代码:

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

首先,Board成员b不是指针,因此不应删除。其次,您正在使用address-of运算符来获取指针的地址(它将是Player**类型的值),您不会分配它。放下&