莫名其妙的错误,高手请进(关于头文件出错问题)

时间:2022-09-20 10:43:09
这是我编的人工智能问题的解答。
题目要求为:
(一) 实现A*算法框架
设计一个能适应所有情况的A*算法抽象类,其中
设定节点类为Node_T
建议使用向量来表示Open,Close表
设置排序函数为Sort()方法,为抽象方法
设置生成器与评价器方法,为抽象方法
写出搜索算法Search()方法,其中调用了上述数据结构与抽象方法。
  (二)实例化抽象类
八数码算法不同效果:
宽度优先 (则没有不用调用排序算法了)
启发函数为:W(n)(即错位个数)
启发函数为:P(n)错位距离
启发函数为:混合型f=3S(n)+p(n)
可以在生成器中加入深度限制


S(n)是对节点n中张牌排列顺序的计分值,规定对非中心位置的张牌,顺某一方向检查,若某一张牌后面跟的后继者和目标状态相应张牌的顺序相比不一致时,则该张牌估分取2,一致时则估分取0;对中心位置有张牌时估分取1,无张牌时估分值取0;所有非中心位置每个张牌估分总和加上中心位置的估分值定义为S(n)。依据这些启发信息,取h(n)=P(n)+3S(n)时,就是用f(n)=g(n)+P(n)+3S(n)来估计最佳路径的耗散值。f(n)值小的节点,确能反映该节点愈有希望处于到达目标节点的最佳路径上 

// 抽象类a_start_abstract_class.h
#include <vector>

using namespace std;

#ifndef __a_start_abstract_class__
#define __a_start_abstract_class__
// ----------------------------private---------------------------------
// |1|2|3|
// |8|0|4|
// |7|6|5|

namespace {
const int DefaultArray[10] = {1, 2, 3, 8, 0, 4, 7, 6, 5};
}


// -----------------------interface-----------------------------
struct Node
{
int Array[3][3]; // 定义一个存放八数码数据的二维数组
int Depth; // 该搜索节点在搜索树中的深度
// int Cost; // 前段代价,从根状态到当前状态的跳步费用,后段代价不用保存
int Value; // 评价函数计算的值,每扩展一次都会重新计算此值
bool isExpanded; // 该节点是否已经被扩展,用于消除重复状态,当isExpanded为true时,此结点在CLOSE表中,否则在OPEN表中
Node * Parent; // 父节点指针
Node * Child; // 最优路径上的子节点指针,当打印搜索结果时用
};


class Node_T
{
public:
virtual void Create(int l = 8); 
virtual void Create(int* Array, int l = 8);
virtual void Free() = 0; // 析构结点对象
virtual Node * Search() = 0; // 搜索函数,用来生成执行路径,为主要函数
void SetLimit(int i = 8); // 设置限制值
void SetFinalNode(const int* Array = DefaultArray); // 设置最终状态
virtual Node* MOVE_FIRST();      // 指示取OPEN表首的节点作为当前要被扩展的节点n,同时将节点n移到CLOSE表

public:
Node *CurrentNode; // 指示当前结点
/* 
设置一个指针数组,用来指向所生成的子结点
 为了更加容易实现,这个二维指针数组的个数为实际的子结点个数+1
 在八数码情况下,该数组长度为4
*/
Node **CurrentNodeTailer;
Node *Header; // 指示搜索树初始状态结点

private:
explicit Node_T(int l); // 构造函数
explicit Node_T(int* Array, int l); // Array代表八数码,l表示为最大结点限制深度
virtual ~Node_T() = 0; // 析构函数,定义为抽象函数

private:
int limit; // 生成器的深度限制,默认为8

protected:
/* OPEN表,CLOSE表定义 
 * 另:如果OPEN和CLOSE表用集合来实现会更加容易,不过由于题目要求,就只好用向量
 * OPEN,CLOSE表用来存放指针
 */
static vector<Node *> OPEN,  CLOSE;
static int FinalNode[9]; // finalNode 为最终状态

protected:
virtual bool Sort(Node* T[], int (*func)()) = 0; // 排序函数,根据启发式函数func来排序
virtual int f(int (*p)(void)) = 0; // 评价函数
virtual int g() = 0; // 前段代价,可以认为是当前代价
// virtual int h() = 0; // 后段代价
};

inline void Node_T::SetLimit(int i)
{
limit = i;
}
#endif

//实现
#pragma warning(disable: 4786)
#include "a_start_abstract_class.h"
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <vector>
#include <string>


using namespace std;

// 定义无名命名空间
namespace 
{
// 初始化结点,可以得到一个比较理想的随机状态
void InitNodeArray(Node *T)
{
srand( (unsigned)time( NULL ) ); // 以当前时间作为随机值
int tem, Array[10];
for (int i = 0; i < 9; ++i)
{
bool flat = false;
do
{
tem = rand() % 9; // 取得任一9以内的数值,不包括9
for (int j = 0; j < 9; ++j)
{
if (Array[j] == tem)
{
flat = true;
}
else
{
flat = false;
}
}
} while (flat);
Array[i] = tem; // 当tem不在数组之内时
}

for (int k = 0; k < 3; ++k)
{
for (int l = 0; l < 3; ++l)
{
T->Array[k][l] = Array[k + 3*l];
}
}
}

void InitNode(Node* T)
{
T->Depth = 0; // 初始结点深度为0
// T->Cost = 0; // 代价为0
T->Value = 0; // 启发函数值为0
T->isExpanded = true; // 父结点默认为已经扩展
T->Parent = 0; // 没有父结点
T->Child = 0; // 也没有孩子结点, pity
}

class Err
{
public:
Err(string msg)
{
errMsg = msg;
}
private:
string errMsg;
};
// 函数对象,用来从CLOSE表中找到待删除结点
}

Node_T::Node_T(int l)
{
SetLimit(l);
Header = new Node;
InitNodeArray(Header);
InitNode(Header);
CLOSE.empty();
// CLOSE.push_back(Header); // 把初始结点放到扩展表CLOSE中
OPEN.empty(); // 初始结点暂时还没有子结点
}

Node_T::Node_T(int* Array, int l)
{
SetLimit(l);
try
{
Header = new Node;
if (Header == 0)
{
Err NewErr("申请内存出错啦!");
throw NewErr;
}
}
catch (Err)
{
while (1)
{
Header = new Node; // 重新申请内存,不过这样会比较耗费CPU时间
if (Header != 0)
break;
}

}

for (int k = 0; k < 3; ++k)
{
for (int m = 0; m < 3; ++m)
{
Header->Array[k][m] = Array[k + 3*l];
}
}
InitNode(Header);
// CLOSE.insert(Header);
OPEN.clear(); // 这句可以不用
}

// 实例化结点对象
void Node_T::Create(int l)
{

Node_T::Node_T(l);
}

void Node_T::Create(int* Array, int l)
{
Node_T::Node_T(Array, l);
}

void Node_T::SetFinalNode(const int* Array)
{
for (int i = 0; i < 9; ++i)
{
FinalNode[i] = Array[i];
}
}

Node* Node_T::MOVE_FIRST()
{
vector<Node *>::iterator it = OPEN.begin();
CLOSE.push_back(*it);
OPEN.erase(it); // 从OPEN表移去当前要被扩展的节点
*it = CLOSE.back();
return static_cast<Node *>(*it);
}



//

8 个解决方案

#1


帖太长了,分段再贴
派生类
#include "a_start_abstract_class.h"
#include <vector>
#include <set>

using namespace std;

#ifndef __a_start_class__
#define __a_start_class__
class eightCode: public Node_T
{
public:
void Create(int l = 8); // 实例化结点对象
void Create(int* Array, int l = 8);
void Free(); // 析构结点对象
Node* Search();

private:
explicit eightCode(int l); // 构造函数
explicit eightCode(int* Array, int l);
~eightCode(); // 析构函数
// set<Node *> SNS;

bool Sort(Node* T[], int (*func)); // 排序函数
int f(int (*p)(void)); // 评价函数 = 前段代价 + 后段代价, 在这里根据函数指针p来选择相应的评估函数作为后段代价
int g(); // 前段代价,可以认为是当前结点深度
int d(); // 尝试优先
int w(); // 错位个数
int p(); // 错位距离
int s(); // 
int mix();  // 混合型
}

#endif

// 实现

#pragma warning(disable: 4785)
#include "a_start_class.h"
#include <vector>
#include <iostream>
#include <stack>

using namespace std;

eightCode::eightCode(int l)
{
Node_T::Node_T(l);
// SNS.clear();
}

eightCode::eightCode(int* Array, int l)
{
Node_T::Node_T(Array, l);
// SNS.clear();
}

/* 清除申请的内存
*  利用深度遍历清空节点
*/
eightCode::~eightCode()
{
stack<Node *> freeandhaha;
Node * TT;
int i;  // looper
freeandhaha.push(Node_T::Header); // 把header所指向的内存存入栈中,所以header指针所指向的东西就可以为空了啦。
Header = 0; // 置空,防止野指针
while (!freeandhaha.empty()) // 栈不空,则继续做
{
TT = freeandhaha.pop();
for (i = 0; i < 4; ++i)
{
if (TT->Child[i])
{
freeandhaha.push(TT->Child[i]);
}
}
delete TT->Child; // 把指针数组删除
TT->Child = 0;
delete TT; // 把TT的内容删除
TT = 0;
}
}

void eightCode::Create(int l)
{
eightCode(l);
}

void eightCode::Create(int* Array, int l)
{
eightCode(Array, l);
}

void eightCode::Free()
{
eightCode::~eightCode();
}

// p 为函数指针,用所选择的评价函数做为指针传入即可
int eightCode::f(int (*p)(void))
{
return *p() + g();
}

// 这个函数可以内联的,不过为了美观则写在这里了
int eightCode::g()
{
return Node_T::CurrentNode->Depth;
}

// 深度优先
int eightCode::d()
{
return 0;
}

// 错位个数
int eightCode::w()
{
int ErrNum = 0;
Node* Temp = Node_T::CurrentNode;
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
if (Temp->Array[i][j] != FinalNode[3*j + i])
{
++ErrNum;
}
}
}
return ErrNum;
}

int eightCode::p()
{
int i, j, k, ErrDistance = 0;
Node* Temp = Node_T::CurrentNode;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 3; ++j)
{
for (k = 0; k < 9; ++k)
{
if (Temp->Array[i][j] == FinalNode[k])
{
break;
}
}
ErrDistance += k - 1;
}
}
return ErrDistance;
}

int eightCode::s()
{
int Num = 0;
Node* Temp = Node_T::CurrentNode;
for (int i = 0; i < 2; ++i)
{
if (Temp->Array[0][i+1] != (Temp->Array[0][i] + 1))
{
Num += 2;
}
/* else
Num += 0; */
}

if ((Temp->Array[1][0] + 1) != Temp->Array[0][0])
{
Num += 2;
}

if (Temp->Array[1][1] != 0)
{
Num += 1;
}

if (Temp->Array[1][2] != (Temp->Array[0][2] + 1))
{
Num += 2;
}

if (Temp->Array[2][2] != (Temp->Array[1][2] + 1))
{
Num += 2;
}

for (int j = 1; j > 0; --j)
{
if (Temp->Array[2][j] != (Temp->Array[2][j+1] + 1))
Num += 2;
}

return Num;
}

int eightCode::mix()
{
return 3 * s() + p();
}

bool eightCode::Sort(Node* T[], int (*func)())
{

}

namespace
{
bool CompareArr(int* OrientedArr, int* FinallArr)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
if (OrientedArr[i][j] != FinallArr[3*j + i])
{
return false;
}
}
}

return true;
}

void ExchangeData(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
// 函数对象ItCmp
class ItCmp
{
public:
bool operator()(Node* A, Node* B)
{
return A->Value < B->Value;
}
};
}

