C ++中的明星实现(语言问题)

时间:2011-06-10 02:56:04

标签: c++ algorithm debugging pointers overloading

我正在研究一种A星算法来解决N平铺幻灯片拼图。给出一个特定的目标状态我想找到解决它的最少步骤数。我理解算法,但由于我缺乏理解,我遇到了C ++问题。任何风格的建议也会受到高度赞赏。

  • 重载操作员分配:似乎删除元素指针有问题,所以现在我手动重新分配所有内容
  • browseNeighbor:似乎做了我想要的所有事情但是被推回到开放向量的数据元素中的值似乎在求解函数中再次被访问时变得混乱。
  • 现在我只是让它访问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);
}

1 个答案:

答案 0 :(得分:1)

一些一般风格的评论:

  • 尝试摆脱指针(在传递给函数时更喜欢使用引用,使用std :: vector来保存数据,最后使用智能指针)。
  • 了解const正确性。

我认为问题出在你的解决程序中。您正在使用各种指向临时对象的指针,然后当循环再次出现时它们会消失。