How can I simplify my game to avoid it from taking larger memory as the running time increases?

问题遇到的现象和发生背景

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?

问题相关代码,请勿粘贴截图
### The game is based on the flipping number game
### 

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 tile
    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()

if __name__ == '__main__':
    # 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

运行结果及报错内容
我的解答思路和尝试过的方法
我想要达到的结果

The problem is adding too many click events

img

img

img

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 tile
    x = -200
    y = -200
 
    for i in range(len(optionColor)):
        tile = prototypeForOptions[i]
        tile.goto(i * width + x, -(height+50) + y)
        tile.color('white', optionColor[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 = prototypeForScreens[row][column]
            square.goto(column * (5+width) + x , row * (5+height) + y)
            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()

prototypeForOptions = []
prototypeForScreens = []
for i in range(len(optionColor)):
    tile = prototype.clone()
    tile.onclick(partial(returnChosenColor, i),add=False)
    prototypeForOptions.append(tile)
for column in range(5):
    prototypeForScreen = []
    for row in range(5):
        square = prototype.clone()
        square.onclick(partial(userChosenTile, column, row),add=False)
        prototypeForScreen.append(square)
    prototypeForScreens.append(prototypeForScreen)
 
if __name__ == '__main__':
    # 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