#2


// 返回一个搜索结果路径,如果搜索不到结果则返回0
// func表示搜索时所选择的评估函数
Node* eightCode::Search(int (*func)())
{
int i, j, k; // 循环变量

// 步骤1
Node* G = Node_T::Header;

// 步骤2
OPEN.push_back(Header);
CLOSE.clear();

while (1)
{
// 步骤3
if (OPEN.empty())
{
return 0;
}

// 步骤4
CurrentNode = MOVE_FIRST();

// 步骤5
if (CompareArr(CurrentNode->Array, FinalNode))
{
return G;
}

// 步骤6扩展当前结点
CurrentNodeTailer = new Node [4];
CurrentNode->Child = CurrentNodeTailer; // 只需一条语句,则可以使当前结点指向四个子结点
  // 变换状态
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 3; ++j)
{
for (k = 0; k < 3; ++k)
{
CurrentNodeTailer[i]->Array[j][k] = CurrentNode->Array[j][k];
}
}
CurrentNodeTailer[i]->Depth = CurrentNode->Depth + 1;
CurrentNodeTailer[i]->isExpanded = false;
// CurrentNodeTailer[i]->Parent = CurrentNode;
CurrentNodeTailer[i]->Child = 0;
CurrentNodeTailer[i]->Value = f(func);
}
ExchangeData(CurrentNodeTailer[0]->Array[0][1], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[1]->Array[1][0], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[2]->Array[1][2], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[3]->Array[2][1], CurrentNodeTailer[0]->Array[1][1]);

// 步骤7,对SNS中的子节点分为3类
vector<Node *>::iterator it;
  // 已经出现在OPEN表中的结点,不会出现在CLOSE表中
for (it = OPEN.begin(); it != OPEN.end(); ++it)
{
for (i = 0; i < 4; ++i)
if (CompareArr(static_cast<Node *>(it)->Array, CurrentNodeTailer[i]->Array))
{ // 出现在OPEN表中时
if (static_cast<Node *>(it)->Value > CurrentNodeTailer[i]->Value)
{// 如果老父节点的评价函数值大于新父节点的值,则此节点的父指针指向新父节点则为CurrentNode
static_cast<Node *>(it)->Parent = CurrentNode; 
}
delete CurrentNodeTailer[i]; // 把多余的节点删除
CurrentNodeTailer[i] = 0;
}
}

for (it = CLOSE.begin(); it != CLOSE.end(); ++it)
{
for (i = 0; i < 4; ++i)
if (CompareArr(static_cast<Node *>(it)->Array, CurrentNodeTailer[i]->Array))
{ // 出现在OPEN表中时
if (static_cast<Node *>(it)->Value > CurrentNodeTailer[i]->Value)
{/*
 * 如果老父节点的评价函数值大于新父节点的值,
 * 则此节点的父指针指向新父节点则为CurrentNode,
 * 并把这些子节点从CLOSE表中移出,重新加入OPEN表中;
 */ 
static_cast<Node *>(it)->Parent = CurrentNode; 
OPEN.push_back(static_cast<Node *>(it));
CLOSE.erase(it);
}
// 删除多余的结点
delete CurrentNodeTailer[i]; 
CurrentNodeTailer[i] = 0;
}
}

for (i = 0; i < 4; ++i)
{ // 如果父指针为空,则为全新结点
if (CurrentNodeTailer[i]->Parent == 0)
{
CurrentNodeTailer[i]->Parent = CurrentNode;
OPEN.push_back(CurrentNode);
}
}

/* 步骤8
 * 因为评估值在前面已经计算过,所以在这里就不用对OPEN表的结点计算评估值了
 * 在这里运用泛型算法sort对vector类型的OPEN进行排序
 * 一句语句即可,够简洁吧!
 */ 
stable_sort(OPEN.begin(), OPEN.end(), ItCmp());
// 步骤9返回步骤3
}
}

// 测试文件
#include "a_start_class.h"
#include <iostream>

using namespace std;

