我正在研究一种A星算法来解决N平铺幻灯片拼图。给出一个特定的目标状态我想找到解决它的最少步骤数。我理解算法,但由于我缺乏理解,我遇到了C ++问题。任何风格的建议也会受到高度赞赏。
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);
}
答案 0 :(得分:1)
一些一般风格的评论:
我认为问题出在你的解决程序中。您正在使用各种指向临时对象的指针,然后当循环再次出现时它们会消失。