เล่นเกมที่สมบูรณ์แบบในปี 2048


18

งานของคุณคือการจำลองเกมที่สมบูรณ์แบบทางคณิตศาสตร์ของ 2048 ความคิดคือการหาขีด จำกัด บนทางทฤษฎีของวิธีการที่เกม 2048 สามารถไปได้ไกลเท่าไหร่และหาวิธีไปที่นั่น

หากต้องการทราบว่าลักษณะนี้เป็นอย่างไรให้เล่นกับโคลน 2x2 นี้แล้วลองทำคะแนน 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
สิ่งนี้ซ้ำซ้อนจริงหรือ จะต้องใช้อะไรมากกว่านี้เพื่อทำให้แตกต่าง
Kendall Frey

1
@Quincunx จริง ๆ แล้วจะสร้างเกมที่ยอดเยี่ยม
Kendall Frey

4
ฉันพบว่าหัวใจของความท้าทายนี้ "ค้นหาทางออกที่ดีที่สุด" ให้มีความโดดเด่น แต่เป็นที่ยอมรับว่าเป็นตัวเลือกที่ไม่ดีที่จะใส่ไว้ใน "shell" ที่ซ้ำกัน หนึ่งในนี้กรีดร้องว่า "โอ้ดูความท้าทายอีก 2048 รหัสกอล์ฟ" ด้วยการโหวตอย่างใกล้ชิดเป็นส่วนตัวดังนั้นคุณต้องขายความท้าทายของคุณให้กับฝูงชน บางครั้งนั่นหมายถึงการสร้างจุดเริ่มต้นที่เลวร้ายของคุณเองในปี 2048
Rainbolt

คำตอบ:


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 เมื่อผมเล่น 2,048 ตัวเอง: เพียงแค่สลับกันระหว่างขึ้นและซ้าย ในการทำให้งานนี้นานที่สุดเท่าที่จะเป็นไปได้ลูกใหม่4จะเกิดที่มุมล่างขวา

แก้ไข:ฉันได้เพิ่มสวิทช์รหัสยากที่จะไปสองสามครั้งในขั้นตอนเฉพาะก่อนสิ้นซึ่งจริง ๆ แล้วช่วยให้ฉันไปถึง 1024 สิ่งนี้ได้รับค่อนข้างมือดังนั้นฉันจะหยุดกับตอนนี้และ คิดเกี่ยวกับแนวทางที่ดีกว่าในวันพรุ่งนี้ (ความจริงแล้วความจริงที่ว่าฉันสามารถเพิ่มคะแนนของฉันได้ 4 เท่าโดยการเพิ่มแฮ็กที่ปรับแต่งด้วยมือบอกได้แค่ว่ากลยุทธ์ของฉันคืออึ)

นี่คือบอร์ดที่คุณท้ายที่สุด

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

การวางไข่ 4 ครั้งนั้นไม่ได้ให้คะแนนที่ดีที่สุดเพราะคุณไม่ได้รับ 4 คะแนนในแต่ละครั้งที่สร้างขึ้นโดยที่ไม่ถูกสร้างโดย 2 2
BrunoJ

@BrunoJ คะแนนสำหรับความท้าทายนี้คำนวณโดยรวมเป็นไพ่ทั้งหมดในตอนท้ายไม่ใช่คะแนนที่คุณมีในเกมจริง แต่ถ้าเป็นอย่างนั้นคุณก็ถูกต้องแน่นอน ;) ... ถึงแม้ว่าฉันจะคิดด้วยกลยุทธ์ของฉันมันก็ไม่ได้สร้างความแตกต่างเลยเพราะฉันจะได้แค่ 128 แทนที่จะเป็น 256 แล้ว
Martin Ender

โอ้ไม่ทราบว่าการให้คะแนนไม่เหมือนกันขอโทษฉัน
BrunoJ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.