新鲜出炉的连连看连接算法Python版

来源:互联网 发布:网络销售水果途径 编辑:程序博客网 时间:2024/06/10 08:21

这段时间老是“不务正业”的搞一些东西玩。之前的贪吃蛇,俄罗斯方块激发了我研究游戏算法的兴趣。经过1个星期的构思,连连看的连接算法终于出炉了。再过一段时间就基于这个算法使用JavaScript推出网页版的连连看。下面是说明及代码。

功能:为连连看游戏提供连接算法
说明:模块中包含一个Point类,该类是游戏的基本单元“点”,该类包含属性:x,y,value。
其中x,y代表了该点的坐标,value代表该点的特征:0代表没有被填充,1-8代表被填充为游戏图案,9代表被填充为墙壁
模块中还包含一个名为points的Point列表,其中保存着整个游戏界面中的每个点
使用模块的时候应首先调用createPoints方法,初始化游戏界面中每个点,然后可通过points访问到每个点,继而初始化界面
模块中核心的方法是link,通过提供源点和终点,可尝试连接两点,如果可以连接则返回保存路径的path列表,否则返回False

鸣谢:感谢我的同学asy668(http://hi.baidu.com/myasy)完善这个算法中createPoints,帮助我测试这个算法,并为这个算法写了一个用户交互界面。

 

  1. #-*-coding:utf-8-*-
  2. """连连看连接算法
  3. 为连连看游戏提供连接算法
  4. 模块中包含一个Point类,该类是游戏的基本单元“点”,该类包含属性:x,y,value。
  5. 其中x,y代表了该点的坐标,value代表该点的特征:0代表没有被填充,1-8代表被填充为游戏图案,9代表被填充为墙壁
  6. 模块中还包含一个名为points的Point列表,其中保存着整个游戏界面中的每个点
  7. 使用模块的时候应首先调用createPoints方法,初始化游戏界面中每个点,然后可通过points访问到每个点,继而初始化界面
  8. 模块中核心的方法是link,通过提供源点和终点,可尝试连接两点,如果可以连接则返回保存路径的path列表,否则返回False
  9. """
  10. import random
  11. import time
  12. __author__  ="http://blog.csdn.net/anhulife"
  13. __license__ ="python"
  14. class Point:
  15.     """Point类
  16.     
  17.     Point类是游戏中基本单元:“点”
  18.     """
  19.     def __init__(self,x,y,value):
  20.         self.x = x
  21.         self.y = y
  22.         self.value = value
  23.         self.directs = None
  24.         self.changed = 0
  25.         
  26.         
  27.     def __createDirect(self,pre,target):
  28.         """构造点的方向集
  29.         
  30.         每个点在连接的过程中都持有一个方向集,这个方向集中保
  31.         存着该点的前进方向选择的优先级优先级:指向目标点的方向级别最
  32.         高,在同等级别并且遵循x方向优先于y方向
  33.         """
  34.         self.directs = list()
  35.         stx = target.x - self.x
  36.         sty = target.y - self.y
  37.         if stx >= 0 :
  38.             self.directs.append("right")
  39.             self.directs.append("left")
  40.         else:
  41.             self.directs.append("left")
  42.             self.directs.append("right")
  43.         if sty >= 0 :
  44.             self.directs.insert(1,"up")
  45.             self.directs.append("down")
  46.         else:
  47.             self.directs.insert(1,"down")
  48.             self.directs.append("up")
  49.         if pre == None :
  50.             return
  51.         spx = pre.x - self.x
  52.         spy = pre.y - self.y
  53.         if spx == 0 :
  54.             if spy == 1:
  55.                 self.directs.remove("up")
  56.             else:
  57.                 self.directs.remove("down")
  58.         else :
  59.             if spx == 1:
  60.                 self.directs.remove("right")
  61.             else:
  62.                 self.directs.remove("left")
  63.                 
  64.                 
  65.     def forward(self,pre,target):
  66.         """点的前进动作
  67.         
  68.         点的前进即是依次从方向集中取出优先级高的方向,并判
  69.         断该方向上的下一个点是否被填充如果没有被填充则说明该方
  70.         向可通,并返回该方向。否则试探下一个方向,如果方向集中没
  71.         有方向可用了,则返回None
  72.         """
  73.         if self.directs == None :
  74.             self.__createDirect(pre,target)
  75.         if len(self.directs) == 0 :
  76.             return None
  77.         direct = None
  78.         while(True):
  79.             if len(self.directs) == 0 :
  80.                 break
  81.             tmpDirect = self.directs.pop(0)
  82.             if tmpDirect == "up" :
  83.                 x = self.x
  84.                 y = self.y + 1
  85.             elif tmpDirect == "down":
  86.                 x = self.x
  87.                 y = self.y - 1
  88.             elif tmpDirect == "left":
  89.                 x = self.x - 1
  90.                 y = self.y
  91.             elif tmpDirect == "right":
  92.                 x = self.x + 1
  93.                 y = self.y
  94.             p = points[x][y]
  95.             if p.value > 0 and p != target:
  96.                 continue
  97.             else :
  98.                 direct = tmpDirect
  99.                 if pre == None:
  100.                     self.changed = 1
  101.                 else:
  102.                     if (pre.x - self.x) == 0 and (p.x - self.x) == 0:
  103.                         self.changed = 0
  104.                     else:
  105.                         if (pre.y - self.y) == 0 and (p.y - self.y) == 0:
  106.                             self.changed = 0
  107.                         else :
  108.                             self.changed = 1
  109.                 break
  110.         return direct
  111.         
  112.     def __eq__(self,p):
  113.         if p == None :
  114.             return False
  115.         if self.x == p.x and self.y == p.y :
  116.             return True
  117.         else:
  118.             return False
  119.             
  120. points = list()
  121. valuestack=list()
  122.         
  123. def createPoints(w,h):
  124.     """构造游戏界面的点
  125.     
  126.     初始化界面中的所有的点,并且规则如下:
  127.     最外一层是“墙壁”点,接下来的一层是没有被填充的点,被包裹的是填充的点
  128.     """
  129.     r = random.randint
  130.     random.seed(time.time())
  131.     Pointstack(w,h)
  132.     for x in range(w):
  133.         temp = list()
  134.         for y in range(h):
  135.             if x == 0 or x == (w-1or y == 0 or y == (h-1):
  136.                 temp.append(Point(x,y,9))
  137.             else:
  138.                 if x == 1 or x == (w-2or y == 1 or y == (h-2):
  139.                     temp.append(Point(x,y,0))
  140.                 else:
  141.                     temp.append(Point(x,y,valuestack.pop()))
  142.         points.append(temp)
  143.         
  144. def Pointstack(w,h):
  145.     size=w*h-(w*4+h*4-16)
  146.     size=size/2
  147.     random.seed(time.time())
  148.     for i in range(size):
  149.         value=random.randint(1,8)
  150.         if len(valuestack)==0:
  151.             valuestack.append(value)
  152.             valuestack.append(value)
  153.         else:
  154.             valuestack.insert(random.randint(1,len(valuestack)),value)
  155.             valuestack.insert(random.randint(1,len(valuestack)),value)  
  156.             
  157. def link(source,target):
  158.     """点的连接
  159.     
  160.     连接方法的思想:针对源点的每个方向尝试前进,如果可以前进,
  161.     则将针对该方向上的下个点的每个方向尝试前进,
  162.     当一个点的可选方向都不能前进的时候,则使用规定的信息标记该点,
  163.     并返回到已有前进路径中的前一个点,尝试该点其他可选方向。当回源点
  164.     的每个方向都走不通,连接失败返回False。否则当路径连接到目标点而且
  165.     路径的方向变化小于4的时候,连接成功返回路径
  166.     """
  167.     if source == target:
  168.         return False
  169.     if source.value==9 or source.value==0:
  170.         return False
  171.     path = list()
  172.     fail = dict()
  173.     change = 0
  174.     current = source
  175.     tempPoint = None
  176.     while True:
  177.         if current==target and change < 4:
  178.             for p in path:
  179.                 p.directs = None
  180.             return path
  181.         if change == 4:
  182.                 current.directs = None
  183.                 fail[str(current.x)+"_"+str(current.y)] = change
  184.                 current = path.pop()
  185.                 change = change - current.changed
  186.                 continue
  187.         if current == source:
  188.             direct = current.forward(None,target)
  189.         else:
  190.             direct = current.forward(path[len(path)-1],target)
  191.         if direct != None:
  192.             if direct == "up" :
  193.                 x = current.x
  194.                 y = current.y + 1
  195.             elif direct == "down":
  196.                 x = current.x
  197.                 y = current.y - 1
  198.             elif direct == "left":
  199.                 x = current.x - 1
  200.                 y = current.y
  201.             elif direct == "right":
  202.                 x = current.x + 1
  203.                 y = current.y
  204.             if fail.has_key(str(x)+"_"+str(y)):
  205.                 if change >= fail.get(str(x)+"_"+str(y)):
  206.                     continue
  207.                 else:
  208.                     fail.pop(str(x)+"_"+str(y))
  209.             change = change + current.changed
  210.             path.append(current)
  211.             current = points[x][y]
  212.         else:
  213.             if current == source:
  214.                 source.directs = None
  215.                 return False
  216.             else:
  217.                 current.directs = None
  218.                 fail[str(current.x)+"_"+str(current.y)] = change
  219.                 current = path.pop()
  220.                 change = change - current.changed
  221. #createPoints(8,8)
  222. #p = link(points[2][2],points[5][2])
  223. #print p
原创粉丝点击