C++中的一个星形实现(语言问题)

A star implementation in C++ (Language Issues)

本文关键字:实现 语言 问题 一个 C++      更新时间:2023-10-16

我正在研究一个A星算法来解决一个N块幻灯片难题。给出一个特定的目标状态,我想找到最少的步骤来解决它。我理解算法,但由于缺乏理解,我在C++方面遇到了问题。任何风格建议都将不胜感激。

  • 重载运算符分配:删除元素指针似乎有问题,所以现在我正在手动重新分配所有内容
  • browseNeighbor:似乎可以做我想做的一切,但当在solve函数中再次访问时,被推回到开放向量上的数据——元素中的值——似乎会变得混乱
  • 现在我只让它访问leftIndex来执行向左移动,并给它一个非常简单的问题来解决,看看它是否有效,但上面的两个问题阻止了它正确工作

C++代码:

#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <list>
#include <vector>
using namespace std;
class board{
    public:
        int boardSize;
        int *elements; //ptr to array
        int rowSize;
        int zeroIndex;
        int upIndex;
        int downIndex;
        int leftIndex;
        int rightIndex;
        int h;
        int g;
        int f;
        board();
        board(int new_rowSize, int new_elements[]);
        ~board();
        void updateZero();
        void updateUpIndex();
        void updateDownIndex();
        void updateLeftIndex();
        void updateRightIndex();
        void updateIndexes();
        void moveUp();
        void moveDown();
        void moveLeft();
        void moveRight();
        bool operator==(const board&);
        board& operator=(const board&);
};
board::board(){
    rowSize = 3;
    boardSize = rowSize * rowSize;
    elements = new int[boardSize];
}
board::board(int new_rowSize, int new_elements[]){
    rowSize = new_rowSize;
    boardSize = rowSize * rowSize;
    elements = new int[boardSize];
    for(int i = 0; i < boardSize; i++) {
        elements[i] = new_elements[i];
    }
}
board::~board(){
    delete [] elements;
}
void board::updateZero(){
    for(int i = 0; i < boardSize; i++){
        if(elements[i] == 0) {
            zeroIndex = i;
            break;
        }
    }
}
void board::updateUpIndex(){
    int temp_upIndex = zeroIndex + rowSize;
    if (temp_upIndex < boardSize) {
        upIndex = temp_upIndex;
    }
    else {
        upIndex = -1;
    }
}
void board::updateDownIndex(){
    int temp_downIndex = zeroIndex - rowSize;
    if (temp_downIndex >= 0) {
        downIndex = temp_downIndex;
    }
    else {
        downIndex = -1;
    }
}
void board::updateLeftIndex(){
    int temp_leftIndex = zeroIndex + 1;
    if(temp_leftIndex % rowSize != 0) {
        leftIndex = temp_leftIndex;
    }
    else {
        leftIndex = -1;
    }
}
void board::updateRightIndex(){
    int temp_rightIndex = zeroIndex - 1;
    if(zeroIndex >= 0 && temp_rightIndex % rowSize - 1 != 0) {
        rightIndex = temp_rightIndex;
    }
    else {
        rightIndex = -1;
    }
}
void board::updateIndexes(){
    updateZero();
    updateUpIndex();
    updateDownIndex();
    updateLeftIndex();
    updateRightIndex();
}
bool board::operator==(const board& second){
    bool result = true;
    for(int i = 0; i < boardSize; i++){
        if(elements[i] != second.elements[i])
            result = false;
    }
    return result;
}
void board::moveUp(){
    elements[zeroIndex] = elements[upIndex];
    elements[upIndex] = 0;
}
void board::moveDown(){
    elements[zeroIndex] = elements[downIndex];
    elements[downIndex] = 0;
}
void board::moveLeft(){
    elements[zeroIndex] = elements[leftIndex];
    elements[leftIndex] = 0;
}
void board::moveRight(){
    elements[zeroIndex] = elements[rightIndex];
    elements[rightIndex] = 0;
}
board& board::operator=(const board& rhs){
    if(this != &rhs){
        delete [] elements;
        boardSize = rhs.boardSize;
        rowSize = rhs.rowSize;
        elements = new int[boardSize];
        for(int i = 0; i < boardSize; i++) {
            elements[i] = rhs.elements[i];
        } 
        zeroIndex = rhs.zeroIndex;
        upIndex = rhs.upIndex;
        downIndex = rhs.downIndex;
        leftIndex = rhs.leftIndex;
        rightIndex = rhs.rightIndex;
        h = rhs.h;
        g = rhs.g;
        f = rhs.f;
    }
    return *this;
}
int manhattan(board *goal, board *current){
    int sum = 0;
    for(int i = 0; i < goal->boardSize; i++) {
        for(int j = 0; j < current->boardSize; j++) {
            if(goal->elements[i] == current->elements[j]) {
                //this produces (goal.x - current.x) + (goal.y - current.y)
                sum += abs(i%goal->rowSize - j%goal->rowSize) + abs(i/goal->rowSize - j/goal->rowSize);
                break;
            }
        }
    }
    return sum;
}
void browseNeighbor(board *goal, board *x, vector<board *> *open, vector<board *> *closed){
            //check if in closed
            x->updateIndexes();
            for(int i = 0; i < closed->size(); i++){
                if(x == closed->at(i)) {
                    return;
                }
            }
            int tenative_g = x->g + 1;
            //check if not in opn
            //flag for in or not
            bool in_open = false;
            int open_index = -1;
            for(int i = 0;  i < open->size(); i++){
                if(x == open->at(i)){
                    in_open = true;
                    open_index = i;
                }
            }
            //cout << "The value of in open is " << in_open << endl;
            bool tenative_is_better = false;
            if(in_open == false) {
                //open->push_back(x);
                tenative_is_better = true;
            }
            else if(tenative_g < x->g){
                tenative_is_better = true;
            }
            else {
                //tenative_is_better = false;
                return;
            }
            if(tenative_is_better == true){
                //how to update correctly
                //if just placed than access in_open.back()
                //if not placed, find it in open
                if(in_open == false){
                    x->g = tenative_g;
                    x->h = manhattan(goal,x);
                    x->f = x->g + x->h;
                    open->push_back(x);
                }
                else{
                    open->at(open_index)->g = tenative_g;
                    open->at(open_index)->h = manhattan(goal,x);
                    open->at(open_index)->f = open->at(open_index)->g + open->at(open_index)->h;
                }
            }
}
void solve(board *goal, board *current){
    vector<board *> closed;
    vector<board *> open;
    //Initialize values of current
    current->g = 0;
    current->h = manhattan(goal,current);
    current->f = current->h;
    open.push_back(current);
    while(!open.empty()){
        //find entry in open with the lowest f value
        int lowest_index = 0;
        for(int i = 0; i < open.size(); i++) {
            if(open[i]->f < open[lowest_index]->f) {
                lowest_index = i;
            }
        }
        board *x = open[lowest_index];
        board temp(x->rowSize, x->elements); 
        //board temp = *x;
        temp.boardSize = x->boardSize;
        temp.zeroIndex = x->zeroIndex;
        temp.upIndex = x->upIndex;
        temp.downIndex = x->downIndex;
        temp.leftIndex = x->leftIndex;
        temp.rightIndex = x->rightIndex;
        temp.g = x->g;
        temp.h = x->h;
        temp.f = x->f;
        x = &temp;
        x->updateIndexes();
        printf("The value of x is  n");
        for(int i = 0; i < x->boardSize; i++){
            printf("%d", x->elements[i]);
        }
        cout << endl;
        //stop if the goal has been reached
        if(x->h == goal->h) {
            //return answer
            return;
        }
        closed.push_back(x);
        open.erase(open.begin()+lowest_index);
        /*if(x->upIndex >= 0){
            board *y = x;
            board temp_y(y->rowSize, y->elements);
            y = &temp_y;
            y->moveUp();
            browseNeighbor(goal, y, &open, &closed);
        }
        if(x->downIndex >= 0){
            board *y = x;
            board temp_y(y->rowSize, y->elements);
            y = &temp_y;
            y->moveDown();
            browseNeighbor(goal, y, &open, &closed);
        }
        */
        if(x->leftIndex >= 0){
            board *y = x;
            board temp_y(y->rowSize, y->elements);// = *y;
            temp_y.boardSize = y->boardSize;
            temp_y.zeroIndex = y->zeroIndex;
            temp_y.upIndex = y->upIndex;
            temp_y.downIndex = y->downIndex;
            temp_y.leftIndex = y->leftIndex;
            temp_y.rightIndex = y->rightIndex;
            temp_y.g = y->g;
            temp_y.h = y->h;
            temp_y.f = y->f;
            y = &temp_y;
            y->moveLeft();
            y->updateIndexes();
            browseNeighbor(goal, y, &open, &closed);    
        }
        /*
        if(x->rightIndex >= 0){
            board *y = x;
            board temp_y(y->rowSize, y->elements);
            y = &temp_y;
            y->moveRight();
            browseNeighbor(goal, y, &open, &closed);
        }*/
    }
}
int main(){
    const int N = 3;
    int testArray[N*N] = {1,2,3,4,5,6,7,0,8}; //only need to move 8 to the left to solve
    int target[N*N] = {1,2,3,4,5,6,7,8,0}; //target state
    board a(N, target);
    board b(N, testArray);
    b.updateIndexes();
    board *goal = &a;
    board *test = &b;
    solve(goal, test);
}

一些通用风格评论:

  • 试着去掉指针(在传递给函数时更喜欢使用引用,std::vector用于保存数据,最后使用智能指针)
  • 了解常量正确性

我认为问题出在你的解决程序中。你正在获取各种指向临时对象的指针,当循环再次循环时,这些指针就会消失。