用grid类实现棋盘
包括:
1、一维数组存储棋盘状态
2、my_index、parent存储自己下标和父节点下标
3、string str_state 实现用字符串表达棋盘状态
class grid{
public:
int state[9]; //one_dimensional_vector
int my_index;
int parent;
string str_state;
string movement; //进行到本状态'0'需执行的动作
//构造函数
grid(int state[9], int parent, string movement)
{
for(int i = 0; i < 9; i ++)
this->state[i] = state[i];
this->parent = parent;
this->movement = movement;
}
grid() {}
void create_newstate(int dir);
void Numarry_to_String();
bool isend();
};
每生成一个棋盘状态,便将其push到vector(grid)中去,实现父子节点关系的表示
map<string, int> HashMap
其中key为期盼状态,value为棋盘下标,每次生成新的棋盘状态,便在HashMap中查找有无该状态:
若有,则不生成
若没有,则生成。
stack<grid>
查找到后,用该stack存储父节点。
对读取到的节点进行上下左右四个方向生成新结点。
对于每一个给定方向(dir),判断一下能否向该方向移动:
若能,则两个点交换位置,并返回true
若不能,直接返回false
bool getNewGrid(grid &nownode,int dir)
{
int index;
for(int i = 0; i < 9; i ++)
if(nownode.state[i] == 0)
index = i;
switch (dir)
{
case -3: //index向上 i>=3
if(index >= 3)
swap(nownode.state[index],nownode.state[index-3]);
nownode.Numarry_to_String();
return true;
break;
case 3:
if(index <= 5) //index向下 i <= 5
swap(nownode.state[index],nownode.state[index+3]);
nownode.Numarry_to_String();
return true;
break;
case 1: //index 向右 i!=2,5,8;
if(index!=2 && index != 5 && index !=8 )
swap(nownode.state[index],nownode.state[index+1]);
nownode.Numarry_to_String();
return true;
break;
case -1:
if(index%3 != 0) //index向左
swap(nownode.state[index],nownode.state[index-1]);
nownode.Numarry_to_String();
return true;
break;
default:
return false;
break;
}
}
用队列存储生成的新节点。每次从队列首部开始访问,并出队列,实现宽度搜索
若搜到,则进行回推:
上述的栈此时起到了作用,先一路回溯,每遇到一个父节点就将其入栈,一直到initial节点为止。
再从栈顶开始出栈并输出,实现了每一步打印的效果。
若当前节点不是目标节点,则更新parent_index以及my_index并将该节点入vector(其中my_index就是该节点vector下标,parent_index就是父节点在vector中的下标)并将该节点入队列待搜索。
if(NewGrid.isend())
{
stack<grid> path;
grid ParentGrid = NewGrid;
path.push(ParentGrid);
while(ParentGrid.parent != -1)
{
path.push(GList[ParentGrid.parent]);
ParentGrid = GList[ParentGrid.parent];
}
//path.push(ParentGrid);
int step = 0;
while(!path.empty())
{
grid prinGrid = path.top();
path.pop();
if(step == 0) cout<<prinGrid.movement<<endl;
else
cout<<"step "<<step<<endl;
for(int i = 0; i < 9 ; i ++)
{
cout<<prinGrid.state[i]<<" ";
if(i == 2|| i ==5 || i == 8)
cout<<endl;
}
step++;
}
return true;
}
if(HashMap.find(NewGrid.str_state) == HashMap.end()) //不存在
{
HashMap.insert(pair(NewGrid.str_state,MapIndex));
MapIndex ++;
GridQueue.push(NewGrid);
}
#include
#include
#include //key: string
#include
#include
#include
using namespace std;
//哈希存储状态
class grid{
public:
int state[9]; //one_dimensional_vector
int my_index;
int parent;
string str_state;
string movement; //进行到本状态'0'需执行的动作
//构造函数
grid(int state[9], int parent, string movement)
{
for(int i = 0; i < 9; i ++)
this->state[i] = state[i];
this->parent = parent;
this->movement = movement;
}
grid() {}
void create_newstate(int dir);
void Numarry_to_String();
bool isend();
};
grid start,final;
vector<grid> GList;
void grid::Numarry_to_String()
{
for(int i = 0; i < 9 ; i ++)
{
char ch = state[i] + '0';
str_state = str_state + ch;
}
}
bool grid::isend()
{
for(int i = 0; i < 9; i ++)
if(state[i] != final.state[i])
return false;
return true;
}
map<string,int> HashMap;
bool getNewGrid(grid &nownode,int dir)
{
int index;
for(int i = 0; i < 9; i ++)
if(nownode.state[i] == 0)
index = i;
switch (dir)
{
case -3: //index向上 i>=3
if(index >= 3)
swap(nownode.state[index],nownode.state[index-3]);
nownode.Numarry_to_String();
return true;
break;
case 3:
if(index <= 5) //index向下 i <= 5
swap(nownode.state[index],nownode.state[index+3]);
nownode.Numarry_to_String();
return true;
break;
case 1: //index 向右 i!=2,5,8;
if(index!=2 && index != 5 && index !=8 )
swap(nownode.state[index],nownode.state[index+1]);
nownode.Numarry_to_String();
return true;
break;
case -1:
if(index%3 != 0) //index向左
swap(nownode.state[index],nownode.state[index-1]);
nownode.Numarry_to_String();
return true;
break;
default:
return false;
break;
}
}
int MapIndex = 2;
bool bfs()
{
queue<grid> GridQueue;
GridQueue.push(start);
string move[4] = {"up","down","left","right"};
int dir[4] = {-3,3,-1,1};
int index = 0;
while(!GridQueue.empty())
{
grid FirstGrid = GridQueue.front();
GridQueue.pop();
for(int i = 0; i < 4; i ++)
{
grid NewGrid = grid(FirstGrid.state,FirstGrid.my_index,move[i]);
if(getNewGrid(NewGrid,dir[i]))
{
GList.push_back(NewGrid);
index ++;
NewGrid.my_index = index;
if(NewGrid.isend())
{
stack<grid> path;
grid ParentGrid = NewGrid;
path.push(ParentGrid);
while(ParentGrid.parent != -1)
{
path.push(GList[ParentGrid.parent]);
ParentGrid = GList[ParentGrid.parent];
}
//path.push(ParentGrid);
int step = 0;
while(!path.empty())
{
grid prinGrid = path.top();
path.pop();
if(step == 0) cout<<prinGrid.movement<<endl;
else
cout<<"step "<<step<<endl;
for(int i = 0; i < 9 ; i ++)
{
cout<<prinGrid.state[i]<<" ";
if(i == 2|| i ==5 || i == 8)
cout<<endl;
}
step++;
}
return true;
}
if(HashMap.find(NewGrid.str_state) == HashMap.end()) //不存在
{
HashMap.insert(pair<string,int>(NewGrid.str_state,MapIndex));
MapIndex ++;
GridQueue.push(NewGrid);
}
}
}
}
return false;
}
int main()
{
int n = 9;
for(int i = 0 ; i < n ; i ++)
{
cin>>start.state[i];
}
start.parent = -1;
start.my_index = 0;
start.movement = "initial";
start.Numarry_to_String();
HashMap.insert(pair<string, int>(start.str_state,0));
GList.push_back(start);
//char enter;
//cin>>enter;
for(int i = 0; i < n ; i ++)
{
cin>>final.state[i];
}
final.Numarry_to_String();
HashMap.insert(pair<string,int>(final.str_state,1));
if(!bfs())
cout<<"no answer";
}