Create 2048 Game using Python

FREE Online Courses: Transform Your Career – Enroll for Free!

2048 is a simple mathematics puzzle game. It is a really addictive and interesting game. Let’s build 2048 game with basic knowledge of Python.

About Python 2048 Game Project

The objective of the project is to develop a 2048 game using python tkinter. In this game, we have to press any one of four keys to move up, down, left, or right. When we press a key, the elements move in the direction of the respective key and if any two same numbers are in that same row or column they get added up.

Project Prerequisites

To develop this game we need a basic knowledge of this game and some models like tkinter, random and configparser.

  • tkinter – for use Interface(UI)
  • random – to generate random values

Download 2048 GameProject Code

Please download the full source code of 2048 game: Python 2048 Game Code

Steps to Build 2048 Game using Python

Let’s see the steps to create python 2048 Game.

  • First we will import all the necessary modules.
  • In the second step we will create the game window for the user.
  • Then we will create a function to accept the keys from the user and move the cell according to it.
  • Then create two functions one for game over and one for game won.

Project File Structure

Below is the structure of python 2048 game:

  1. Importing modules
  2. Creating display function
  3. Define Function
  4. Creating main function

1. Importing Modules for Python 2048 Game

We first import all the necessary libraries required for this project.

# ==== Importing all necessary libraries for PythonGeeks Python 2048 Game
from tkinter import *
import random

2. Create Display Window

First we’ll create the main class named Play_2048, in which we will first create an initiator function where we pass the root for the interface. With the help of root we will set the title, geometry, background image, frames and buttons for the interface.

# ==== creating main class
class Play_2048(Tk):

   # ==== adding necessary class variables
   game_board = []
   new_random_tiles = [2, 2, 2, 2, 2, 2, 4]
   score = 0
   high_score = 0
   game_score = 0
   highest_score = 0

   # ==== creating user window
   def __init__(self, *args, **kwargs):
       Tk.__init__(self, *args, **kwargs)
       # ==== create user interface
       self.game_score = StringVar(self)
       self.game_score.set("0")
       self.highest_score = StringVar(self)
       self.highest_score.set("0")

       # ==== adding new game , score and highest score option
       self.button_frame = Frame(self)
       self.button_frame.grid(row=2, column=0, columnspan=4)
       Button(self.button_frame, text="New Game", font=("times new roman", 15), command=self.new_game).grid(row=0, column=0)
       self.button_frame.pack(side="top")

       Label(self.button_frame, text="Score:", font=("times new roman", 15)).grid(row=0, column=1)
       Label(self.button_frame, textvariable=self.game_score, font=("times new roman", 15)).grid(row=0, column=2)
       Label(self.button_frame, text="Record:", font=("times new roman", 15)).grid(row=0, column=3)
       Label(self.button_frame, textvariable=self.highest_score, font=("times new roman", 15)).grid(row=0, column=4)

       self.canvas = Canvas(self, width=410, height=410, borderwidth=5, highlightthickness=0)
       self.canvas.pack(side="top", fill="both", expand="false")

       # ==== create new game
       self.new_game()

3. Define functions

a. new_tiles()

This function will add new tiles to the game window when we perform any movement in game. The tiles will have either number 2 or number 4 and the new generated tiles will have different colors for both the numbers.

# ==== add new tiles in python 2048 game
def new_tiles(self):
    index = random.randint(0, 6)
    x = -1
    y = -1

    # ==== check while game is not over
    while self.full() == False:
        x = random.randint(0, 3)
        y = random.randint(0, 3)

        if (self.game_board[x][y] == 0):
            self.game_board[x][y] = self.new_random_tiles[index]
            x1 = y * 105
            y1 = x * 105
            x2 = x1 + 105 - 5
            y2 = y1 + 105 - 5
            num = self.game_board[x][y]
            if num == 2:
                self.square[x, y] = self.canvas.create_rectangle(x1, y1, x2, y2, fill="#e0f2f8", tags="rect",
                                                                 outline="", width=0)
                self.canvas.create_text((x1 + x2) / 2, (y1 + y2) / 2, font=("Arial", 36), fill="#f78a8a", text="2")
            elif num == 4:
                self.square[x, y] = self.canvas.create_rectangle(x1, y1, x2, y2, fill="#b8dbe5", tags="rect",
                                                                 outline="", width=0)
                self.canvas.create_text((x1 + x2) / 2, (y1 + y2) / 2, font=("Arial", 36), fill="#f78a8a", text="4")

            Break

b. full()

This function will check whether all the grid in the game is full or not. It will return either True or False.

# ==== showing game board
 def show_board(self):
     cellwidth = 105
     cellheight = 105
     self.square = {}

     for column in range(4):
         for row in range(4):
             x1 = column * cellwidth
             y1 = row * cellheight
             x2 = x1 + cellwidth - 5
             y2 = y1 + cellheight - 5
             num = self.game_board[row]
             if num == 0:
                 self.show_number0(row, column, x1, y1, x2, y2)
             else:
                 self.show_number(row, column, x1, y1, x2, y2, num)

