玩一个完美的2048游戏


18

您的工作是模拟一个数学上完美的2048游戏。其想法是找到2048游戏可以进行的理论上限,并找到达到该水平的方法。

要了解其外观,请尝试使用此2x2克隆并尝试获得68分。如果这样做,最终将得到2、4、8和16磁贴。超越这一点是不可能的。

就像此clone一样,您可以轻松选择任务,因为它们可以选择生成瓦片的位置及其值。

您必须编写一个程序或函数,接受2048板作为输入,并输出带有生成的图块的图板和折叠图块后的图板。例如:

Input:
-------
0 0 0 0
0 0 0 0
0 0 0 0
0 0 8 8

Output:
-------
0 0 0 0
0 0 0 0
0 0 0 0
0 4 8 8

0 0 0 0
0 0 0 0
0 0 0 0
0 0 4 16

您的程序将反复获得其自己的输出,以模拟整个2048的游戏。该程序的第一个输入将是一个空局。您必须在上面生成一个图块,这与原始游戏的两个图块不同。在游戏的最后一步,您将无法移动,因此两个输出板可以相同。

当然,您必须仅输出合法动作。只能生成2或4,必须在移动中移动或折叠至少一个图块,依此类推。

我故意使输入和输出要求含糊不清。您可以自由选择输入和输出的格式。您可以使用矩阵,数组,字符串或任何您想要的东西。只要您可以使用它们模拟2048游戏,您的输入和输出就可以了。

获胜者将是在棋盘上以最高的总和,然后以源代码中的最低字节数结束游戏的人。原始游戏的得分将不予考虑。(提示:使用4's)


@undergroundmonorail与这个问题不同。这个问题允许产生自己的瓷砖,并且在数学上要尽可能地发展,而不仅仅是达到2048。–
Kendall Frey

1
@TheDoctor 68是2的幂的总和,并且如果你得到你的分数会是什么2,4,8,16
user12205

2
这真的是重复的吗?要使它与众不同还需要什么?
肯德尔·弗雷

1
@Quincunx这确实会产生次优游戏。
肯德尔·弗雷

4
我发现这个挑战的核心是“寻找最佳解决方案”,它是独一无二的,但是诚然,将其包含在重复的“外壳”中是一个糟糕的选择。这个人尖叫着,“哦,另一个2048码高尔夫挑战赛。” 鉴于票数如此主观,您确实必须挑战卖给人群。有时这意味着产生的2048自己可怕的骗人货
Rainbolt

Answers:


4

Ruby,进入角落,得分:3340

这是一个非常简单的策略来开始这一工作。我确实有一个(接近)完美分数的想法,但是我很难将其形式化,所以这是使事情顺利进行的简单方法。

def slide board, dir
    case dir
    when 'U'
        i0 = 0
        i_stride = 1
        i_dist = 4
    when 'D'
        i0 = 15
        i_stride = -1
        i_dist = -4
    when 'L'
        i0 = 0
        i_stride = 4
        i_dist = 1
    when 'R'
        i0 = 15
        i_stride = -4
        i_dist = -1
    end

    4.times do |x|
        column = []
        top_merged = false
        4.times do |y|
            tile = board[i0 + x*i_stride + y*i_dist]
            next if tile == 0
            if top_merged || tile != column.last
                column.push tile
                top_merged = false
            else
                column[-1] *= 2
                top_merged = true
            end
        end

        4.times do |y|
            board[i0 + x*i_stride + y*i_dist] = column[y] || 0
        end
    end

    board
end

def advance board
    if board.reduce(:*) > 0
        return board, board
    end

    16.times do |i|
        if board[15-i] == 0
            board[15-i] = 4
            break
        end
    end

    spawned = board.clone

    # Attention, dirty dirty hand-tweaked edge cases to avoid
    # the inevitable for a bit longer. NSFS!
    if board[11] == 8 && (board[12..15] == [32, 16, 4, 4] ||
                          board[12..15] == [16, 16, 4, 4] && board[8..10] == [256,64,32]) || 
       board[11] == 16 && (board[12..15] == [32, 8, 4, 4] || 
                           board[12..15] == [4, 32, 8, 8] || 
                           board[12..15] == [4, 32, 0, 4])

        dir = 'R'
    elsif board[11] == 16 && board[12..15] == [4, 4, 32, 4] ||
          board[11] == 8 && board[12..15] == [0, 4, 32, 8]
        dir = 'U'
    else
        dir = (board.reduce(:+)/4).even? ? 'U' : 'L'
    end

    board = slide(board, dir)

    if board == spawned
        dir = dir == 'U' ? 'L' : 'U'
        board = slide(board, dir)
    end
    return spawned, board
end

advance功能是您所要求的。它以棋盘为一维数组,并在生成瓦片并进行移动后返回棋盘。

您可以使用此代码段对其进行测试

board = [0]*16
loop do
    spawned, board = advance(board)
    board.each_slice(4) {|row| puts row*' '}
    puts
    break if board[15] > 0
end

puts "Score: #{board.reduce :+}"

该策略非常简单,这是我自己在玩2048时实际跳到128的策略:只是在之间交替。为了使这项工作尽可能长的时间,4在右下角会产生new 。

编辑:我已经添加了一个硬编码的开关,可以在结束之前的特定步骤执行几次,这实际上使我达到了1024。不过这有些失控了,所以我现在就停下来想一想明天总体上更好的方法。(老实说,我可以通过添加一些手动调整的技巧将得分提高4倍,这只能告诉我我的策略很糟糕。)

这是您最终获得的董事会

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4

仅仅对nitpick来说,生成4不会给您最佳的分数,因为您每次创建1而不是2 2都会得到4点。
BrunoJ 2014年

@BrunoJ此挑战的分数只是作为末尾所有图块的总和来计算,而不是您在实际游戏中得到的分数。但是,如果是这样,您当然是对的。;)...尽管我认为我的策略不会有什么不同,因为我只会得到128而不是256。
Martin Ender 2014年

抱歉,我没有道歉得分不一样
BrunoJ 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.