How to resolve the algorithm 2048 step by step in the Julia programming language

Published on 22 June 2024 08:30 PM

How to resolve the algorithm 2048 step by step in the Julia programming language

Table of Contents

Problem Statement

Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.

The name comes from the popular open-source implementation of this game mechanic, 2048.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm 2048 step by step in the Julia programming language

The provided Julia code defines functions and a graphical user interface (GUI) for a 2048 game:

  1. shifttiles!: This function handles the movement of tiles in the 2048 game. It takes a matrix representing the game board (b), the size of the board (siz), and the direction of movement (direction). It adjusts the rotation of the matrix if the movement is not leftward (which is the default implementation) and then performs the leftward shift. The leftshift! function is called to perform the shift and calculate any points gained or winner status. Finally, the rotated matrix is rotated back to its original orientation, and the updated board, points gained, and winner status are returned.

  2. compactleft!: This function compacts the tiles in a given row of the game board to the left. It iterates through the columns and shifts any non-zero tiles to the left, effectively condensing the tiles together.

  3. leftshift!: This function handles the core logic of the 2048 game. It operates on each row of the input matrix b and performs the following steps:

    • Compacts tiles to the left using compactleft!.
    • Iterates over the row and checks for adjacent tiles with the same value. If found, the tiles are merged into a single tile with double the value, and the corresponding row element is set to 0. This process continues until no more merges are possible.
    • Compacts tiles to the left again, ensuring they are packed tightly.
    • Keeps track of the points gained from the merges and returns the updated row and the winner status (set to true if a 2048 tile is created).
  4. app2048: This function defines the graphical user interface (GUI) for the 2048 game. It sets up a window with a toolbar and a grid to display the game board. It also initializes various game variables, including the game board, past board states, score, game over status, etc. The function handles events such as button clicks and key presses within the game window.

  5. update!: This function updates the GUI to reflect the current state of the game board. It iterates through the board and sets the labels of the buttons (representing each tile) to the corresponding values. It also updates the window title with the current score.

  6. newrandomtile!: This function adds a new random tile to the game board. It checks for empty cells (blanks) and randomly chooses one. It then sets the value of the chosen cell to either 2 or 4 with a certain probability.

  7. initialize!: This function initializes a new game or resets the game state. It clears the board, adds two random tiles, and sets the game over status to false.

  8. undo!: This function allows the player to undo their last move. It pops the previous board state from the pastboardstates array (which stores previous game states) and updates the current board to reflect the previous state.

  9. keypress: This event handler is used to capture key press events in the game window. It maps the arrow key codes to corresponding game directions (Up, Left, Down, Right) and calls the shifttiles! function to perform the appropriate move.

  10. endit: This function is called when the game window is closed. It notifies the condition object to end the main event loop and terminate the program.

  11. The main event loop is started by wait(condition), which blocks the program until the condition object is notified by endit when the game window is closed.

Overall, this code provides the core game logic and a graphical user interface for playing the 2048 game. It handles tile movement, merging, score tracking, and game over conditions.

Source code in the julia programming language

using Gtk.ShortNames

@enum Direction2048 Right Left Up Down

"""
    shifttiles!
The adding and condensing code is for a leftward shift, so if the move is not
leftward, this will rotate matrix to make move leftward, move, then undo rotation.
"""
function shifttiles!(b, siz, direction)
    if direction == Right
        tmpb = rot180(b); points, winner = leftshift!(tmpb, siz); tmpb = rot180(tmpb)
    elseif direction == Up
        tmpb = rotl90(b); points, winner = leftshift!(tmpb, siz); tmpb = rotr90(tmpb)
    elseif direction == Down
        tmpb = rotr90(b); points, winner = leftshift!(tmpb, siz); tmpb = rotl90(tmpb)
    else # left movement function as coded
        return leftshift!(b, siz)
    end
    for i in 1:siz, j in 1:siz
        b[i,j] = tmpb[i,j]   # copy tmpb contents back to b (modifies b)
    end
    points, winner
end


function compactleft!(b, siz, row)
    tmprow = zeros(Int, siz)
    tmppos = 1
    for j in 1:siz
        if b[row,j] != 0
            tmprow[tmppos] = b[row,j]
            tmppos += 1
        end
    end
    b[row,:] = tmprow
end