c. show_board()

This function will show the game board. Each number in the game window will have a separate color. The numbers in the game board are 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 and 2048.

# ==== showing game board in python 2048 game
  def show_board(self):
      cellwidth = 105
      cellheight = 105
      self.square = {}

      for column in range(4):
          for row in range(4):
              x1 = column * cellwidth
              y1 = row * cellheight
              x2 = x1 + cellwidth - 5
              y2 = y1 + cellheight - 5
              num = self.game_board[row]
              if num == 0:
                  self.show_number0(row, column, x1, y1, x2, y2)
              else:
                  self.show_number(row, column, x1, y1, x2, y2, num)

d. show_number0()

This function will have to show the color of the grid when there is no number on it.

# ==== show board block when it is empty
   def show_number0(self, row, column, a, b, c, d):
       self.square[row, column] = self.canvas.create_rectangle(a, b, c, d, fill="#f5f5f5", tags="rect", outline="")

e. show_number()

This function will show the color of the grid and number as respect to the different numbers.

# ==== show board number
   def show_number(self, row, column, a, b, c, d, num):
       bg_color = {'2': '#eee4da', '4': '#ede0c8', '8': '#edc850', '16': '#edc53f', '32': '#f67c5f', '64': '#f65e3b', '128': '#edcf72', '256': '#edcc61', '512': '#f2b179', '1024': '#f59563', '2048': '#edc22e',}
       color = {'2': '#776e65', '4': '#f9f6f2', '8': '#f9f6f2', '16': '#f9f6f2', '32': '#f9f6f2', '64': '#f9f6f2', '128': '#f9f6f2', '256': '#f9f6f2', '512': '#776e65', '1024': '#f9f6f2', '2048': '#f9f6f2', }
       self.square[row, column] = self.canvas.create_rectangle(a, b, c, d, fill=bg_color[str(num)], tags="rect", outline="")
       self.canvas.create_text((a + c) / 2, (b + d) / 2, font=("Arial", 36), fill=color[str(num)], text=str(num))

f. moves()

This function will accept the different events performed by the user and perform the movement of blocks of grid as per the event. The events given by the user are ‘UP’, ‘DOWN’, ‘LEFT’, and ‘RIGHT’.

# ==== moves by user
def moves(self, event):

    if event.keysym == 'Down':
        for j in range(0, 4):
            shift = 0
            for i in range(3, -1, -1):
                if self.game_board[i][j] == 0:
                    shift += 1
                else:
                    if i - 1 >= 0 and self.game_board[i - 1][j] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i - 1][j] = 0
                    elif i - 2 >= 0 and self.game_board[i - 1][j] == 0 and self.game_board[i - 2][j] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i - 2][j] = 0
                    elif i == 3 and self.game_board[2][j] + self.game_board[1][j] == 0 and self.game_board[0][j] == self.game_board[3][
                        j]:
                        self.game_board[3][j] *= 2
                        self.score += self.game_board[3][j]
                        self.game_board[0][j] = 0
                    if shift > 0:
                        self.game_board[i + shift][j] = self.game_board[i][j]
                        self.game_board[i][j] = 0
        self.show_board()
        self.new_tiles()
        self.game_over()
    elif event.keysym == 'Right':
        for i in range(0, 4):
            shift = 0
            for j in range(3, -1, -1):
                if self.game_board[i][j] == 0:
                    shift += 1
                else:
                    if j - 1 >= 0 and self.game_board[i][j - 1] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i][j - 1] = 0
                    elif j - 2 >= 0 and self.game_board[i][j - 1] == 0 and self.game_board[i][j - 2] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i][j - 2] = 0
                    elif j == 3 and self.game_board[i][2] + self.game_board[i][1] == 0 and self.game_board[0][j] == self.game_board[3][
                        j]:
                        self.game_board[i][3] *= 2
                        self.score += self.game_board[i][3]
                        self.game_board[i][0] = 0
                    if shift > 0:
                        self.game_board[i][j + shift] = self.game_board[i][j]
                        self.game_board[i][j] = 0
        self.show_board()
        self.new_tiles()
        self.game_over()
    elif event.keysym == 'Left':
        for i in range(0, 4):
            shift = 0
            for j in range(0, 4):
                if self.game_board[i][j] == 0:
                    shift += 1
                else:
                    if j + 1 < 4 and self.game_board[i][j + 1] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i][j + 1] = 0
                    elif j + 2 < 4 and self.game_board[i][j + 1] == 0 and self.game_board[i][j + 2] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i][j + 2] = 0
                    elif j == 0 and self.game_board[i][1] + self.game_board[i][2] == 0 and self.game_board[i][3] == self.game_board[i][
                        0]:
                        self.game_board[i][0] *= 2
                        self.score += self.game_board[i][0]
                        self.game_board[i][3] = 0
                    if shift > 0:
                        self.game_board[i][j - shift] = self.game_board[i][j]
                        self.game_board[i][j] = 0
        self.show_board()
        self.new_tiles()
        self.game_over()
    elif event.keysym == 'Up':
        for j in range(0, 4):
            shift = 0
            for i in range(0, 4):
                if self.game_board[i][j] == 0:
                    shift += 1
                else:
                    if i + 1 < 4 and self.game_board[i + 1][j] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i + 1][j] = 0
                    elif i + 2 < 4 and self.game_board[i + 1][j] == 0 and self.game_board[i + 2][j] == self.game_board[i][j]:
                        self.game_board[i][j] *= 2
                        self.score += self.game_board[i][j]
                        self.game_board[i + 2][j] = 0
                    elif i == 0 and self.game_board[1][j] + self.game_board[2][j] == 0 and self.game_board[3][j] == self.game_board[0][
                        j]:
                        self.game_board[0][j] *= 2
                        self.score += self.game_board[0][j]
                        self.game_board[3][j] = 0
                    if shift > 0:
                        self.game_board[i - shift][j] = self.game_board[i][j]
                        self.game_board[i][j] = 0
        self.show_board()
        self.new_tiles()
        self.game_over()

    self.game_score.set(str(self.score))
    if self.score > self.high_score:
        self.high_score = self.score
        self.highest_score.set(str(self.high_score))

