python 实现华容道/拼图游戏(代码还未重构,后期还会修改),采用深度优先遍历

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36528804/article/details/82917686

游戏原理如下(类似拼图游戏):初始状态,移动表中方块的0,每次移动都跟对应数字交换,使其最终能到胜利状态。
初始状态:

1 2 3
4 5 6
0 7 8

向右移动变成:

1 2 3
4 5 6
7 0 8

再向右移动变成如下状态,即胜利状态:

1 2 3
4 5 6
7 8 0

代码如下:

# -*- coding: utf-8 -*-
# !/usr/bin/env python

from enum import Enum

Moving = Enum('Moving', ('LEFT', 'RIGHT', 'UP', 'DOWN'))

# 深度优先搜索
class HuaRongDao(object):
	def __init__(self, numlist):
		self.numlist = numlist
		self.findZero()
		self.movelist = []		# 移动步骤
		self.winState = '[[1, 2, 3], [4, 5, 6], [7, 8, 0]]'		# 正确结果
		self.allState = set()		# 每一步移动后的矩阵的状态

	# 找到0所在行列
	def findZero(self):
		for i in self.numlist:
			if 0 in i:
				self.x = self.numlist.index(i)
				self.y = i.index(0)
			else:
				pass

	# 打印矩阵
	def printNumlist(self):
		for i in self.numlist:
			print(i)
		print("================")

	# 判断是否可以向某个方向移动
	def canMove(self, direction):
		if Moving.LEFT.value == direction:
			return self.y>0
		if Moving.RIGHT.value == direction:
			return self.y<2
		if Moving.UP.value == direction:
			return self.x>0
		if Moving.DOWN.value == direction:
			return self.x<2

	# 向前移动
	def move(self, direction):
		if Moving.LEFT.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x][self.y-1] = self.numlist[self.x][self.y-1], self.numlist[self.x][self.y]
			self.y = self.y - 1
		if Moving.RIGHT.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x][self.y+1] = self.numlist[self.x][self.y+1], self.numlist[self.x][self.y]
			self.y = self.y + 1
		if Moving.UP.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x-1][self.y] = self.numlist[self.x-1][self.y], self.numlist[self.x][self.y]
			self.x = self.x - 1
		if Moving.DOWN.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x+1][self.y] = self.numlist[self.x+1][self.y], self.numlist[self.x][self.y]
			self.x = self.x + 1
		self.movelist.append(direction)

	# 往后回退
	def moveBack(self, direction):
		if Moving.LEFT.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x][self.y+1] = self.numlist[self.x][self.y+1], self.numlist[self.x][self.y]
			self.y = self.y + 1
		if Moving.RIGHT.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x][self.y-1] = self.numlist[self.x][self.y-1], self.numlist[self.x][self.y]
			self.y = self.y - 1
		if Moving.UP.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x+1][self.y] = self.numlist[self.x+1][self.y], self.numlist[self.x][self.y]
			self.x = self.x + 1
		if Moving.DOWN.value == direction:
			self.numlist[self.x][self.y], self.numlist[self.x-1][self.y] = self.numlist[self.x-1][self.y], self.numlist[self.x][self.y]
			self.x = self.x - 1
		self.movelist.pop()

	# 搜索所有可能
	def search(self, direction):
		# 添加len(self.movelist)<100判断,是为了防止多次递归导致的堆栈溢出
		if self.canMove(direction) and len(self.movelist)<100:
			self.move(direction)
			if self.winState == str(self.numlist):
				return True
			if str(self.numlist) in self.allState:
				self.moveBack(direction)
				return False
			self.allState.add(str(self.numlist))

			searchAll = self.search(2) or self.search(4) or self.search(1) or self.search(3)
			if searchAll:
				return True
			else:
				self.moveBack(direction)
				return False
		else:
			return False

	# 寻找移动方式的入口
	def solve(self):
		if self.winState == str(str(self.numlist)):
			return True
		else:
			self.allState.add(str(self.numlist))
			return self.search(2) or self.search(4) or self.search(1) or self.search(3)

	# 打印路径
	def printRoute(self):
		routelist = []
		for direction in self.movelist:
			if Moving.LEFT.value == direction:
				routelist.append("左")
			if Moving.RIGHT.value == direction:
				routelist.append("右")
			if Moving.UP.value == direction:
				routelist.append("上")
			if Moving.DOWN.value == direction:
				routelist.append("下")
		print(routelist)

	# 程序入口
	def testStart(self):
		self.printNumlist()
		if self.solve():
			print("能!移动方式如下:")
			self.printRoute()
		else:
			print("不能!")

# 测试
numlist = [[1,2,3],
		[4,5,6],
		[0,7,8]
		]		# "失败!"
huaRongDao = HuaRongDao(numlist)
huaRongDao.testStart()

代码还有多处缺陷,例如:

  • 使用了大量的if else语句
  • 有部分相似代码可以更精简
  • 结果可能不是最优解,想要最优解可以使用广度优先遍历。

猜你喜欢

转载自blog.csdn.net/qq_36528804/article/details/82917686