This is a color-flipping game based on the python turtle module. The game is composed of a rectangular board divided into a number of flat colored tiles of various colors. The goal of the game is to turn all tiles to the same color by choosing one tile on the board and then changing its color to another color. The newly selected color will spread to all its neighboring tiles which match the original color of the chosen tile. The player continues selecting another tile and changing its color to another until all the tiles within the board flipped to the same color. In addition to the rectangular board, an array of colors is shown below the board. These are the colors to which the player can choose to flip the color of the selected tile.
As I started to run my game, the memory it took up was getting larger and larger as the running time increased. And it's getting slower and slower. I think it might be due to the while loop at the end of my code. But I'm not sure. How can I modify it to make it faster?
from turtle import *
from random import choice
from functools import partial
# set game dimension to be 5 x 5
g_dim = 5
# use random.choice() to create the color for the game
g_game = [choice(['#0000FF', '#FF0000', '#FFFF00', '#008000', '#00FFFF']) for i in range(25)]
# provide the option to flip during the game
optionColor = ['#0000FF', '#FF0000', '#FFFF00', '#008000', '#00FFFF']
# show a set of colors as option for user to flip
def promptColorToFlip(optionColor, # a list that contains a set of the color for user to choose from
height=100, # the height of the option tiles
width=100 # the width of the option tiles
):
# the coordinates of the first tiles
x = -200
y = -200
for i in range(len(optionColor)):
tile = prototype.clone()
tile.goto(i * width x, -(height 50) y)
tile.color('white', optionColor[i])
tile.onclick(partial(returnChosenColor, i))
# return the index of the select-to-flip-to color in the optionColor list
def returnChosenColor(userChosenColor, # the index of the select-to-flip-to color in the optionColor list
x, y # take the positional arguments from the onclick() function to avoid errors, no significant meaning
):
global userOption
userOption = userChosenColor
def refreshScreen(game, rows=5, columns=5, height=100, width=100):
x = -200
y = -200
for column in range(columns):
for row in range(rows):
square = prototype.clone()
square.goto(column * (5 width) x , row * (5 height) y)
square.onclick(partial(userChosenTile, row, column))
if state['framed'] == row*5 column:
square.color('black', game[row*5 column])
else:
square.color('white', game[row*5 column])
update()
def userChosenTile(ROW, COL, x, y):
global state, R, C
state['framed'] = ROW*5 COL
R = ROW
C = COL
def flipColor(row, col, game, orig, to):
print('excuted')
global userOption, state, R, C
if orig == to:
return game
if row < 0 or row >= g_dim:
return
if col < 0 or col >= g_dim:
return
idx = row*g_dim col
if game[idx] != orig:
return
print(idx, 'excuted')
game[idx] = to
flipColor(row-1, col, game, orig, to)
flipColor(row 1, col, game, orig, to)
flipColor(row, col-1, game, orig, to)
flipColor(row, col 1, game, orig, to)
state = {'framed':None}
R = None
C = None
userOption = None
return game
# initialize the game status
state = {'framed':None} # stores the number of the last selected tile, which will be framed with a black border
R = None # the row of the last selected tile
C = None # the column of the last selected tile
userOption = None # the index of the select-to-flip-to color in the optionColor list
# create a prototype of the tiles
prototype = Turtle()
prototype.shape('square')
prototype.shapesize(5, 5, 5)
prototype.penup()
# disable auto screen refresh
tracer(False)
# run the game
while True:
# the try and except block here is to prevent error from raising when user terminate the progarm
try:
promptColorToFlip(optionColor)
refreshScreen(g_game)
if state['framed'] is not None and R is not None and C is not None and userOption is not None:
g_game = flipColor(R, C, g_game, g_game[state['framed']], optionColor[userOption])
except:
pass
CodePudding user response:
I haven't fully worked through your somewhat complex code, but I'm pretty sure I see the source of your progressive slowdown as the game runs for a while. It's right here, in your refreshScreen
function:
for column in range(columns):
for row in range(rows):
square = prototype.clone()
...
This code makes a new turtle for each square of your board on every frame. Those turtles never go away, so you just keep on stacking up more and more of them, which slows down the performance of the whole game over time. The solution is probably to use only one turtle for each location, and keep references to them so that you can change their colors when necessary, rather than making them anew each time.