g. new_game()

This function will create a new game for the user. It will display a fresh game with the last highest score of the user.

# ==== to create new python 2048 game
def new_game(self):
    self.score = 0
    self.game_score.set("0")
    self.game_board = []
    self.game_board.append([0, 0, 0, 0])
    self.game_board.append([0, 0, 0, 0])
    self.game_board.append([0, 0, 0, 0])
    self.game_board.append([0, 0, 0, 0])
    while True:
        x = random.randint(0, 3)
        y = random.randint(0, 3)
        if (self.game_board[x][y] == 0):
            self.game_board[x][y] = 2
            break

    index = random.randint(0, 6)
    while self.full() == False:
        x = random.randint(0, 3)
        y = random.randint(0, 3)
        if (self.game_board[x][y] == 0):
            self.game_board[x][y] = self.new_random_tiles[index]
            break
    self.show_board()

h. game_over()

This function will check for game over, it will return True if the game is over and display a new empty grid window displaying “GAME OVER”.

# ==== check for game over
  def game_over(self):
      for i in range(0, 4):
          for j in range(0, 4):
              if (self.game_board[i][j] == 2048):
                  self.game_won()
      for i in range(0, 4):
          for j in range(0, 4):
              if (self.game_board[i][j] == 0):
                  return False
      for i in range(0, 4):
          for j in range(0, 3):
              if (self.game_board[i][j] == self.game_board[i][j + 1]):
                  return False
      for j in range(0, 4):
          for i in range(0, 3):
              if self.game_board[i][j] == self.game_board[i + 1][j]:
                  return False
      gameover = [["G", "A", "M", "E", ], ["", "", "", ""], ["O", "V", "E", "R"], ["", "", "", ""]]
      cellwidth = 105
      cellheight = 105
      self.square = {}

      for column in range(4):
          for row in range(4):
              a = column * cellwidth
              b = row * cellheight
              c = a + cellwidth - 5
              d = b + cellheight - 5
              self.square[row, column] = self.canvas.create_rectangle(a, b, c, d, fill="#ede0c8", tags="rect",
                                                                      outline="")
              self.canvas.create_text((a + c) / 2, (b + d) / 2, font=("Arial", 36), fill="#494949",
                                      text=gameover[row])
      return True

h. game_won()

This function will check for a game won and condition for game won is the user has to make a grid of value 2048, then it will return True and display a new empty grid window displaying “GAMEWON!”.

# ==== check for game won
def game_won(self):
    gameover = [["Y", "O", "U", "", ], ["", "", "", ""], ["W", "O", "N", "!"], ["", "", "", ""]]
    cellwidth = 105
    cellheight = 105
    self.square = {}
    for column in range(4):
        for row in range(4):
            a = column * cellwidth
            b = row * cellheight
            c = a + cellwidth - 5
            d = b + cellheight - 5
            self.square[row, column] = self.canvas.create_rectangle(a, b, c, d, fill="#ede0c8", tags="rect",
                                                                    outline="")
            self.canvas.create_text((a + c) / 2, (b + d) / 2, font=("Arial", 36), fill="#494949",
                                    text=gameover[row])

4. Creating the main function

In the main function, the main window of tkinter is made and the creation of objects for the main class is done. In this function, we will pass the user moves, title of our project, size of game window.

if __name__ == "__main__":
   # ==== preparing main window
   app = Play_2048()
   app.bind_all('<Key>', app.moves)
   app.wm_title("2048 by PythonGeeks")
   app.minsize(430, 470)
   app.mainloop()

Python 2048 Project Output

python 2048 project output

Summary

YAY!! We have successfully developed the 2048 game using python and the tkinter library. We learn how to use tkinter to make GUI. This tutorial is divided into various tasks.

I hope you enjoyed building this project using this tutorial at PythonGeeks.

Your 15 seconds will encourage us to work even harder
Please share your happy experience on Google | Facebook


Leave a Reply

Your email address will not be published. Required fields are marked *