Skip to content

Instantly share code, notes, and snippets.

@ssaurel
Last active May 8, 2023 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssaurel/67a0a56167d7ba8f7c237ab0e83b7492 to your computer and use it in GitHub Desktop.
Save ssaurel/67a0a56167d7ba8f7c237ab0e83b7492 to your computer and use it in GitHub Desktop.
Flipping Bits Game in Python with Tkinter - Tutorial for the SSaurel's Blog
import tkinter as tk
import random
from copy import deepcopy
class FlippingBitsGame:
def __init__(self, level):
self.level = level # Level = size of the square
self.target = [[0] * level for _ in range(level)] # the board to obtain when you play
self.board = [[0] * level for _ in range(level)] # the current board played by the user
self.solved = True
self.newgame() # new game method to define later
# method to flip a column
def flipcol(self, r):
for i in range(len(self.board[r])):
self.board[r][i] ^= 1 # 0 -> 1, 1 -> 0
# method to flip a row
def fliprow(self, c):
for row in self.board:
row[c] ^= 1
# method to shuffle the board
def shuffle(self):
for _ in range(self.level * self.level):
if random.random() > 0.5:
self.flipcol(random.randint(0, self.level - 1))
else:
self.fliprow(random.randint(0, self.level - 1))
# new game
def newgame(self):
if self.solved:
# generate a new game
while True:
self.shuffle()
self.target = deepcopy(self.board) # we make a deep copy of board into the target
self.shuffle() # then we shuffle the board
if self.issolved() == False:
break
self.solved = False
# is solved method. We check if board == target
def issolved(self):
for i in range(self.level):
for j in range(self.level):
if self.board[i][j] != self.target[i][j]:
return False
self.solved = True
return True
# Now we need to write the code for the GUI
class FlippingBitsGUI:
def __init__(self, root, level):
self.game = FlippingBitsGame(level)
self.root = root
self.root.title("Flipping Bits Game - SSaurel")
self.root.geometry("700x800")
self.canvas = tk.Canvas(self.root, width = 700, height = 800)
self.canvas.pack()
self.drawboard() # method to define letting us to draw the board for the user
def drawboard(self):
# we clean the canvas
self.canvas.delete("all")
squaresize = 500 / self.game.level
targetsize = squaresize / 10
for i in range(self.game.level):
x = 100 + i * squaresize
for j in range(self.game.level):
y = 100 + j * squaresize
value = self.game.board[i][j]
self.canvas.create_rectangle(x, y, x + squaresize, y + squaresize, fill = ("blue", "yellow")[value == 0])
# draw the target on the top left
target = self.game.target[i][j]
self.canvas.create_rectangle(x + 10, y + 10, x + 10 + targetsize, y + 10 + targetsize, fill = ("blue", "yellow")[target == 0])
if self.game.issolved():
self.canvas.create_text(200, 750, text = "Solved. Click to start a new game", font = ("Helvetica", "20", "bold"))
def onclick(self, event):
if self.game.solved:
self.game.newgame()
self.drawboard()
return
# we get coordinates of the user's click
idx = int(event.x)
idy = int(event.y)
# check if you must flip a column or a row
if (idx > 0 and idx < 100 and idy > 100 and idy < 600) or (idx > 600 and idx < 700 and idy > 100 and idy < 600):
# we need to flip a row
squaresize = 500 / self.game.level
row = int((idy - 100) / squaresize)
self.game.fliprow(row)
elif (idy > 0 and idy < 100 and idx > 100 and idx < 600) or (idy > 600 and idy < 800 and idx > 100 and idx < 600):
# we need to flip a col
squaresize = 500 / self.game.level
col = int((idx - 100) / squaresize)
self.game.flipcol(col)
self.drawboard()
root = tk.Tk()
gui = FlippingBitsGUI(root, 6) # we will use a 5x5 board
gui.canvas.bind("<Button-1>", gui.onclick)
root.mainloop()
# Time to put our game in action :P
# Watch the tutorial on YouTube => https://www.youtube.com/watch?v=mPZOLy9wui0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment