Site icon TechVidvan

Learn How to Create 2048 Game in Python

2048 is a popular simple mathematical sliding puzzle game played by a single player. 2048 is a very addictive game and the main thing which is performed in this 2048 game is addition and combining the tiles. So let’s build this 2048 game using python and Tkinter.

What is the 2048 Game?

In this game, players have to swipe the numbered tiles using arrow keys of the keyboard and create a tile with number 2048 by combining the tiles. And by combining scores get increases. Once every tile on board gets occupied you will lose.

Python 2048 game Project Details

The main aim of this project is to build a 2048 game using python in GUI. This is a simple 2048 game in python programming. Here we use the tkinter python library for creating a graphical user interface that is a GUI and also we have to import random python module.

Here we’ve tried our best to make the same color code as the original 2048 game contains. In this game we have to combine numbered tile to make high numbered tile. The goal of the 2048 game is to get 2048 in one of the cells.

This game includes a single player. The game starts with only two tiles and the lowest number tile is two, then player have to combine the titles and make a high numbers tile. Once you got 2048 in any row you won the game and the player lost the game which means that every tile on the board is occupied and there are no possible moves left. So the game is over.

Project Prerequisite

This project requires good knowledge of python and the Tkinter library. Tkinter is the python binding to the Tk toolkit which is used across many programming languages for building Graphical user interface which is GUI.

Download 2048 Python Code

Please download the source code of Python 2048 game from the following link: Python 2048 Game Project

Steps to Build Python Project on 2048 Game

Below are the steps to develop python 2048 game from scratch:

  1. Import module
  2. Creating Game class
  3. Making Color Coding
  4. Create a function To make GUI
  5. Creating Score header
  6. Create a function to start game
  7. Make matrix manipulation functions
  8. Create a function to randomly add new tile
  9. Create a function to update GUI
  10. Create a function for pressing arrow buttons for playing game
  11. Create a function to check if any moves are possible
  12. Function to check if game is over

Step 1- Importing Modules random and tkinter

#2048 python code - import modules
import tkinter as tk
import random

Code Explanation-

Step 2- Creating Game class

