Question: This program plays the classic tile matching game. The object of the game is to find all the matching tiles by turning over two tiles

This program plays the classic tile matching game. The object of the game is to find all the matching tiles by turning over two tiles at a time. If the colors match, the tiles are removed. If not, then the tiles are replaced and two more tiles are turned over. The game is over once all the matching colors have been found.
This implementation of the game allows the player to select the number of rows and columns of tiles. Unfortunately, this sometimes causes problems. The game currently runs without issue for the default number of rows and columns, however if the player chooses an odd number of rows and an odd number of columns, the game will crash.
Your task is to identify the cause of the crash and modify the game to both:
1. Prevent the game from crashing regardless of what values for rows and columns are entered (you may assume that both values will always be greater than 0)
2. Allow the game to be played successfully regardless of what values for rows and columns are selected.
The number of rows and columns may be selected by starting the game and selecting File -> Options
import time
from tkinter import *
from random import randint
class ButtonWrapper:
def __init__(self, id="", row=-1, col=-1, c=""):
self.ID = id
self.ROW = row
self.COL = col
self.COLOR = c
self.BUTTON_OBJ = None
def check_match():
global buttons
clicked =[]
for b in buttons.values():
if b.BUTTON_OBJ['relief']== "sunken":
clicked.append(b)
if len(clicked)>=2:
if clicked[0].BUTTON_OBJ['bg']== clicked[1].BUTTON_OBJ['bg']:
clicked[0].BUTTON_OBJ.configure(fg='black', bg='black', relief='raised')
clicked[1].BUTTON_OBJ.configure(fg='black', bg='black', relief='raised')
else:
clicked[0].BUTTON_OBJ.configure(fg='SystemButtonFace', bg='SystemButtonFace', relief='raised')
clicked[1].BUTTON_OBJ.configure(fg='SystemButtonFace', bg='SystemButtonFace', relief='raised')
def button_pushed(pushed_id):
global buttons
buttons[pushed_id].BUTTON_OBJ.configure(bg=buttons[pushed_id].COLOR, relief="sunken")
buttons[pushed_id].BUTTON_OBJ.after(1500, check_match)
def close_options(top):
top.destroy()
def save_options(r, c):
global rows, cols
rows = r
cols = c
reset_game()
def options():
top = Toplevel(root)
top.geometry("250x250")
row_val = StringVar()
col_val = StringVar()
row = Entry(top, width=25, textvariable=row_val)
row.pack()
col = Entry(top, width=25, textvariable=col_val)
col.pack()
save = Button(top, text="Save", command=lambda: save_options(int(row_val.get()), int(col_val.get())))
close = Button(top, text="Close", command=lambda: close_options(top))
save.pack(pady=5, side=TOP)
close.pack(pady=5, side=TOP)
def reset_game():
global buttons
for b in buttons.values():
b.BUTTON_OBJ.destroy()
buttons ={} # Clear the button dictionary
for i in range(rows):
for j in range(cols):
id =(i * cols)+ j # Calculate the button id
b = ButtonWrapper(id=str(id), row=i, col=j) # Create the button meta data object
b.BUTTON_OBJ = Button(root, text="", command=lambda bid=b.ID: button_pushed(bid), height=3, width=7)
buttons[b.ID]= b # Save the button meta data object in the dictionary
ids = list(range(rows * cols)) # Make a list of all button IDs
while len(ids)>0: # While there are still IDs in the list
a = ids[randint(0, len(ids)-1)] # Pick a random button ID
ids.remove(a) # Remove it from the list
b = ids[randint(0, len(ids)-1)] # Pick a second random button ID
ids.remove(b) # Remove it from the list as well
color = colors[randint(0, len(colors)-1)] # Pick a random color
buttons[str(a)].COLOR = color # Set both buttons to the same color
buttons[str(b)].COLOR = color
for b in buttons.values():
b.BUTTON_OBJ.configure(fg='SystemButtonFace', bg='SystemButtonFace', relief='raised')
b.BUTTON_OBJ.configure(fg='SystemButtonFace', bg='SystemButtonFace', relief='raised')
f in buttons.values():
b.BUTTON_OBJ.grid(row=b.ROW, column=b.COL)
rows =5
cols =6
buttons ={}
root = Tk()
menubar = Menu(root) # Creating Menubar
colors =['red', 'green', 'blue', 'cyan', 'yellow', 'magenta']
file = Menu(menubar, tearoff=0)
menubar.add_cascade(label='File', menu=file)
file.add_command(label='New Game', command=reset_game)
file.add_command(label='Options', command=options)
file.add_separator()
file.add_command(label='Exit', command=root.destroy)
reset_game()
root.grid_rowconfigure(0, minsize=40)
root.config(menu=menubar)
root.mainloop()

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!