【问题标题】:Generate the initial game board of a Candy-Crush-like game生成类似于 Candy-Crush 的游戏的初始游戏板
【发布时间】:2019-12-05 13:08:02
【问题描述】:

我需要实现一个功能, 它返回一个满足以下要求的 6 x 6 矩阵:

  • 棋盘上的36个数字必须是9个1、9个2、9个3和9个4
  • 任何行或列不得包含 3 个或更多相同数量的直接邻居
  • 函数返回值不能是常量
  • 显然不允许使用预先计算好的答案

正确答案:

    [[3, 2, 4, 1, 3, 2],
    [2, 2, 1, 1, 4, 4],
    [4, 4, 1, 3, 3, 2],
    [4, 1, 3, 2, 2, 4],
    [3, 1, 2, 4, 3, 1],
    [3, 3, 1, 1, 2, 4]]

   [[3, 3, 1, 2, 2, 4],
    [1, 1, 3, 3, 2, 4],
    [4, 4, 2, 1, 1, 3],
    [2, 2, 3, 4, 4, 1],
    [4, 4, 1, 1, 2, 2],
    [3, 1, 2, 3, 3, 4]]

错误答案:

    [[3, 3, 3, 2, 2, 4],
    [1, 1, 1, 3, 2, 4],
    [4, 4, 2, 1, 1, 3],
    [2, 2, 3, 4, 4, 1],
    [4, 4, 1, 1, 2, 2],
    [3, 1, 2, 3, 3, 4]]

   [[3, 3, 1, 2, 2, 4],
    [1, 1, 2, 3, 2, 4],
    [4, 4, 1, 1, 2, 3],
    [2, 2, 3, 4, 4, 1],
    [4, 4, 1, 1, 2, 2],
    [3, 1, 2, 3, 3, 4]]

无需过多担心学术时间/空间的复杂性。更多地关注工程的观点。有什么好主意吗?

【问题讨论】:

  • 回溯显然可以解决问题。另一种是随机生成一个,然后每三排“粉碎”一次,然后重新填充剩余的,直到它停止?
  • 随机生成一个1s、2s、3s、4s分布正确的棋盘,不满足行/列条件则丢弃。只要有效的板相对常见,这应该可以正常工作。这就是所谓的“验收抽样”

标签: python algorithm numpy matrix nested-lists


【解决方案1】:

这应该可行。请注意,此解决方案只是生成一个随机板,检查条件是否成立,如果不成立,则生成另一个,因此不是最优雅的解决方案。

代码:

from random import shuffle

def check_board(board):
    for row in board:
        if check_list(row):
            return False
    for i in range(len(board[0])):
        col = [row[i] for row in board]
        if check_list(col):
            return False
    return True

def check_list(lst):
    return any(lst[i]==lst[i+1] and lst[i]==lst[i+2] for i in range(len(lst)-2))

board = [[]]

while check_board(board):
    board = [1,2,3,4]*9
    shuffle(board)
    board = [board[i:i + 6] for i in range(0, len(board), 6)]

print(board)

生成的示例板:

[[3, 2, 4, 3, 3, 2],
 [1, 1, 2, 3, 1, 3],
 [1, 3, 3, 2, 2, 2],
 [4, 4, 1, 4, 1, 2],
 [1, 1, 4, 4, 2, 4],
 [2, 4, 4, 3, 3, 1]]

[[2, 3, 4, 1, 4, 1],
 [3, 4, 1, 1, 3, 4],
 [3, 1, 4, 1, 3, 4],
 [3, 4, 2, 4, 2, 1],
 [2, 1, 4, 2, 3, 2],
 [2, 2, 1, 3, 3, 2]]

【讨论】:

  • 它应该可以,但是一些快速的餐巾纸数学表明生成没有冲突的板的概率可能小于 1%
  • 同意 - 如果要扩大规模,这可能会成为一个问题,但timeit 给我的每个有效生成板大约为 48.6 µs ± 3.62 µs,因此对于这种情况,它似乎可以接受。
【解决方案2】:
  1. 创建一个大小为 36 的数组并用所需的值填充它 => [1,1,1....4,4,4]

  2. 应用 Fisher-Yates shuffle 在 O(n) 中创建该数组的排列

  3. 检查“连续 3 个”规则并在必要时交换一个随机值,再次检查直到网格没有该规则。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 2013-03-12
    相关资源
    最近更新 更多