int main()
{
eightCode* obj;
obj->Create(10);
obj->Search(obj->d());
obj->Free();
}

这个测试只是用来检测算法是否通过的!并没有把解答路径等求出。


上面的代码在编译时顺利通过,但是在连接时就出现下面的问题。
--------------------Configuration: AI - Win32 Debug--------------------
Compiling...
a_start.cpp
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : error C2143: syntax error : missing ';' before 'string'
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : fatal error C1004: unexpected end of file found
test.cpp
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : error C2143: syntax error : missing ';' before 'string'
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : fatal error C1004: unexpected end of file found
Error executing cl.exe.

AI.exe - 4 error(s), 0 warning(s)


小弟一般比较少提问的,大多都通过搜索得到答案,不过这个问题不好找到解答。望高手给予帮助!

#3


该算法如下
A*算法过程

算法定义
s--指示初始状态结点;
G--指示搜索图;
OPEN--作为存放待扩展节点的表;
CLOSE--作为存放已被扩展节点的表;
MOVE_FIRST(OPEN)—指示取OPEN表首的节点作为当前要被扩展的节点n,同时将节点n移到CLOSE表;
SNS--子节点集合。
f(n) = g(n) + h(n);// 评价函数f
n--搜索图中某个当前被扩展的节点;
f(n)--从初始状态节点s,经由节点n到达目标状态节点 
g(n)--从s到n,估计的最小路径代价;
h(n)--从n到 ,估计的最小路径代价;

该算法的一般实现过程如下:
1、G := s; 
2、OPEN := (S), CLOSE := ();
3、若OPEN是空表,则算法以失败结束;
4、n := MOVE-FIRST(OPEN);
5、若n是目标状态节点,则搜索成功结束,并给出解答路径;
6、扩展节点n,将非节点n祖先的子节点置于子节点集合SNS中,并插入搜索图G中,对于SNS中的每个子节点 ,计算f(n,  ) = g(n,  ) + h( );
7、句标记和修改指针:
&#8226;把SNS中的子节点分为3类:
①全新节点;
②己出现于OPEN表的节点;
③己出现于CLOSE表的节点;
&#8226;加第一类子节点于OPEN表,并建立从子节点到父节点n的指针;
&#8226;比校第2类子节点 经由新、老父节点的评价函数值f( ) = f(n,  ),并移动子节点指向老父节点的指针,改为指向新父节点。
&#8226;对于第三类子节点作与第2类同样的处理,并把这些子节点从CLOSE表中移出,重新加入OPEN表中;
8、启发式算法A按f(n)排序OPEN表中的节点,f(n)值最小者排在首位,优先加以扩展,体现了最佳优先(Best-first)搜索策略的思想。
9、返回语句3

#4


先收下再看

#5


哈哈,其实也不用怎么看,算法上应该是没有问题的了,只是不知道在那里出错了。

#6


相应的评估函数作为后段代价
int g(); // 前段代价,可以认为是当前结点深度
int d(); // 尝试优先
int w(); // 错位个数
int p(); // 错位距离
int s(); // 
int mix();  // 混合型
}          //need ;(semicolon)

#endif

派生类结束的时候少了分号.
不过,你里面还有一些错误,比如构造函数用的是private,如果你只是封装一个基类,那么可以声明为protect,如果不是的话,建议为public,不然你的测试方法就不能用了.另外,析构也是一样,如果你的类支持指针类型的声明,最好声明为public, 而且是virtual.如果只是派生类做为实例用,也可以用protect,建议不要用private.

#7


哦,我是在effective C++看到的,现在来实用一下
我在看看有没有问题!

#8


problem solve!
给分!
走人!

#1


帖太长了,分段再贴
派生类
#include "a_start_abstract_class.h"
#include <vector>
#include <set>

using namespace std;

