我试图找出在一个带有8块的滑动拼图中,用Python 3编写洗牌方法/函数的简单方法。
假设这个数组表示我们的9个正方形,0表示空空间。
puzzle = [[1, 2, 3], [4, 5, 6], [7, 8, 0]]
我知道Python中有一个内置的霉运()函数,但我无法找到信息,说明它是否可以用于在不使3x3难题不可解的情况下对3x3谜题进行洗牌。
发布于 2020-07-06 21:48:14
使用此解决方案:
也是如此。
逻辑很简单。shuffle运行您指定的移动量,在每次迭代时获得围绕空的部分。然后,它从返回的部分中随机选择一段,并将所选的部分与空的部分交换。这是一个程序相当于手动加扰这些谜题之一的手。考虑到它总是有一个有效的移动,最后的拼图应该是可解的。
lastPiece用于确保我们不会撤销先前的操作。它只是存储最后一次移动的索引,然后在下一次迭代中从选择中删除。
撇开:
我相信,从长远来看,您可能会使用一个图形列表。仍然使用数字来获得洗牌。一旦数字列表被洗牌,您就可以迭代它,并根据数字为每个位置分配图形。洗牌图形数据比洗牌数字要密集得多。
编辑:
作为奖励,我添加了解决方案和解决方案解析器(solve)。再给我一个小时,我会让你的整个游戏!:D解决方案被压缩。不像[(2, 1), (1, 4), (4, 5)]那样,每个元组等于(to, from),因为from总是下一个to (因为from是新的空索引),我们用[2, 1, 4, 5]代替[2, 1, 4, 5],并在solve中处理压缩。
import random, math
def surroundingPieces(z, w, h):
x = z%w
y = math.floor(z/h)
left = None if x == 0 else z - 1
up = None if y == 0 else z - w
right = None if x == (w-1) else z + 1
down = None if y == (h-1) else z + w
return list(filter(None, [left, up, right, down]))
def shuffle(puzzle, moves, width, height):
empty = puzzle.index(0) #find initial empty index
lastPiece = empty #init lastPiece
solution = [empty] #init solution
for _ in range(moves):
#get surrounding pieces
pieces = surroundingPieces(empty, width, height)
#remove the last piece we moved
if lastPiece in pieces:
pieces.remove(lastPiece)
#select a piece
pieceIndex = random.choice(pieces)
solution.insert(0, pieceIndex) #insert move in solution
#swap
puzzle[empty] = puzzle[pieceIndex]
lastPiece = empty #store this piece index
puzzle[pieceIndex] = 0
empty = pieceIndex #store new empty index
return puzzle, solution
#this is the program equivalent of manually solving the puzzle
def solve(pzl, sol):
for i in range(len(sol)-1):
pzl[sol[i]] = pzl[sol[i+1]]
pzl[sol[i+1]] = 0
return pzl
puzzle, solution = shuffle([1, 2, 3, 4, 0, 5, 6, 7, 8], 10, 3, 3)
print(puzzle) #[1, 3, 0, 7, 2, 6, 4, 8, 5]
print(solution) #[2, 1, 4, 5, 8, 7, 4, 3, 6, 7, 4]
print(solve(puzzle[:], solution)) #[1, 2, 3, 4, 0, 5, 6, 7, 8]发布于 2020-07-06 21:35:45
慢法:洗牌,直到你得到一个可解的谜题。
如果3X3有奇数倒置,它是不可解的。将此answer用于3X3难题的可解性。
代码
def is_solvable(puzzle):
p = puzzle[puzzle != 0]
inversions = 0
for i, x in enumerate(p):
for y in p[i+1:]:
if x > y:
inversions += 1
return inversions % 2==0
# Now lets generate until we get a solvable puzzle
while True:
puzzle = np.random.choice(np.arange(9), size=9, replace=False)
if is_solvable(puzzle):
break
print (puzzle.reshape(3,3))产出:
[[8 3 4]
[2 1 7]
[5 6 0]]https://stackoverflow.com/questions/62764453
复制相似问题