Gioca una partita perfetta del 2048


18

Il tuo compito è quello di simulare un gioco matematicamente perfetto del 2048. L'idea è quella di trovare il limite superiore teorico di quanto può andare lontano un gioco del 2048 e trovare come arrivarci.

Per avere un'idea di come appare, gioca con questo clone 2x2 e prova a segnare 68 punti. Se lo fai, finirai con una tessera 2, 4, 8 e 16. È impossibile avanzare oltre quel punto.

Il tuo compito è reso più semplice perché puoi scegliere dove vengono generate le tessere e quali sono i loro valori, proprio come questo clone .

È necessario scrivere un programma o una funzione che accetti una scheda 2048 come input e emetta la scheda con la tessera generata e la scheda dopo il crollo delle tessere. Per esempio:

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

Il tuo programma riceverà ripetutamente il proprio output per simulare un intero gioco del 2048. Il primo input del programma sarà una scheda vuota. Devi generare una tessera su di essa, a differenza delle due tessere del gioco originale. Nell'ultima fase del gioco, non sarai in grado di muoverti, quindi le tue due schede di output possono essere identiche.

Ovviamente devi solo produrre mosse legali. Possono essere generati solo 2 o 4, devi muovere o comprimere almeno una tessera su una mossa, ecc.

Ho volutamente reso vaghi i requisiti di input e output. Sei libero di scegliere il formato dell'input e dell'output. Puoi usare matrici, matrici, stringhe o qualsiasi cosa tu voglia. Finché puoi simulare un gioco 2048 con loro, i tuoi input e output vanno bene.

Il vincitore sarà colui che termina il gioco con la somma più alta di tessere sul tabellone, quindi con il minor numero di byte nel codice sorgente. Il punteggio del gioco originale non verrà preso in considerazione. (Suggerimento: usa i 4)


@undergroundmonorail Questo è diverso da questa domanda. Questa domanda consente di spawnare le proprie tessere e riguarda il punto matematicamente possibile, non solo fino al 2048.
Kendall Frey,

1
@TheDoctor 68 è una somma di potenze di 2 ed è il tuo punteggio se ottenessi 2, 4, 8, 16.
user12205

2
È davvero un duplicato? Cosa ci vorrebbe di più per renderlo diverso?
Kendall Frey,

1
@Quincunx Sarebbe davvero generare un gioco non ottimale però.
Kendall Frey,

4
Ho trovato il cuore di questa sfida, "Trova una soluzione ottimale", unico, ma è stato una scelta sbagliata racchiuderlo in una "shell" duplicata. Questo urla: "Oh guarda, un'altra sfida del Code Golf del 2048". Dato che i voti stretti sono così soggettivi, devi davvero vendere la tua sfida alla folla. A volte questo significa generare il tuo terribile ripoff del 2048.
Rainbolt

Risposte:


4

Ruby, Into the Corner, Punteggio: 3340

Ecco una strategia molto semplice per dare il via a questo. Ho un'idea per un punteggio (quasi) perfetto, ma ho problemi a formalizzarlo, quindi ecco qualcosa di semplice per far andare le cose.

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

La advancefunzione è quella che stai chiedendo. Prende una tavola come 1d array e restituisce la tavola dopo che la tessera è stata generata e dopo che la mossa è stata effettuata.

Puoi provarlo con questo frammento

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

La strategia è molto semplice, ed è quella che in realtà ho usato per saltare ai 128 quando giocavo al 2048 da solo: basta alternare tra alto e sinistro . Per far funzionare il più a lungo possibile, 4vengono generate nuove s nell'angolo in basso a destra.

EDIT: ho aggiunto un interruttore hard coded per andare a destra alcune volte in passaggi specifici appena prima della fine, che in realtà mi consente di raggiungere il 1024. Tuttavia, mi sto sfuggendo un po 'di mano, quindi per ora smetterò con questo e pensa a un approccio generalmente migliore domani. (Onestamente, il fatto che posso aumentare il mio punteggio di un fattore 4 aggiungendo hack modificati a mano mi dice solo che la mia strategia è una schifezza.)

Questa è la tavola con cui finisci

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

Solo per nitpick, la generazione di 4 non ti dà un punteggio ottimale perché non stai guadagnando i 4 punti ogni volta che ne viene creato uno invece di essere generato da 2 2.
BrunoJ,

@BrunoJ Il punteggio per questa sfida viene semplicemente calcolato come il totale di tutte le tessere alla fine, non il punteggio che avresti ottenuto nel gioco reale. Ma se così fosse, hai ragione ovviamente. ;) ... Anche se penso che con la mia strategia non farebbe differenza, perché arriverei a 128 invece di 256.
Martin Ender,

Oh, non ho capito che il punteggio non è lo stesso, le mie scuse
BrunoJ,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.