深度优先搜索的Minimax算法导致的段错误

我正在尝试使用C++编写一个反向4×3的井字游戏,使用深度优先搜索和Minimax算法。每当树试图获取Minimax值时,我总是会遇到段错误,我不确定这是为什么。我已经多次检查了我的逻辑,但就是找不到问题所在。我认为可能是树的创建方式有问题。

我的深度优先搜索的想法是,它会查看父节点,如果父节点没有所有子节点,它会创建下一个子节点,将父节点的棋盘复制到子节点的棋盘上,然后对于childNum数组中的每个子节点,它会跳过与子节点编号相对应的空格数量,然后在棋盘上相应地放置X或O。如果不是结束状态,它会将该子节点发送到getMove()。一旦到达结束状态,它会将该值存储在父节点中,并将父节点发送到getMove(),然后逐步返回到树的上层。

有谁能看出是什么导致了这个段错误,或者我的代码中还有其他什么错误吗?这是我的代码:

#include <iostream>#include <fstream>#include <iomanip>#include <string>#include <vector>#include <ctype.h>#include <iostream>using namespace std;struct node_t{    node_t* parent;    int minimax;    int childrenVals[12];    bool isMax;    char board[4][3];    int level;    bool xmove;    node_t* child;};void getMove(node_t *root);void printBoard(char board[4][3]);int checkStatus(char board[4][3]);int getChildNum( int minimax[12]);int status = -2;char myBoard[4][3];int main(){    //create root node    node_t n;    node_t* root;    root = &n;    root->board[0][0] = '1';    root->board[0][1] = '2';    root->board[0][2] = '3';    root->board[1][0] = '4';    root->board[1][1] = '5';    root->board[1][2] = '6';    root->board[2][0] = '7';    root->board[2][1] = '8';    root->board[2][2] = '9';    root->board[3][0] = '/';    root->board[3][1] = '*';    root->board[3][2] = '-';    root->parent = NULL;    root->child = NULL;    root->isMax = true;    root->xmove = true;    root-> level = 0;    for(int i = 0; i < 12; i++){        root->childrenVals[i] = -2;    }    for(int i = 0; i < 4; i++){        for(int j = 0; j < 3; j++){                myBoard[i][j] = root->board[i][j];        }    }    cout<<"Welcome to Reverse Tic Tac Toe! Here is the board:"<<endl;    printBoard(root->board);    cout<<"To make a move, you will type in the number or symbol "<<endl;    cout<<"of the box you would like to place your piece in. "<<endl;    cout<<endl;    cout<<"Would you like to go first or second? (type 1 or 2):"<<endl;    char order;    char Omove;    bool isValid = false;    bool gameOver = false;    int gameValue;    //Get order    cin >> order;    while(order !='1' && order != '2'){        if(order != '1' && order != '2'){            cout<<"Please type a 1 if you would like to go first and a 2 if youwould like to go second:";            cin >> order;        }        else{            break;        }    }    if(order == '2'){        root->xmove = true;        getMove(root);        //root->board = myBoard;        for(int i = 0; i < 4; i++){            for(int j = 0; j < 3; j++){                    root->board[i][j] = myBoard[i][j];            }        }        root->level++;        printBoard(root->board);    }    while(gameOver == false){        cout<< "Your move:";        while(isValid == false){            cin >> Omove;            for(int i = 0; i < 4; i++){                for(int j = 0; j < 3; j++){                    if(root->board[i][j] == Omove && Omove != 'X' && Omove != 'O'){                        root->board[i][j] = 'O';                        isValid = true;                    }                }            }            if(isValid == false){                cout<<"Invalid move, please look at the board and try again:";            }        }        root->level++;        printBoard(root->board);        gameValue = checkStatus(root->board);        if(gameValue != -2){            gameOver = true;        }        else{            getMove(root);            for(int i = 0; i < 4; i++){                for(int j = 0; j < 3; j++){                    root->board[i][j] = myBoard[i][j];                }            }            root->level++;            root->isMax = true;            printBoard(root->board);            if(gameValue != -2){                gameOver = true;            }        }    }    if(gameOver == 1){        cout<<"You lose!"<<endl;    }    else if(gameOver == -1){        cout<<"You win!"<<endl;    }    else if(gameOver == 0){        cout<<"It's a tie!"<<endl;    }    return 0;}void getMove(node_t *node){     status = checkStatus(node->board);     //if node is not an end state    if(status == -2){        int childNum = 0;        for(int i = 0; i < 12 - node->level; i++){            if(node->childrenVals[i] == 0 || node->childrenVals[i] == 1 || node->childrenVals[i] == -1){                childNum++;            }        }        //if node does not have all its children        if(childNum != 12 - node->level){            if(childNum > 0){                //delete current child pointer                delete node->child;            }            //create child Node            node_t* child = new node_t;            child->parent = node;            node->child = child;            child->level = node->level + 1;            for(int i = 0; i < 4; i++){                for(int j = 0; j < 3; j++){                    child->board[i][j] = node->board[i][j];                }            }            for(int i = 0; i < 12; i++){                child->childrenVals[i]= -2;            }            if(node->isMax == true){                child->isMax = false;            }            else{                child->isMax = true;            }            //xmove means the children of that node move for X            if(node->xmove == true){                child->xmove = false;            }            else{                child->xmove = true;            }            int openSpace = 0;            bool shouldbreak = false;            for(int i=0; i < 4; i++){                for(int j=0; j< 3; j++){                    if(child->board[i][j] != 'X' && child->board[i][j] != 'O'){                        if(openSpace == childNum){                            if(node->xmove){                                child->board[i][j] = 'X';                                shouldbreak = true;                                break;                            }                            else{                                child->board[i][j] = 'O';                                shouldbreak = true;                                break;                            }                        }                        else{                            openSpace++;                        }                    }                    if(shouldbreak == true){                        break;                    }                }                if(openSpace == childNum){                    break;                }            }    //  cout<<"Level: "<<node->level<<endl;    //  printBoard(child->board);    //  cout<<endl;            getMove(child);        }        //if node does have all its children        else{        //cout<<"Level: "<<node->level<<endl;    //  printBoard(node->board);            //n is used for the case that it is back to the root node            int n;            if(node->isMax == true){                for(int i = 0; i < 12 - node->level; i++){                    if(node->childrenVals[i] > node->minimax){                        node->minimax = node->childrenVals[i];                        n = i;                    }                }            }            else{                for(int i = 0; i < 12 - node->level; i++){                    if(node->childrenVals[i] < node->minimax){                        node->minimax = node->childrenVals[i];                        n = i;                    }                }            }            //if not at root node            if(node->parent != NULL){                int next = getChildNum(node->parent->childrenVals);                node->parent->childrenVals[next] = node->minimax;                node_t* temp = node->parent;                node->parent = NULL;                getMove(temp);            }            //if at root node            else{            //get move from root by recreating nth child            int openSpace = 0;            for(int i=0; i < 4; i++){                for(int j=0; j< 3; j++){                    if(node->board[i][j] == 'X' || node->board[i][j] == 'O'){                    //go to next space                    }                    else{                        if(openSpace == n){                            node->board[i][j] = 'X';                            break;                        }                        else{                            openSpace++;                        }                    }                    //may have to do a conditional break here                }            }            //set myBoard = this board            for(int i = 0; i < 4; i++){                for(int j = 0; j < 3; j++){                    myBoard[i][j] = node->board[i][j];                }            }            return;            }        }    }    //if node is an end state    else{        if(node->parent != NULL){            int next = getChildNum(node->parent->childrenVals);            node->parent->childrenVals[next] = status;            getMove(node->parent);        }    }}int checkStatus(char board[4][3]){    //returns -2 for no win loss or draw    //returns 1 for win    //returns -1 for loss    //returns 0 for draw    if( (board[0][0] == 'X' && board[1][1] == 'X' && board[2][2] == 'X')||        (board[0][0] == 'X' && board[0][1] == 'X' && board[0][2] == 'X')||        (board[0][0] == 'X' && board[1][0] == 'X' && board[2][0] == 'X')||        (board[0][1] == 'X' && board[1][1] == 'X' && board[2][1] == 'X')||        (board[0][2] == 'X' && board[1][2] == 'X' && board[2][2] == 'X')||        (board[0][2] == 'X' && board[1][1] == 'X' && board[2][0] == 'X')||        (board[1][0] == 'X' && board[2][1] == 'X' && board[3][2] == 'X')||        (board[1][0] == 'X' && board[1][1] == 'X' && board[1][2] == 'X')||        (board[1][0] == 'X' && board[2][0] == 'X' && board[3][0] == 'X')||        (board[1][1] == 'X' && board[2][1] == 'X' && board[3][1] == 'X')||        (board[1][2] == 'X' && board[2][2] == 'X' && board[3][2] == 'X')||        (board[1][2] == 'X' && board[2][1] == 'X' && board[3][0] == 'X')||        (board[2][0] == 'X' && board[2][1] == 'X' && board[2][2] == 'X')||        (board[3][0] == 'X' && board[3][1] == 'X' && board[3][2] == 'X')){            return -1;        }    if( (board[0][0] == 'O' && board[1][1] == 'O' && board[2][2] == 'O')||        (board[0][0] == 'O' && board[0][1] == 'O' && board[0][2] == 'O')||        (board[0][0] == 'O' && board[1][0] == 'O' && board[2][0] == 'O')||        (board[0][1] == 'O' && board[1][1] == 'O' && board[2][1] == 'O')||        (board[0][2] == 'O' && board[1][2] == 'O' && board[2][2] == 'O')||        (board[0][2] == 'O' && board[1][1] == 'O' && board[2][0] == 'O')||        (board[1][0] == 'O' && board[2][1] == 'O' && board[3][2] == 'O')||        (board[1][0] == 'O' && board[1][1] == 'O' && board[1][2] == 'O')||        (board[1][0] == 'O' && board[2][0] == 'O' && board[3][0] == 'O')||        (board[1][1] == 'O' && board[2][1] == 'O' && board[3][1] == 'O')||        (board[1][2] == 'O' && board[2][2] == 'O' && board[3][2] == 'O')||        (board[1][2] == 'O' && board[2][1] == 'O' && board[3][0] == 'O')||        (board[2][0] == 'O' && board[2][1] == 'O' && board[2][2] == 'O')||        (board[3][0] == 'O' && board[3][1] == 'O' && board[3][2] == 'O')){            return 1;        }    //if it has not returned a win or a loss and the board is full return draw        bool isFull = true;        for(int i = 0; i < 4; i++){            for(int j = 0; j < 3; j++){                if(board[i][j] != 'X' && board[i][j] != 'O'){                    isFull = false;                }            }        }        if(isFull == true){            return 0;        }        else{            return -2;        }}int getChildNum( int childrenVals[12]){    //return index to know which child needs to be created next    for(int i = 0; i < 12; i++){        if(childrenVals[i] == -2){            return i;        }    }    return -1;}void printBoard(char board[4][3]){    for(int i = 0; i < 4; i++){        cout<<"|"<<board[i][0]<<"|";        cout<<"|"<<board[i][1]<<"|";        cout<<board[i][2]<<"|"<<endl;    }    cout<<endl;}

回答:

启动调试器,例如gdb,并从那里运行你的代码。当它发生段错误时,如果你配置了调试器以查找源文件,它会显示代码中出错的行。对于简单的案例,当二进制文件和源文件在同一个目录中时,调试器通常可以默认找到源代码。

否则,在代码中添加cout或printf()行,并在关键点分别打印1, 2, 3, …。运行代码,然后你可以看到它在哪两个printf之间发生错误。然后添加更多的printf(),例如1.1, 1.2, 1.3 …直到找到出错的行,然后删除这些printf。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注