#ifndef __a_start_class__
#define __a_start_class__
class eightCode: public Node_T
{
public:
void Create(int l = 8); // 实例化结点对象
void Create(int* Array, int l = 8);
void Free(); // 析构结点对象
Node* Search();

private:
explicit eightCode(int l); // 构造函数
explicit eightCode(int* Array, int l);
~eightCode(); // 析构函数
// set<Node *> SNS;

bool Sort(Node* T[], int (*func)); // 排序函数
int f(int (*p)(void)); // 评价函数 = 前段代价 + 后段代价, 在这里根据函数指针p来选择相应的评估函数作为后段代价
int g(); // 前段代价,可以认为是当前结点深度
int d(); // 尝试优先
int w(); // 错位个数
int p(); // 错位距离
int s(); // 
int mix();  // 混合型
}

#endif

// 实现

#pragma warning(disable: 4785)
#include "a_start_class.h"
#include <vector>
#include <iostream>
#include <stack>

using namespace std;

eightCode::eightCode(int l)
{
Node_T::Node_T(l);
// SNS.clear();
}

eightCode::eightCode(int* Array, int l)
{
Node_T::Node_T(Array, l);
// SNS.clear();
}

/* 清除申请的内存
*  利用深度遍历清空节点
*/
eightCode::~eightCode()
{
stack<Node *> freeandhaha;
Node * TT;
int i;  // looper
freeandhaha.push(Node_T::Header); // 把header所指向的内存存入栈中,所以header指针所指向的东西就可以为空了啦。
Header = 0; // 置空,防止野指针
while (!freeandhaha.empty()) // 栈不空,则继续做
{
TT = freeandhaha.pop();
for (i = 0; i < 4; ++i)
{
if (TT->Child[i])
{
freeandhaha.push(TT->Child[i]);
}
}
delete TT->Child; // 把指针数组删除
TT->Child = 0;
delete TT; // 把TT的内容删除
TT = 0;
}
}

void eightCode::Create(int l)
{
eightCode(l);
}

void eightCode::Create(int* Array, int l)
{
eightCode(Array, l);
}

void eightCode::Free()
{
eightCode::~eightCode();
}

// p 为函数指针,用所选择的评价函数做为指针传入即可
int eightCode::f(int (*p)(void))
{
return *p() + g();
}

// 这个函数可以内联的,不过为了美观则写在这里了
int eightCode::g()
{
return Node_T::CurrentNode->Depth;
}

// 深度优先
int eightCode::d()
{
return 0;
}

// 错位个数
int eightCode::w()
{
int ErrNum = 0;
Node* Temp = Node_T::CurrentNode;
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
if (Temp->Array[i][j] != FinalNode[3*j + i])
{
++ErrNum;
}
}
}
return ErrNum;
}

int eightCode::p()
{
int i, j, k, ErrDistance = 0;
Node* Temp = Node_T::CurrentNode;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 3; ++j)
{
for (k = 0; k < 9; ++k)
{
if (Temp->Array[i][j] == FinalNode[k])
{
break;
}
}
ErrDistance += k - 1;
}
}
return ErrDistance;
}

int eightCode::s()
{
int Num = 0;
Node* Temp = Node_T::CurrentNode;
for (int i = 0; i < 2; ++i)
{
if (Temp->Array[0][i+1] != (Temp->Array[0][i] + 1))
{
Num += 2;
}
/* else
Num += 0; */
}

if ((Temp->Array[1][0] + 1) != Temp->Array[0][0])
{
Num += 2;
}

if (Temp->Array[1][1] != 0)
{
Num += 1;
}

if (Temp->Array[1][2] != (Temp->Array[0][2] + 1))
{
Num += 2;
}

if (Temp->Array[2][2] != (Temp->Array[1][2] + 1))
{
Num += 2;
}

for (int j = 1; j > 0; --j)
{
if (Temp->Array[2][j] != (Temp->Array[2][j+1] + 1))
Num += 2;
}

return Num;
}

int eightCode::mix()
{
return 3 * s() + p();
}

bool eightCode::Sort(Node* T[], int (*func)())
{

}

namespace
{
bool CompareArr(int* OrientedArr, int* FinallArr)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
if (OrientedArr[i][j] != FinallArr[3*j + i])
{
return false;
}
}
}

