Zagraj w idealną grę z 2048 roku

18

Twoim zadaniem jest symulacja matematycznie doskonałej gry z 2048 roku. Chodzi o to, aby znaleźć teoretyczną górną granicę zasięgu gry 2048 i znaleźć drogę do niej.

Aby dowiedzieć się, jak to wygląda, graj z tym klonem 2x2 i spróbuj zdobyć 68 punktów. Jeśli to zrobisz, skończysz z kafelkami 2, 4, 8 i 16. Nie można przejść dalej.

Twoje zadanie jest łatwiejsze, ponieważ możesz wybrać miejsce odradzania się płytek i ich wartości, tak jak ten klon .

Musisz napisać program lub funkcję, która akceptuje tablicę 2048 jako dane wejściowe i wyprowadza tablicę z odrodzoną płytką oraz tablicę po złożeniu płytek. Na przykład:

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

Twój program będzie wielokrotnie zasilany własnym wyjściem, aby zasymulować całą grę z 2048 roku. Pierwszym wejściem programu będzie pusta plansza. Musisz odrodzić na nim jeden kafelek, w przeciwieństwie do dwóch kafelków oryginalnej gry. Na ostatnim etapie gry nie będziesz mógł się poruszyć, więc dwie plansze wyjściowe mogą być identyczne.

Musisz oczywiście wysyłać tylko legalne ruchy. Odradzają się tylko 2 lub 4, musisz przenieść lub zwinąć przynajmniej jeden kafelek w ruchu itp.

Celowo sprawiłem, że wymagania dotyczące danych wejściowych i wyjściowych były niejasne. Możesz wybrać format wejścia i wyjścia. Możesz używać macierzy, tablic, ciągów znaków lub cokolwiek chcesz. Tak długo, jak można z nimi symulować grę 2048, twoje dane wejściowe i wyjściowe są w porządku.

Zwycięzcą zostanie ten, który zakończy grę z największą sumą płytek na planszy, a następnie z najmniejszą liczbą bajtów w kodzie źródłowym. Punktacja z oryginalnej gry nie będzie brana pod uwagę. (Wskazówka: użyj 4)

Kendall Frey
źródło
@undergroundmonorail To różni się od tego pytania. To pytanie pozwala na odrodzenie własnych kafelków i dotyczy posunięcia tak daleko, jak to możliwe matematycznie, nie tylko do 2048 r.
Kendall Frey
1
@Doctor 68 to suma potęg 2, i to byłby twój wynik, gdybyś otrzymał 2, 4, 8, 16.
użytkownik12205
2
Czy to naprawdę duplikat? Co jeszcze trzeba zrobić, żeby było inaczej?
Kendall Frey
1
@Quincunx To naprawdę wygenerowałoby jednak nieoptymalną grę.
Kendall Frey
4
Uznałem, że serce tego wyzwania, „znajdowanie optymalnego rozwiązania”, jest wyjątkowe, ale wprawdzie kiepskim wyborem było umieszczenie go w zduplikowanej „powłoce”. Ten krzyczy: „Och, patrz, kolejne wyzwanie Code Golf 2048”. Ponieważ głosy są tak subiektywne, naprawdę musisz sprzedać swoje wyzwanie tłumowi. Czasami oznacza to wygenerowanie własnego okropnego
oszustwa w 2048 r.

Odpowiedzi:

4

Ruby, Into the Corner, wynik: 3340

Oto bardzo prosta strategia rozpoczęcia tego. Mam pomysł na (prawie) idealny wynik, ale mam problem z sformalizowaniem go, więc tutaj jest coś prostego, aby zacząć.

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

Ta advancefunkcja jest tą, o którą prosisz. Pobiera tablicę jako tablicę 1d i zwraca tablicę po odrodzeniu kafelka i po wykonaniu ruchu.

Możesz to przetestować za pomocą tego fragmentu

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

Strategia jest bardzo prosta i właśnie tę przeskoczyłem do 128, kiedy sam grałem w 2048: po prostu na przemian w górę i w lewo . Aby działało to tak długo, jak to możliwe, nowe 4s pojawiają się w prawym dolnym rogu.

EDYCJA: Dodałem przełącznik zakodowany na stałe, aby przejść kilka razy w prawo na określonych etapach tuż przed końcem, co faktycznie pozwala mi osiągnąć 1024. To jednak wymyka się spod kontroli, więc na razie przestanę pomyśl o ogólnie lepszym podejściu jutro. (Szczerze mówiąc, fakt, że mogę zwiększyć swój wynik 4-krotnie poprzez dodanie ręcznie modyfikowanych hacków, mówi mi tylko, że moja strategia to bzdury.)

To jest plansza, na której kończysz

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4
Martin Ender
źródło
Po prostu nitpick, spawnowanie 4 nie daje optymalnego wyniku, ponieważ nie zdobywasz 4 punktów za każdym razem, gdy jeden jest tworzony, a nie generowany przez 2 2.
BrunoJ
@BrunoJ Wynik tego wyzwania jest po prostu obliczany jako suma wszystkich kafelków na końcu, a nie wynik w prawdziwej grze. Ale jeśli tak, to oczywiście masz rację. ;) ... Chociaż myślę, że przy mojej strategii nie zrobiłoby to różnicy, ponieważ wtedy dostałbym tylko 128 zamiast 256.
Martin Ender
Och, nie zrozumiałem, że punktacja nie jest taka sama, przepraszam
BrunoJ