Spielen Sie ein perfektes Spiel von 2048

17

Ihre Aufgabe ist es, ein mathematisch perfektes Spiel von 2048 zu simulieren. Die Idee ist, die theoretische Obergrenze dafür zu finden, wie weit ein Spiel von 2048 gehen kann und wie Sie dorthin gelangen.

Um eine Vorstellung davon zu bekommen, wie dies aussieht, spielen Sie mit diesem 2x2-Klon und versuchen Sie, 68 Punkte zu erzielen. Wenn Sie dies tun, erhalten Sie eine 2, 4, 8 und 16 Kachel. Es ist unmöglich, diesen Punkt zu überschreiten.

Ihre Aufgabe wird erleichtert, da Sie genau wie bei diesem Klon auswählen können, wo Kacheln entstehen und welche Werte sie haben .

Sie müssen ein Programm oder eine Funktion schreiben, die eine 2048-Karte als Eingabe akzeptiert und die Karte mit der hervorgebrachten Kachel und der Karte nach dem Zusammenlegen der Kacheln ausgibt. Beispielsweise:

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

Ihr Programm wird wiederholt mit seiner eigenen Ausgabe gespeist, um ein ganzes Spiel von 2048 zu simulieren. Die erste Eingabe des Programms ist eine leere Tafel. Sie müssen ein Plättchen darauf erzeugen, anders als bei den beiden Plättchen des Originalspiels. Im letzten Schritt des Spiels können Sie sich nicht mehr bewegen, sodass Ihre beiden Ausgangskarten identisch sein können.

Sie müssen natürlich nur legale Züge ausgeben. Es können nur 2 oder 4 erzeugt werden. Sie müssen mindestens ein Plättchen bewegen oder reduzieren.

Ich habe die Eingabe- und Ausgabeanforderungen absichtlich vage gestellt. Sie können das Format der Ein- und Ausgabe frei wählen. Sie können Matrizen, Arrays, Strings oder was immer Sie wollen verwenden. Solange Sie mit ihnen ein 2048-Spiel simulieren können, sind Ihre Ein- und Ausgänge in Ordnung.

Der Gewinner ist derjenige, der das Spiel mit der höchsten Anzahl von Kacheln auf dem Brett und dann mit der niedrigsten Anzahl von Bytes im Quellcode beendet. Die Wertung aus dem ursprünglichen Spiel wird nicht berücksichtigt. (Hinweis: benutze 4er)

Kendall Frey
quelle
@undergroundmonorail Dies unterscheidet sich von dieser Frage. Diese Frage erlaubt das Laichen eigener Kacheln und geht so weit wie mathematisch möglich, nicht nur bis 2048.
Kendall Frey,
1
@TheDoctor 68 ist eine Summe von Potenzen von 2 und entspricht Ihrer Punktzahl, wenn Sie 2, 4, 8, 16 erhalten.
user12205
2
Ist das wirklich ein Duplikat? Was würde es noch brauchen, um es anders zu machen?
Kendall Frey
1
@Quincunx Das würde allerdings wirklich ein suboptimales Spiel erzeugen.
Kendall Frey
4
Ich fand das Herzstück dieser Herausforderung, "Eine optimale Lösung finden", einzigartig, aber es war zugegebenermaßen eine schlechte Wahl, sie in eine doppelte "Hülle" einzuschließen. Dieser schreit: "Oh schau, noch eine 2048 Code Golf Herausforderung." Da enge Abstimmungen so subjektiv sind, muss man seine Herausforderung wirklich an die Menge verkaufen . Manchmal bedeutet das, dass Sie Ihre eigene schreckliche Abzocke von 2048 machen.
Rainbolt

Antworten:

3

Ruby, In die Ecke, Score: 3340

Hier ist eine sehr einfache Strategie, um dies zu starten. Ich habe eine Idee für eine (fast) perfekte Partitur, aber ich habe Probleme, sie zu formalisieren. Hier ist also etwas Einfaches, um die Dinge zum Laufen zu bringen.

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

Die advanceFunktion ist die, nach der Sie fragen. Es nimmt ein Brett als 1d-Array und gibt das Brett zurück, nachdem das Plättchen erzeugt und der Zug ausgeführt wurde.

Sie können es mit diesem Snippet testen

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

Die Strategie ist sehr einfach und ist die, die ich tatsächlich verwendet habe, um zu den 128 zu springen, als ich 2048 selbst gespielt habe: einfach abwechselnd nach oben und links . Damit dies so lange wie möglich funktioniert, 4werden in der rechten unteren Ecke neue s erzeugt.

BEARBEITEN: Ich habe einen hartcodierten Schalter hinzugefügt, der einige Male in bestimmten Schritten kurz vor dem Ende nach rechts geht, wodurch ich tatsächlich 1024 erreiche. Dies gerät jedoch etwas außer Kontrolle Überlegen Sie sich morgen einen allgemein besseren Ansatz. (Ehrlich gesagt, die Tatsache, dass ich meine Punktzahl um den Faktor 4 steigern kann, indem ich von Hand optimierte Hacks hinzufüge, zeigt mir nur, dass meine Strategie Mist ist.)

Dies ist das Board, mit dem Sie enden

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4
Martin Ender
quelle
Nur zu kurz gesagt, das Erzeugen von 4 gibt Ihnen keine optimale Punktzahl, da Sie nicht jedes Mal die 4 Punkte erhalten, wenn eine erstellt wird, anstatt von 2 2 generiert zu werden.
BrunoJ
@BrunoJ Die Punktzahl für diese Herausforderung wird einfach als die Summe aller Kacheln am Ende berechnet und nicht als die Punktzahl, die Sie im tatsächlichen Spiel erzielt hätten. Aber wenn das der Fall war, haben Sie natürlich Recht. ;) ... Obwohl ich denke, dass es mit meiner Strategie keinen Unterschied machen würde, weil ich dann nur 128 statt 256 bekommen würde.
Martin Ender
Oh, habe nicht
mitbekommen,