Juega un juego perfecto de 2048

18

Su trabajo es simular un juego matemáticamente perfecto de 2048. La idea es encontrar el límite superior teórico de cuán lejos puede llegar un juego de 2048 y cómo llegar allí.

Para tener una idea de cómo se ve, juega con este clon de 2x2 e intenta obtener 68 puntos. Si lo haces, terminarás con un mosaico de 2, 4, 8 y 16. Es imposible avanzar más allá de ese punto.

Su tarea se hace más fácil porque puede elegir dónde aparecen los mosaicos y cuáles son sus valores, al igual que este clon .

Debe escribir un programa o función que acepte una placa 2048 como entrada, y que emita la placa con el mosaico generado y la placa después de colapsar los mosaicos. Por ejemplo:

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

Su programa se alimentará repetidamente con su propia salida para simular un juego completo de 2048. La primera entrada del programa será un tablero vacío. Debes generar una ficha en ella, a diferencia de las dos fichas del juego original. En el último paso del juego, no podrás moverte, por lo que tus dos tableros de salida pueden ser idénticos.

Por supuesto, solo debe generar movimientos legales. Solo se pueden generar 2 o 4, debes mover o colapsar al menos una ficha en un movimiento, etc.

He hecho vagamente los requisitos de entrada y salida. Usted es libre de elegir el formato de entrada y salida. Puedes usar matrices, matrices, cadenas o lo que quieras. Mientras puedas simular un juego 2048 con ellos, tus entradas y salidas estarán bien.

El ganador será el que termine el juego con la mayor suma de fichas en el tablero, luego por el menor número de bytes en el código fuente. La puntuación del juego original no se tendrá en cuenta. (Sugerencia: use 4)

Kendall Frey
fuente
@undergroundmonorail Esto es diferente de esa pregunta. Esta pregunta permite generar sus propios mosaicos, y se trata de ir tan lejos como sea matemáticamente posible, no solo hasta 2048.
Kendall Frey
1
@TheDoctor 68 es una suma de poderes de 2, y es su puntaje si obtiene 2, 4, 8, 16.
user12205
2
¿Es esto realmente un duplicado? ¿Qué más se necesitaría para hacerlo diferente?
Kendall Frey
1
@Quincunx Sin embargo, eso realmente generaría un juego subóptimo.
Kendall Frey
44
Encontré que el corazón de este desafío, "Encontrar una solución óptima", es único, pero es cierto que fue una mala elección encerrarlo en un "caparazón" duplicado. Éste grita: "Oh, mira, otro desafío del Código Golf 2048". Con los votos cerrados siendo tan subjetivos, realmente tienes que vender tu desafío a la multitud. A veces eso significa generar tu propia estafa terrible de 2048.
Rainbolt

Respuestas:

4

Ruby, Into the Corner, Puntuación: 3340

Aquí hay una estrategia muy simple para comenzar esto. Tengo una idea para un puntaje (casi) perfecto, pero tengo problemas para formalizarlo, así que aquí hay algo simple para que las cosas funcionen.

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 advancefunción es la que está solicitando. Toma un tablero como matriz 1d y devuelve el tablero después de que se haya generado la ficha y después de que se haya realizado el movimiento.

Puedes probarlo con este fragmento

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 estrategia es muy simple, y es la que realmente solía saltar al 128 cuando jugaba 2048 yo mismo: solo alternar entre arriba y izquierda . Para que esto funcione el mayor tiempo posible, 4se generan nuevos correos electrónicos en la esquina inferior derecha.

EDITAR: He agregado un interruptor codificado para ir a la derecha varias veces en pasos específicos justo antes del final, lo que en realidad me permite llegar a 1024. Sin embargo, esto se está yendo un poco fuera de control, así que me detendré con esto por ahora y piense en un enfoque generalmente mejor mañana. (Honestamente, el hecho de que pueda aumentar mi puntaje en un factor de 4 agregando hacks modificados a mano solo me dice que mi estrategia es una mierda).

Este es el tablero con el que terminas

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4
Martin Ender
fuente
Solo para señalar, generar 4's no te da una puntuación óptima porque no estás ganando los 4 puntos cada vez que se crea uno en lugar de ser generado por 2 2's.
BrunoJ
@BrunoJ El puntaje para este desafío se calcula simplemente como el total de todas las fichas al final, no el puntaje que tendría en el juego real. Pero si ese fuera el caso, tienes razón, por supuesto. ;) ... Aunque creo que con mi estrategia no haría la diferencia, porque solo llegaría a 128 en lugar de 256 entonces.
Martin Ender
Oh, no entendí que la puntuación no es la misma, mis disculpas
BrunoJ