"""
    leftshift!
Work row by row. First, compact tiles to the left if possible. Second, find and
replace paired tiles in the row, then re-compact. Keep score of merges and return
as pointsgained. If a 2048 value tile is created, return a winner true value.
"""
function leftshift!(b, siz)
    pointsgained = 0
    winner = false
    for i in 1:siz
        compactleft!(b, siz, i)
        tmprow = zeros(Int, siz)
        tmppos = 1
        for j in 1:siz-1
            if b[i,j] == b[i,j+1]
                b[i,j] = 2 * b[i,j]
                b[i,j+1] = 0
                pointsgained += b[i,j]
                if b[i,j] == 2048     # made a 2048 tile, which wins game
                    winner = true
                end
            end
            if b[i,j] != 0
                tmprow[tmppos] = b[i,j]
                tmppos += 1
            end
        end
        tmprow[siz] = b[i,siz]
        b[i,:] = tmprow
        compactleft!(b, siz, i)
    end
    pointsgained, winner
end

"""
    app2048
Run game app, with boardsize (choose 4 for original game) as an argument.
"""
function app2048(bsize)
    win = Window("2048 Game", 400, 400) |> (Frame() |> (box = Box(:v)))
    toolbar = Toolbar()
    newgame = ToolButton("New Game")
    set_gtk_property!(newgame, :label, "New Game")
    set_gtk_property!(newgame, :is_important, true)
    undomove = ToolButton("Undo Move")
    set_gtk_property!(undomove, :label, "Undo Move")
    set_gtk_property!(undomove, :is_important, true)
    map(w->push!(toolbar,w),[newgame,undomove])
    grid = Grid()
    map(w -> push!(box, w),[toolbar, grid])
    buttons = Array{Gtk.GtkButtonLeaf,2}(undef, bsize, bsize)
    for i in 1:bsize, j in 1:bsize
        grid[i,j] = buttons[i,j] = Button()
        set_gtk_property!(buttons[i,j], :expand, true)
    end
    board = zeros(Int, (bsize,bsize))
    pastboardstates = []
    score = 0
    gameover = false
    condition = Condition()
    won = ""

    function update!()
        for i in 1:bsize, j in 1:bsize
            label = (board[i,j] > 0) ? board[i,j] : " "
            set_gtk_property!(buttons[i,j], :label, label)
        end
        set_gtk_property!(win, :title, "$won 2048 Game  (Score: $score)")
    end
    function newrandomtile!()
        blanks = Array{Tuple{Int,Int},1}()
        for i in 1:bsize, j in 1:bsize
            if board[i,j] == 0
                push!(blanks, (i,j))
            end
        end
        if length(blanks) == 0
            gameover = true
        else
            i,j = rand(blanks)
            board[i,j] = (rand() > 0.8) ? 4 : 2
        end
    end
    function initialize!(w)
        won = ""
        gameover = false
        for i in 1:bsize, j in 1:bsize
            board[i,j] = 0
            set_gtk_property!(buttons[i,j], :label, " ")
        end
        newrandomtile!()
        update!()
    end
    function undo!(w)
        if gameover == false
            board = pop!(pastboardstates)
            update!()
        end
    end
    function keypress(w, event)
        presses = Dict(37 => Up,    # code rotated 90 degrees
                       38 => Left,  # because of Gtk coordinates
                       39 => Down,  # y is downward positive
                       40 => Right)
        keycode = event.hardware_keycode
        if haskey(presses, keycode) && gameover == false
            push!(pastboardstates, copy(board))
            newpoints, havewon = shifttiles!(board, bsize, presses[keycode])
            score += newpoints
            if havewon && won != "Winning"
                won = "Winning"
                info_dialog("You have won the game.")
            end
            newrandomtile!()
            update!()
            if gameover
                info_dialog("Game over.\nScore: $score")
            end
        end
    end
    endit(w) = notify(condition)
    initialize!(win)
    signal_connect(initialize!, newgame, :clicked)
    signal_connect(undo!,undomove, :clicked)
    signal_connect(endit, win, :destroy)
    signal_connect(keypress, win, "key-press-event")
    Gtk.showall(win)
    wait(condition)
end


const boardsize = 4
app2048(boardsize)


  

You may also check:How to resolve the algorithm Longest string challenge step by step in the FreeBASIC programming language
You may also check:How to resolve the algorithm Record sound step by step in the Common Lisp programming language
You may also check:How to resolve the algorithm Forward difference step by step in the Objeck programming language
You may also check:How to resolve the algorithm Mandelbrot set step by step in the IDL programming language
You may also check:How to resolve the algorithm Hello world/Graphical step by step in the Delphi programming language