class Game(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.grid()
        self.master.title("2048 by TechVidvan")
 
        self.grid_main = tk.Frame(
            self, bg=Game.Color_grid, bd=3, width=600, height=600
        )
        self.grid_main.grid(pady=(110,0))
 
        self.GUI_maker()
        self.start_game()
 
        self.master.bind("<Left>", self.left)
        self.master.bind("<Right>", self.right)
        self.master.bind("<Up>", self.up)
        self.master.bind("<Down>", self.down)
 
        self.mainloop()

Code Explanation-

Step 3- Making Color Coding

#TechVidvan- Making Color Coding
 
    Color_grid = "#b8afa9"
    Color_EmptyCell = "#ffd5b5"
    Font_ScoreLabel = ("Verdana", 24)
    Font_Score = ("Helvetica", 48, "bold")
    Font_GameOver = ("Helvetica", 48, "bold")
    Font_Color_GameOver = "#ffffff"
    Winner_BG = "#ffcc00"
    Loser_BG = "#a39489"
 
    Color_Cells = {
        2: "#fcefe6",
        4: "#f2e8cb",
        8: "#f5b682",
        16: "#f29446",
        32: "#ff775c",
        64: "#e64c2e",
        128: "#ede291",
        256: "#fce130",
        512: "#ffdb4a",
        1024: "#f0b922",
        2048: "#fad74d"    
    }
 
    Color_CellNumber = {
        2: "#695c57",
        4: "#695c57",
        8: "#ffffff",
        16: "#ffffff",
        32: "#ffffff",
        64: "#ffffff",
        128: "#ffffff",
        256: "#ffffff",
        512: "#ffffff",
        12048: "#ffffff"
    }
 
    Fonts_CellNumebr = {
        2: ("Helvetica", 55, "bold"),
        4: ("Helvetica", 55, "bold"),
        8: ("Helvetica", 55, "bold"),
        16: ("Helvetica", 50, "bold"),
        32: ("Helvetica", 50, "bold"),
        64: ("Helvetica", 50, "bold"),
        128: ("Helvetica", 45, "bold"),
        256: ("Helvetica", 45, "bold"),
        512: ("Helvetica", 45, "bold"),
        1024: ("Helvetica", 40, "bold"),
        2048: ("Helvetica", 40, "bold"),
    }    

Code Explanation-

Step 4- Create a function To make GUI

#TechVidvan- Create a function To make GUI
 
    def GUI_maker(self):
        #make grid
        self.cells = []
        for i in range(4):
            row = []
            for j in range(4):
                frame_cells = tk.Frame(
                    self.grid_main,
                    bg=Game.Color_EmptyCell,
                    width=150,
                    height=150
                )
                frame_cells.grid(row=i, column=j, padx=5, pady=5)
                cell_number = tk.Label(self.grid_main, bg=Game.Color_EmptyCell)
                cell_data = {"frame":frame_cells, "number": cell_number}
 
                cell_number.grid(row=i, column=j)
                row.append(cell_data)
            self.cells.append(row)

Code Explanation-

Step 5- Creating Score header

#TechVidvan - Creating Score header
 
        frame_score = tk.Frame(self)
        frame_score.place(relx=0.5, y=60, anchor="center")
        tk.Label(
            frame_score,
            text="Score",
            font=Game.Font_ScoreLabel
        ).grid(row=0)
        self.label_score = tk.Label(frame_score, text="0", font= Game.Font_Score)
        self.label_score.grid(row=1)

Code Explanation-

Step 6- Create a function to start game

#TechVidvan- Create a function to start game
 
    def start_game(self):
        #create matrix of zeros
        self.matrix = [[0] * 4 for _ in range(4)]
 
        #fill 2 random cells with 2s
        row = random.randint(0,3)
        col = random.randint(0,3)
        self.matrix[row][col] = 2
        self.cells[row][col]["frame"].configure(bg=Game.Color_Cells[2])
        self.cells[row][col]["number"].configure(
            bg=Game.Color_Cells[2],
            fg=Game.Color_CellNumber[2],
            font=Game.Fonts_CellNumber[2],
            text="2"
        )
        while(self.matrix[row][col] != 0):
            row = random.randint(0,3)
            col = random.randint(0,3)
        self.matrix[row][col] = 2
        self.cells[row][col]["frame"].configure(bg=Game.Color_Cells[2])
        self.cells[row][col]["number"].configure(
            bg=Game.Color_Cells[2],
            fg=Game.Color_CellNumber[2],
            font=Game.Fonts_CellNumber[2],
            text="2"
        )
 
        self.score = 0

Code Explanation-

Step 7- Make matrix manipulation functions

#TechVidvan- Make Matrix manipulation functions
 
    def stack(self):
        Matrix_1 = [[0] * 4 for _ in range(4)]
        for i in range(4):
            position_fill = 0
            for j in range(4):
                if self.matrix[i][j] != 0:
                    Matrix_1[i][position_fill] = self.matrix[i][j]
                    position_fill += 1
        self.matrix = Matrix_1
 
    def combine(self):
        for i in range(4):
            for j in range(3):
                if self.matrix[i][j] != 0 and self.matrix[i][j] == self .matrix[i][j + 1]:
                    self.matrix[i][j] *= 2
                    self.matrix[i][j + 1] = 0
                    self.score += self.matrix[i][j]
 
    def reverse(self):
        Matrix_1 = []
        for i in range(4):
            Matrix_1.append([])
            for j in range(4):
                Matrix_1[i].append(self.matrix[i][3-j])
        self.matrix = Matrix_1
 
    def transpose(self):
        Matrix_1 = [[0] * 4 for _ in range(4)]
        for i in range(4):
            for j in range(4):
                Matrix_1[i][j] = self.matrix[j][i]
        self.matrix = Matrix_1

Code Explanation-

  1. We write our stack function to compress to the left side.
  2. Matrix_1 – this is the matrix containing all zeros in our nested for loop for each row in our matrix.
  3. We are going to keep track of the number cell containing a nonzero number and variable called position fill.
  4. If the value in the cell is nonzero we set the value in the new matrix at i fill position to the value. Then we increment the fill position by one and after for loop set.matrix equals to matrix 1.
  1. When two tiles of the same value merge together and collapse in one tile of their sum.
  2. So in this nested for loop we are only looping until column two so we can index with j+1. Then we will be checking if the value at i, j in the matrix is not zero and is equal to the value i, j+1.
  3. We multiply the value at i, j by 2 and make the value i, j+1 equal to zero. Combine the function where we update our score by adding newly combined values to self.score…
  1. Creating a matrix 1 that is an empty list.
  2. In the outer for loop we will append an empty list to matrix 1.
  3. Value gets reversed after the nested for loop we set.matrix equal to matrix 1.
  1. Create matrix1 of all zeros then in our nested for loop we set every value at i, j in matrix 1 with the values at j, i in the current matrix. We set.matrix equal to matrix 1.

Step 8- Create a function to randomly add new tile

#TechVidvan- Create a function to randomly add new 2 or 4 tile to an empty cell
   
    def add_tile(self):
        row = random.randint(0,3)
        col = random.randint(0,3)
        while(self.matrix[row][col] != 0):
            row = random.randint(0,3)
            col = random.randint(0,3)
        self.matrix[row][col] = random.choice([2,4])

Code Explanation-

Step 9- Create a function to update GUI

#TechVidvan- Create a function to update GUI to match the matrix
 
    def GUI_update(self):
        for i in range(4):
            for j in range(4):
                cell_value = self.matrix[i][j]
                if cell_value == 0:
                    self.cells[i][j]["frame"].configure(bg=Game.Color_EmptyCell)
                    self.cells[i][j]["number"].configure(bg=Game.Color_EmptyCell, text="")
                else:
                    self.cells[i][j]["frame"].configure(bg=Game.Color_Cells[cell_value])
                    self.cells[i][j]["number"].configure(
                        bg=Game.Color_Cells[cell_value],
                        fg=Game.Color_CellNumber[cell_value],
                        font=Game.Fonts_CellNumebr[cell_value],
                        text=str(cell_value)
                    )
        self.label_score.configure(text=self.score)
        self.update_idletasks()

Code Explanation-

Step 10- Create a function for pressing arrow buttons for playing game

#TechVidvan- Create a function for pressing arrow buttons for playing game
 
    def left(self, event):
        self.stack()
        self.combine()
        self.stack()
        self.add_tile()
        self.GUI_update()
        self.game_over()
 
    def right(self, event):
        self.reverse()
        self.stack()
        self.combine()
        self.stack()
        self.reverse()
        self.add_tile()
        self.GUI_update()
        self.game_over()
 
    def up(self, event):
        self.transpose()
        self.stack()
        self.combine()
        self.stack()
        self.transpose()
        self.add_tile()
        self.GUI_update()
        self.game_over()
 
    def down(self, event):
        self.transpose()
        self.reverse()
        self.stack()
        self.combine()      
        self.stack()
        self.reverse()
        self.transpose()
        self.add_tile()
        self.GUI_update()
        self.game_over()

Code Explanation-

  1. Calling stack function for compressing non zero numbers to the left side of the matrix.
  2. Calling combine() for combining horizontally adjacent numbers.
  3. Again calling stack to eliminate newly created zeros cells from the combine function.
  4. Then add a new title and GUI update which we do in each of these 4 funcs.
  5. Also, call game over function to over game.
  1. Calling the reverse function to transform, right swipe into left swipe.
  2. Calling stack function for compressing non zero numbers to the left side of the matrix.
  3. Calling combine() for combining horizontally adjacent numbers.
  4. Again calling stack to eliminate newly created zeros cells from the combine function.
  5. Again calling reverse function for reversing the matrix back into its original orientation.
  6. Then add a new title and GUI update. Also call game over function to over game.
  1. We will transpose the matrix to make it work like the left move.
  2. Calling stack function for compressing non zero numbers to the left side of the matrix.
  3. Calling combine() for combining horizontally adjacent numbers.
  4. Again calling stack to eliminate newly created zeros cells from the combine function.
  5. Again call transpose. Then add a new title and GUI update. Also call game over function to over game.
  1. For this we have to transpose and reverse the matrix so a leftward moment can have a downward effect.
  2. Calling stack function for compressing non-zero numbers to the left side of the matrix.
  3. Calling combine() for combining horizontally adjacent numbers.
  4. Again calling stack to eliminate newly created zeros cells from the combine function.
  5. Again call transpose. Then add a new title and GUI update. Also call game over function to over game.

Step 11- Create a function to check if any moves are possible

#TechVidvan - check if any moves are possible
 
    def Exists_horizontalMoves(self):
        for i in range(4):
            for j in range(3):
                if self.matrix[i][j] == self.matrix[i][j + 1]:
                    return True
        return False
 
    def Exists_verticalMoves(self):
        for i in range(3):
            for j in range(4):
                if self.matrix[i][j] == self.matrix[i + 1][j]:
                    return True
        return False

Code Explanation-

Step 12- Function to check if the game is over

#TechVidvan- check if game is over (Win/lose)
 
    def game_over(self):
        if any(2048 in row for row in self.matrix):
            game_over_frame = tk.Frame(self.grid_main, borderwidth=2)
            game_over_frame.place(relx=0.5, rely= 0.5, anchor="center")
            tk.Label(
                game_over_frame,
                text = "YOU WIN!!",
                bg=Game.Winner_BG,
                fg=Game.Font_Color_GameOver,
                font=Game.Font_GameOver
            ).pack()
        elif not any(0 in row for row in self. matrix) and not self.Exists_horizontalMoves() and not self.Exists_verticalMoves():
            game_over_frame = tk.Frame(self.grid_main, borderwidth=2)
            game_over_frame.place(relx=0.5, rely= 0.5, anchor="center")
            tk.Label(
                game_over_frame,
                text = "GAME OVER!!",
                bg=Game.Loser_BG,
                fg=Game.Font_Color_GameOver,
                font=Game.Font_GameOver
            ).pack()
       
def main():
    Game()
 
if __name__ == "__main__":
    main()

Code Explanation-

Python 2048 Game Output

Summary

We have successfully created a python 2048 game using Graphical user Interface(GUI). We have learned about the Tkinter module and the function that module provides. It is really great fun to develop a 2048 game in python using GUI rather than playing, now we will play the 2048 game which we have developed.

Exit mobile version