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

这段时间老是“不务正业”的搞一些东西玩。之前的贪吃蛇,俄罗斯方块激发了我研究游戏算法的兴趣。经过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. importrandom
  11. importtime
  12. __author__="http://blog.csdn.net/anhulife"
  13. __license__="python"
  14. classPoint:
  15. """Point类
  16. Point类是游戏中基本单元:“点”
  17. """
  18. def__init__(self,x,y,value):
  19. self.x=x
  20. self.y=y
  21. self.value=value
  22. self.directs=None
  23. self.changed=0
  24. def__createDirect(self,pre,target):
  25. """构造点的方向集
  26. 每个点在连接的过程中都持有一个方向集,这个方向集中保
  27. 存着该点的前进方向选择的优先级优先级:指向目标点的方向级别最
  28. 高,在同等级别并且遵循x方向优先于y方向
  29. """
  30. self.directs=list()
  31. stx=target.x-self.x
  32. sty=target.y-self.y
  33. ifstx>=0:
  34. self.directs.append("right")
  35. self.directs.append("left")
  36. else:
  37. self.directs.append("left")
  38. self.directs.append("right")
  39. ifsty>=0:
  40. self.directs.insert(1,"up")
  41. self.directs.append("down")
  42. else:
  43. self.directs.insert(1,"down")
  44. self.directs.append("up")
  45. ifpre==None:
  46. return
  47. spx=pre.x-self.x
  48. spy=pre.y-self.y
  49. ifspx==0:
  50. ifspy==1:
  51. self.directs.remove("up")
  52. else:
  53. self.directs.remove("down")
  54. else:
  55. ifspx==1:
  56. self.directs.remove("right")
  57. else:
  58. self.directs.remove("left")
  59. defforward(self,pre,target):
  60. """点的前进动作
  61. 点的前进即是依次从方向集中取出优先级高的方向,并判
  62. 断该方向上的下一个点是否被填充如果没有被填充则说明该方
  63. 向可通,并返回该方向。否则试探下一个方向,如果方向集中没
  64. 有方向可用了,则返回None
  65. """
  66. ifself.directs==None:
  67. self.__createDirect(pre,target)
  68. iflen(self.directs)==0:
  69. returnNone
  70. direct=None
  71. while(True):
  72. iflen(self.directs)==0:
  73. break
  74. tmpDirect=self.directs.pop(0)
  75. iftmpDirect=="up":
  76. x=self.x
  77. y=self.y+1
  78. eliftmpDirect=="down":
  79. x=self.x
  80. y=self.y-1
  81. eliftmpDirect=="left":
  82. x=self.x-1
  83. y=self.y
  84. eliftmpDirect=="right":
  85. x=self.x+1
  86. y=self.y
  87. p=points[x][y]
  88. ifp.value>0andp!=target:
  89. continue
  90. else:
  91. direct=tmpDirect
  92. ifpre==None:
  93. self.changed=1
  94. else:
  95. if(pre.x-self.x)==0and(p.x-self.x)==0:
  96. self.changed=0
  97. else:
  98. if(pre.y-self.y)==0and(p.y-self.y)==0:
  99. self.changed=0
  100. else:
  101. self.changed=1
  102. break
  103. returndirect
  104. def__eq__(self,p):
  105. ifp==None:
  106. returnFalse
  107. ifself.x==p.xandself.y==p.y:
  108. returnTrue
  109. else:
  110. returnFalse
  111. points=list()
  112. valuestack=list()
  113. defcreatePoints(w,h):
  114. """构造游戏界面的点
  115. 初始化界面中的所有的点,并且规则如下:
  116. 最外一层是“墙壁”点,接下来的一层是没有被填充的点,被包裹的是填充的点
  117. """
  118. r=random.randint
  119. random.seed(time.time())
  120. Pointstack(w,h)
  121. forxinrange(w):
  122. temp=list()
  123. foryinrange(h):
  124. ifx==0orx==(w-1)ory==0ory==(h-1):
  125. temp.append(Point(x,y,9))
  126. else:
  127. ifx==1orx==(w-2)ory==1ory==(h-2):
  128. temp.append(Point(x,y,0))
  129. else:
  130. temp.append(Point(x,y,valuestack.pop()))
  131. points.append(temp)
  132. defPointstack(w,h):
  133. size=w*h-(w*4+h*4-16)
  134. size=size/2
  135. random.seed(time.time())
  136. foriinrange(size):
  137. value=random.randint(1,8)
  138. iflen(valuestack)==0:
  139. valuestack.append(value)
  140. valuestack.append(value)
  141. else:
  142. valuestack.insert(random.randint(1,len(valuestack)),value)
  143. valuestack.insert(random.randint(1,len(valuestack)),value)
  144. deflink(source,target):
  145. """点的连接
  146. 连接方法的思想:针对源点的每个方向尝试前进,如果可以前进,
  147. 则将针对该方向上的下个点的每个方向尝试前进,
  148. 当一个点的可选方向都不能前进的时候,则使用规定的信息标记该点,
  149. 并返回到已有前进路径中的前一个点,尝试该点其他可选方向。当回源点
  150. 的每个方向都走不通,连接失败返回False。否则当路径连接到目标点而且
  151. 路径的方向变化小于4的时候,连接成功返回路径
  152. """
  153. ifsource==target:
  154. returnFalse
  155. ifsource.value==9orsource.value==0:
  156. returnFalse
  157. path=list()
  158. fail=dict()
  159. change=0
  160. current=source
  161. tempPoint=None
  162. whileTrue:
  163. ifcurrent==targetandchange<4:
  164. forpinpath:
  165. p.directs=None
  166. returnpath
  167. ifchange==4:
  168. current.directs=None
  169. fail[str(current.x)+"_"+str(current.y)]=change
  170. current=path.pop()
  171. change=change-current.changed
  172. continue
  173. ifcurrent==source:
  174. direct=current.forward(None,target)
  175. else:
  176. direct=current.forward(path[len(path)-1],target)
  177. ifdirect!=None:
  178. ifdirect=="up":
  179. x=current.x
  180. y=current.y+1
  181. elifdirect=="down":
  182. x=current.x
  183. y=current.y-1
  184. elifdirect=="left":
  185. x=current.x-1
  186. y=current.y
  187. elifdirect=="right":
  188. x=current.x+1
  189. y=current.y
  190. iffail.has_key(str(x)+"_"+str(y)):
  191. ifchange>=fail.get(str(x)+"_"+str(y)):
  192. continue
  193. else:
  194. fail.pop(str(x)+"_"+str(y))
  195. change=change+current.changed
  196. path.append(current)
  197. current=points[x][y]
  198. else:
  199. ifcurrent==source:
  200. source.directs=None
  201. returnFalse
  202. else:
  203. current.directs=None
  204. fail[str(current.x)+"_"+str(current.y)]=change
  205. current=path.pop()
  206. change=change-current.changed
  207. #createPoints(8,8)
  208. #p=link(points[2][2],points[5][2])
  209. #printp

你可能感兴趣的:(python)