/*
连连看游戏设计:
主要包含游戏局面的状态描述,游戏规则的描述:状态的合法转移(哪些操作满足规则,经过这些操作,达到哪些状态)。自动机模型适合描述游戏设计。
如何求出相同图形之间的最短路径,最短路径的转弯数目最少,转弯数目最少时,经过格子数目尽可能少。
最短路径中:把最短路径问题的目标函数改为从一个点到另一个店的转弯次数。广度优先搜索
首先把图形A(x1,y1)压入队列,然后扩展A(x1,y1)可以直线到达的格子,假设这些格子的集合为S0,S0 =Find(x1,y1),如果图形B(x2,y2)在S0zhong ,结束搜索。
A和B可以用直线连接。
否则,低于所有S0集合中的空格子(没有图形),分别找到它们可以直线到达的格子,假设该集合为S1 = {Find(p)|p属于S0},S1包含了S0,令S1'= S1 - S0,
则S1'中的格子和图形A(x1,y1)可以通过转弯数目为1的路径连接。如果图形B在S1'中,可以用转弯数目为1的路径连接。
否则,对S1'中集合的空格子,找出可直线到达的格子集合,记为S2,S2' = S2 - S0-S1,若B在S2'ZHong,可以用转弯数为 2的路径连接。
扩展的过程中,记下每个格子从哪个格子连过来的(转弯的位置),最后图形A和B之间的路径可以绘制出来。
S1' = S1 - S0,S2' = S2 - S0 - S1,可以通过记录从图形A(x1,y1)到该格子(x,y)的转弯数目实现。开始,将所有格子(x,y)和格子A(x1,y1)之间路径的最少转弯数目Min
Crossing(x,y)初始化为无穷大。令MinCrossing(A) = MinCrossing(x1,y1) = 0,格子A到自身当然不需要转弯。第一步扩展后,所有S0集合中的格子的MinCrossing的
值为0.在S0集合继续扩展得到S1的集合中,格子X和格子A之间至少有转弯为1的路径。如果格子X本身在S0中,那么MinCrossing(X) = 0,这时,保留转弯数目少的路径
MinCrossing(X) = MinValue(MinCrossing(X),1) = 0.
每一个格子X(x,y),都有一个状态值MinCrossing(X)。记录下该格子和起始格子A之间的最优路径的转弯数目。广度优先搜索,就是每次优先扩展状态值最少的格子。
如果要保证转弯数目最少的情况下,保持路径长度尽可能短,需要对每一个格子X保存两个状态值MinCrossing(X)和MinDistance(X)。从格子X扩展到格子Y的过程,
用下面代码实现
判断死锁:
判断两个格子是否可以消去,对游戏中尚未消去的格子,两两计算一下是否可以消去。每次都是扩展出起始格子A(x1,y1)能够到达的格子。对于每一个格子,可以调用
一次上面的扩展过程,得到所有可以到达的格子。如果这些格子中有任意一个格子的图形跟起始格子一致,则可以消去,不处于死锁状态
*/
#include <stdio.h> typedef struct Pos { Pos(){} Pos(int ix,int iy):_ix(ix),_iy(iy){} int _iX; int _iY; }Pos; typedef struct Pic { }Pic; typedef struct Grid { Pos _pos; Pic _pic; int _minCrossing; int _minDistance; }Grid; int Dist(int x,int y) { return 1; } void bfs() { Grid x,y; if((x._minCrossing + 1 < y._minCrossing) || ((x._minCrossing + 1 == y._minCrossing ) && (x._minDistance(x) + Dist(x,y)))) //如果发现从格子X过来的路径改进了转弯数目或者路径的长度,则更新格子Y { y._minCrossing = x._minCrossing + 1; y._minDistance = x._minDistance + Dist(x,y); } } //如何求出相同图形之间的最短路径,最短路径的转弯数目最少,转弯数目最少时,经过格子数目尽可能少。 //最短路径中:把最短路径问题的目标函数改为从一个点到另一个店的转弯次数。广度优先搜索 bool findPath(const Grid& preClick,const Grid& curClick) { return true; } void run() { //生成游戏初始局面 Grid preClick = NULL,curClick = NULL; bool isComplete = false; while(!isComplete) { //监听用户动作 int x,y; if()//用户点击格子(x,y),且格子(x,y)为非空格子 { preClick = curClick; curClick._pos(x,y); } if(preClick != NULL && curClick != NULL && preClick._pic = curClick._pic && findPath(preClick,curClick)) //如果前后两次点击均不为空,两次图片一致,能够找到路径,那么开始尝试消去 { //显示两个格子之间的消去路径 //消去格子preClick和curClick preClick = curClick = NULL; } } } void process() { run(); } int main(int argc,char* argv[]) { process(); getchar(); return 0; }