Слушать идеальную игру 2048

18

Ваша задача - симулировать математически совершенную игру 2048 года. Идея состоит в том, чтобы найти теоретический верхний предел того, как далеко может пройти игра 2048 года, и найти способ ее достижения.

Чтобы понять, как это выглядит, поиграйте с этим клоном 2х2 и попытайтесь набрать 68 очков. Если вы это сделаете, вы получите плитки 2, 4, 8 и 16. Невозможно продвинуться дальше этой точки.

Ваша задача стала проще, потому что вы можете выбрать, где появляются плитки и каковы их значения, как этот клон .

Вы должны написать программу или функцию, которая принимает плату 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)

Кендалл Фрей
источник
@undergroundmonorail Это отличается от этого вопроса. Этот вопрос позволяет порождая свои собственные плитки, и о движении, насколько математически возможно, не только 2048.
Kendall Frey
1
@TheDoctor 68 - это сумма степеней 2, и это будет ваш счет, если вы получите 2, 4, 8, 16.
user12205
2
Это действительно дубликат? Что еще нужно, чтобы сделать его другим?
Кендалл Фрей
1
@Quincunx Это действительно создало бы неоптимальную игру все же.
Кендалл Фрей
4
Я нашел суть этой задачи, «Найти оптимальное решение», уникальной, но по общему признанию, это был неудачный выбор заключить ее в дубликат «оболочки». Один из них кричит: «О, смотри, еще один вызов 2048 Code Golf». При близком субъективном голосовании вы действительно должны продать свой вызов толпе. Иногда это означает создание собственного ужасного
грабежа 2048 года.

Ответы:

4

Рубин, в угол, оценка: 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Функция является один ваш просить. Он принимает доску в виде 1d-массива и возвращает доску после появления плитки и после того, как ход был сделан.

Вы можете проверить это с помощью этого фрагмента

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 :+}"

Стратегия очень проста, и я использовал ее для перехода к 128, когда сам играл в 2048: просто чередуйте вверх и влево . Чтобы это работало как можно дольше, 4в правом нижнем углу появляются новые s.

РЕДАКТИРОВАТЬ: Я добавил жестко запрограммированный переключатель, чтобы несколько раз перейти прямо на определенные этапы непосредственно перед концом, что на самом деле позволяет мне достичь 1024. Хотя это немного выходит из-под контроля, поэтому я остановлюсь на этом сейчас и Подумайте о лучшем подходе завтра. (Честно говоря, тот факт, что я могу увеличить свой счет в 4 раза, добавив взломанные вручную хаки, говорит мне лишь о том, что моя стратегия - дерьмо.)

Это доска, на которой вы играете

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4
Мартин Эндер
источник
Просто чтобы придираться, порождение 4-х не дает вам оптимального результата, потому что вы не получаете 4 очка каждый раз, когда создается один, а не 2-х.
BrunoJ
@BrunoJ Счет для этой задачи просто вычисляется как сумма всех фишек в конце, а не счет, который вы получили бы в реальной игре. Но если бы это было так, вы, конечно, правы. ;) ... Хотя я думаю, что с моей стратегией это не будет иметь значения, потому что тогда я получу только 128 вместо 256.
Мартин Эндер
О, не уловил, что выигрыш не тот, мои извинения
BrunoJ