首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在不使其不可解的情况下洗刷滑动的瓷砖拼图?(Python 3)

如何在不使其不可解的情况下洗刷滑动的瓷砖拼图?(Python 3)
EN

Stack Overflow用户
提问于 2020-07-06 21:01:12
回答 2查看 1.6K关注 0票数 0

我试图找出在一个带有8块的滑动拼图中,用Python 3编写洗牌方法/函数的简单方法。

假设这个数组表示我们的9个正方形,0表示空空间。

puzzle = [[1, 2, 3], [4, 5, 6], [7, 8, 0]]

我知道Python中有一个内置的霉运()函数,但我无法找到信息,说明它是否可以用于在不使3x3难题不可解的情况下对3x3谜题进行洗牌。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-06 21:48:14

使用此解决方案:

  1. 您不需要篡改多维列表
  2. ,您可以确定要它采取的移动量,它应该处理任何维度的谜题,即使是不平等的维度,

也是如此。

逻辑很简单。shuffle运行您指定的移动量,在每次迭代时获得围绕空的部分。然后,它从返回的部分中随机选择一段,并将所选的部分与空的部分交换。这是一个程序相当于手动加扰这些谜题之一的手。考虑到它总是有一个有效的移动,最后的拼图应该是可解的。

lastPiece用于确保我们不会撤销先前的操作。它只是存储最后一次移动的索引,然后在下一次迭代中从选择中删除。

撇开:

我相信,从长远来看,您可能会使用一个图形列表。仍然使用数字来获得洗牌。一旦数字列表被洗牌,您就可以迭代它,并根据数字为每个位置分配图形。洗牌图形数据比洗牌数字要密集得多。

编辑:

作为奖励,我添加了解决方案和解决方案解析器(solve)。再给我一个小时,我会让你的整个游戏!:D解决方案被压缩。不像[(2, 1), (1, 4), (4, 5)]那样,每个元组等于(to, from),因为from总是下一个to (因为from是新的空索引),我们用[2, 1, 4, 5]代替[2, 1, 4, 5],并在solve中处理压缩。

代码语言:javascript
运行
复制
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]
票数 3
EN

Stack Overflow用户

发布于 2020-07-06 21:35:45

慢法:洗牌,直到你得到一个可解的谜题。

如果3X3有奇数倒置,它是不可解的。将此answer用于3X3难题的可解性。

代码

代码语言:javascript
运行
复制
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))

产出:

代码语言:javascript
运行
复制
[[8 3 4]
 [2 1 7]
 [5 6 0]]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62764453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档