return true;
}

void ExchangeData(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
// 函数对象ItCmp
class ItCmp
{
public:
bool operator()(Node* A, Node* B)
{
return A->Value < B->Value;
}
};
}

#2


// 返回一个搜索结果路径,如果搜索不到结果则返回0
// func表示搜索时所选择的评估函数
Node* eightCode::Search(int (*func)())
{
int i, j, k; // 循环变量

// 步骤1
Node* G = Node_T::Header;

// 步骤2
OPEN.push_back(Header);
CLOSE.clear();

while (1)
{
// 步骤3
if (OPEN.empty())
{
return 0;
}

// 步骤4
CurrentNode = MOVE_FIRST();

// 步骤5
if (CompareArr(CurrentNode->Array, FinalNode))
{
return G;
}

// 步骤6扩展当前结点
CurrentNodeTailer = new Node [4];
CurrentNode->Child = CurrentNodeTailer; // 只需一条语句,则可以使当前结点指向四个子结点
  // 变换状态
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 3; ++j)
{
for (k = 0; k < 3; ++k)
{
CurrentNodeTailer[i]->Array[j][k] = CurrentNode->Array[j][k];
}
}
CurrentNodeTailer[i]->Depth = CurrentNode->Depth + 1;
CurrentNodeTailer[i]->isExpanded = false;
// CurrentNodeTailer[i]->Parent = CurrentNode;
CurrentNodeTailer[i]->Child = 0;
CurrentNodeTailer[i]->Value = f(func);
}
ExchangeData(CurrentNodeTailer[0]->Array[0][1], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[1]->Array[1][0], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[2]->Array[1][2], CurrentNodeTailer[0]->Array[1][1]);
ExchangeData(CurrentNodeTailer[3]->Array[2][1], CurrentNodeTailer[0]->Array[1][1]);

// 步骤7,对SNS中的子节点分为3类
vector<Node *>::iterator it;
  // 已经出现在OPEN表中的结点,不会出现在CLOSE表中
for (it = OPEN.begin(); it != OPEN.end(); ++it)
{
for (i = 0; i < 4; ++i)
if (CompareArr(static_cast<Node *>(it)->Array, CurrentNodeTailer[i]->Array))
{ // 出现在OPEN表中时
if (static_cast<Node *>(it)->Value > CurrentNodeTailer[i]->Value)
{// 如果老父节点的评价函数值大于新父节点的值,则此节点的父指针指向新父节点则为CurrentNode
static_cast<Node *>(it)->Parent = CurrentNode; 
}
delete CurrentNodeTailer[i]; // 把多余的节点删除
CurrentNodeTailer[i] = 0;
}
}

for (it = CLOSE.begin(); it != CLOSE.end(); ++it)
{
for (i = 0; i < 4; ++i)
if (CompareArr(static_cast<Node *>(it)->Array, CurrentNodeTailer[i]->Array))
{ // 出现在OPEN表中时
if (static_cast<Node *>(it)->Value > CurrentNodeTailer[i]->Value)
{/*
 * 如果老父节点的评价函数值大于新父节点的值,
 * 则此节点的父指针指向新父节点则为CurrentNode,
 * 并把这些子节点从CLOSE表中移出,重新加入OPEN表中;
 */ 
static_cast<Node *>(it)->Parent = CurrentNode; 
OPEN.push_back(static_cast<Node *>(it));
CLOSE.erase(it);
}
// 删除多余的结点
delete CurrentNodeTailer[i]; 
CurrentNodeTailer[i] = 0;
}
}

for (i = 0; i < 4; ++i)
{ // 如果父指针为空,则为全新结点
if (CurrentNodeTailer[i]->Parent == 0)
{
CurrentNodeTailer[i]->Parent = CurrentNode;
OPEN.push_back(CurrentNode);
}
}

/* 步骤8
 * 因为评估值在前面已经计算过,所以在这里就不用对OPEN表的结点计算评估值了
 * 在这里运用泛型算法sort对vector类型的OPEN进行排序
 * 一句语句即可,够简洁吧!
 */ 
