Flipping Tiles (memory game) using Python3


Welcome to this blog post where we will be discussing the implementation of a fun game called Flip! using Python. Flip! is a game that involves flipping over tiles on a 4x4 grid to reveal their color. The objective of the game is to flip over all the tiles while making as few moves as possible. In this post, we will go through the implementation of the game using Python and explain the different components of the code.

Syntax

The following packages are used in this code −

  • itertools − This package provides functions to iterate over collections in a simpler way.

  • tkinter − This package provides a graphical user interface (GUI) for the game.

  • random − This package provides functions to generate random numbers.

  • ctypes − This package provides access to low-level Windows functions.

As each of these packages is a part of the default Python library, extra installation is not necessary.

Algorithm

  • A button's color is exposed when it is pushed, and it is compared to the color of the button that was pressed before it.

  • The buttons stay in the reverse position and the player's score is updated if the two colors match. The buttons flip back over and the player's score is not changed if the two colors do not coordinate.

  • The game goes on until all of the buttons have been flipped over and the program saves the player's highest score in a text file called maxscore.txt.

  • When comparing the player's score to their best score at the conclusion of the game, the best score is altered in the file if the player's score is greater.

  • Pushing a button causes the button's white background to change to reveal the color underneath.

  • When the same color buttons are pushed back-to-back, they remain upside-down. By consecutively pressing two buttons of different colors, they turn back around.

  • The game ends and the player's score is shown after all the buttons have been turned over.

  • The amount of times the player hits a button to turn it over determines their score.

import itertools
import tkinter as tk
import random
import ctypes

ctypes.windll.shcore.SetProcessDpiAwareness(1)
pressed = -1
tile_flipped = 16
count_move = 0
maxscore = 0

def is_winner():
   global maxscore, count_move
   if tile_flipped == 0:
      if count_move <= maxscore or maxscore == -1:
         maxscore = count_move
         with open('maxscore.txt', 'w') as f:
            f.write(str(maxscore))
      win_lbl['text'] = f'CLICKS: {str(count_move)}, BEST: {str(maxscore)}'

def print_count_move():
   win_lbl['text'] = f'CLICKS: {str(count_move)}'

def new_game():
   global pressed, tile_flipped, btns, colours, count_move, win_lbl, maxscore
   pressed = -1
   tile_flipped = 16
   count_move = 0
   btns = {}
   win_lbl['text'] = ''

   # make the file if it doesn't exist
   try:
      with open('maxscore.txt', 'r') as f:
         pass
   except FileNotFoundError:
      with open('maxscore.txt', 'w') as f:
         f.write('-1')
             
   with open('maxscore.txt', 'r') as f:
      maxscore = int(f.readline().strip())
   random.shuffle(colours)

   k=0
   for _, _ in itertools.product(range(4), range(4)):
      btn = Button(k)
      btns[k] = btn
      if k!= len(colours)-1: k+=1

   k=0
   for i, j in itertools.product(range(4), range(4)):
      btns[k].bttn.grid(row=i, column=j, sticky='nsew')
      if k!= len(colours)-1: k+=1

class Button:
   def __init__(self, k):
      self.index = k
      self.bttn = tk.Button(frm,width=6, height=2,borderwidth=6, bg='white', activebackground = colours[self.index],command=self.btn_press)
        
   def btn_press(self):
      global pressed, count_move
      self.bttn.configure(bg=colours[self.index])
      count_move += 1
      print_count_move()
      if pressed == -1:
         pressed = self.index
      else:
         self.compare_pressed_btns()
    
   def compare_pressed_btns(self):
      global pressed
      global tile_flipped

      if colours[self.index] != colours[pressed]:
         self.bttn.configure(bg='white')
         btns[pressed].bttn.configure(bg='white')
      elif self.index != pressed:
         self.bttn['state'] = tk.DISABLED
         btns[pressed].bttn['state']= tk.DISABLED
         tile_flipped -= 2
         is_winner()

      else:
         self.bttn.configure(bg='white')
      pressed = -1
       
window = tk.Tk()
window.title('Flip!')
window.config(bg = 'black')

window.rowconfigure([0,1],weight=1,pad=2)
window.columnconfigure(0,weight =1, pad=2)

