C++中的一个星形实现(语言问题)
A star implementation in C++ (Language Issues)
我正在研究一个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用于保存数据,最后使用智能指针)
- 了解常量正确性
我认为问题出在你的解决程序中。你正在获取各种指向临时对象的指针,当循环再次循环时,这些指针就会消失。
相关文章:
- 了解算法的性能差异(如果以不同的编程语言实现)
- 语言分析的二叉树实现 - 子节点:不起作用
- 如何用AOT编译的语言实现匿名函数
- 使用 LLVM IR 实现动态类型语言
- V8 JavaScript 引擎实现语言
- 变量大小取决于语言机器实现,这意味着什么
- 在flex,bison,c ++中实现Wolfram语言
- 在 C 语言中转换C++向量的实现
- C 语言中的文件访问,用于实现协议 OPC UA
- 我怎样才能用另一种语言(也许C++)实现Python集
- 实现 Web 应用程序的张量分解的最有效语言
- 基于套接字的通信独立于用于实现它的编程语言.怎么可能
- 我可以使用JSON在用不同编程语言实现的进程之间进行通信吗
- 用脚本语言实现lambdas
- 用c语言实现密码安全的程序
- 用FFTW在C语言中实现FFT低通滤波器
- c++实现文件中的getter语言 - setter
- C/ c++中定义的操作符在哪里,它们在这些语言中是如何实现的
- C++中的一个星形实现(语言问题)
- internet explorer语言 - 通过c++实现OLE自动化是一个很好的选择吗?