stable_sort(OPEN.begin(), OPEN.end(), ItCmp());
// 步骤9返回步骤3
}
}

// 测试文件
#include "a_start_class.h"
#include <iostream>

using namespace std;

int main()
{
eightCode* obj;
obj->Create(10);
obj->Search(obj->d());
obj->Free();
}

这个测试只是用来检测算法是否通过的!并没有把解答路径等求出。


上面的代码在编译时顺利通过,但是在连接时就出现下面的问题。
--------------------Configuration: AI - Win32 Debug--------------------
Compiling...
a_start.cpp
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : error C2143: syntax error : missing ';' before 'string'
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : fatal error C1004: unexpected end of file found
test.cpp
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : error C2143: syntax error : missing ';' before 'string'
c:\program files\microsoft visual studio\vc98\include\wchar.h(38) : fatal error C1004: unexpected end of file found
Error executing cl.exe.

AI.exe - 4 error(s), 0 warning(s)


小弟一般比较少提问的,大多都通过搜索得到答案,不过这个问题不好找到解答。望高手给予帮助!

#3


该算法如下
A*算法过程

算法定义
s--指示初始状态结点;
G--指示搜索图;
OPEN--作为存放待扩展节点的表;
CLOSE--作为存放已被扩展节点的表;
MOVE_FIRST(OPEN)—指示取OPEN表首的节点作为当前要被扩展的节点n,同时将节点n移到CLOSE表;
SNS--子节点集合。
f(n) = g(n) + h(n);// 评价函数f
n--搜索图中某个当前被扩展的节点;
f(n)--从初始状态节点s,经由节点n到达目标状态节点 
g(n)--从s到n,估计的最小路径代价;
h(n)--从n到 ,估计的最小路径代价;

该算法的一般实现过程如下:
1、G := s; 
2、OPEN := (S), CLOSE := ();
3、若OPEN是空表,则算法以失败结束;
4、n := MOVE-FIRST(OPEN);
5、若n是目标状态节点,则搜索成功结束,并给出解答路径;
6、扩展节点n,将非节点n祖先的子节点置于子节点集合SNS中,并插入搜索图G中,对于SNS中的每个子节点 ,计算f(n,  ) = g(n,  ) + h( );
7、句标记和修改指针:
&#8226;把SNS中的子节点分为3类:
①全新节点;
②己出现于OPEN表的节点;
③己出现于CLOSE表的节点;
&#8226;加第一类子节点于OPEN表,并建立从子节点到父节点n的指针;
&#8226;比校第2类子节点 经由新、老父节点的评价函数值f( ) = f(n,  ),并移动子节点指向老父节点的指针,改为指向新父节点。
&#8226;对于第三类子节点作与第2类同样的处理,并把这些子节点从CLOSE表中移出,重新加入OPEN表中;
8、启发式算法A按f(n)排序OPEN表中的节点,f(n)值最小者排在首位,优先加以扩展,体现了最佳优先(Best-first)搜索策略的思想。
9、返回语句3

#4


先收下再看

#5


哈哈,其实也不用怎么看,算法上应该是没有问题的了,只是不知道在那里出错了。

#6


相应的评估函数作为后段代价
int g(); // 前段代价,可以认为是当前结点深度
int d(); // 尝试优先
int w(); // 错位个数
int p(); // 错位距离
int s(); // 
int mix();  // 混合型
}          //need ;(semicolon)

#endif

派生类结束的时候少了分号.
不过,你里面还有一些错误,比如构造函数用的是private,如果你只是封装一个基类,那么可以声明为protect,如果不是的话,建议为public,不然你的测试方法就不能用了.另外,析构也是一样,如果你的类支持指针类型的声明,最好声明为public, 而且是virtual.如果只是派生类做为实例用,也可以用protect,建议不要用private.

#7


哦,我是在effective C++看到的,现在来实用一下
我在看看有没有问题!

#8


problem solve!
给分!
走人!