frm = tk.Frame(window, bg='Gray')
frm.grid(row = 0, column=0, sticky='nsew')

frm.rowconfigure(list(range(4)), minsize=50, pad=2)
frm.columnconfigure(list(range(4)), minsize=50, pad=2)

btns = {}
colours=['YellowGreen', 'Violet', 'Tomato', 'SlateBlue', 'DarkCyan', 'Orange','DodgerBlue', 'ForestGreen']*2
random.shuffle(colours)
frm2 = tk.Frame(window, bg='Khaki')
win_lbl = tk.Label(frm2,width=19, height=1,bg='PowderBlue',relief=tk.GROOVE,borderwidth=2)
win_lbl.grid(row=0, column=0, padx=5, pady=5, sticky='nsew')

new_game_btn = tk.Button(text='NEW GAME', master=frm2, width=10, height=1, borderwidth=3, bg='Plum', command=new_game)
new_game_btn.grid(row=0, column=1, padx=5, pady=5, sticky = 'nsew')
frm2.grid(row=1, column=0, sticky='nsew')
new_game()

window.mainloop()

Output

Explanation

  • The player is offered a grid of buttons in this condensed version of the popular memory game Flip, with each button initially appearing in white and each button in a 4x4 grid has a color concealed underneath it. The user is tasked with matching the colors of two buttons when they are flipped over and the game ends until no two buttons remain.

  • Import the necessary libraries, including random, itertools, tkinter for the graphical user interface, and ctypes for Windows-specific functionality, first. Random module is utilized to rearrange the button tones. Set up different worldwide factors to follow the game's advancement. "pressed" keeps track of the index of the most recent button press, "tile flipped" shows how many buttons have been matched, "count move" shows how many moves were made, and "maxscore" shows the highest score in the game.

  • The is_winner function is responsible for checking if the game has been won or not. It checks if all the tiles have been flipped, i.e., if tile_flipped is equal to zero, and if so, it checks if the current number of moves count_move is less than or equal to the previous best score maxscore. If it is, it updates the maxscore to the new count_move and writes it to a file named maxscore.txt. Finally, it updates the text of the win_lbl label to show the current score and best score.

  • The print_count_move function updates the win_lbl label to show the current number of moves.

  • The new_game function is responsible for resetting the game. It initializes the variables to their default values, clears the win_lbl label, and reads the previous best score from the maxscore.txt file. Then, it shuffles the list of colors and creates a grid of buttons using the Button class. It also sets the grid layout of the buttons on the screen.

  • The Button class defines the properties and behavior of each tile in the game. Each button has an index value that corresponds to its position in the shuffled list of colors. It creates a tk.Button object with a white background color and an active background color that matches its assigned color. When the button is clicked, its background color is changed to its assigned color, and the count_move is incremented. If the button is the first button to be clicked, it stores its index value in the pressed variable. If it is the second button to be clicked, it compares its color to the color of the first button by calling the compare_pressed_btns method. If the colors match, the buttons are disabled, and the tile_flipped count is decremented. If the colors do not match, the buttons' background color is changed back to white.

  • Finally, the main body of the code initializes the GUI window, sets its title and background color, and creates the frm and frm2 frames that will hold the game board and the score label and new game button, respectively. It also creates the win_lbl label and the new_game_btn button and sets their properties. It then calls the new_game function to start the game. Finally, it enters the main event loop using window.mainloop().

Applications

This project may demonstrate the ideas of graphical user interface (GUI), buttons, and functions; likewise, it fills in as a phenomenal method for evaluating and further developing one's memory abilities by utilizing a sharp graphical associating point. The game can be further modified to include a variety of shapes, colors, and images, making it a great project for beginners to learn how to program graphical user interfaces with Python.

Conclusion

The Flipping Tiles game, using the Tkinter toolkit and Python 3, is entertaining and interesting, and it's an excellent project for learning Python GUI development. The usage of buttons and functions demonstrates how interactive graphical interfaces may be made using a programming language and a GUI framework and hence this puzzle may be tailored to one's liking and is a good place for novices to start learning about the Python programming language's graphical user interface.

Updated on: 22-Aug-2023

106 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements