如何用Tkinter显示二维数组?迷宫游戏开发的数组访问难题
Hey there! I see you're building a maze game with Tkinter, and you're stuck on laying out your maze components and accessing that 2D array. Let's work through this together.
First, Fix the Hidden Image Bug (You’ll Hit This Soon!)
Before diving into layout and array access, there’s a critical issue in your current code: your PhotoImage objects are getting garbage collected. Since icon is a local variable in your visblock() and invisblock() functions, once the function finishes running, Tkinter drops the reference to the image, and it won’t show up in the window. Fix this by attaching the image directly to the widget:
def visblock(): icon = PhotoImage(file="Player_Icon.png") block = tkinter.Label(window, image=icon) block.icon = icon # Keep a reference to the image to avoid garbage collection return block # These act like walls def invisblock(): icon = PhotoImage(file="Player_Icon_Cover.png") block = tkinter.Button(window, image=icon) block.icon = icon # Same fix for empty space buttons return block # These act like empty spaces
Laying Out Your Maze Components
Right now, you’re creating all your Label/Button widgets but never telling Tkinter where to place them. For a grid-based maze, the grid() method is perfect—it maps directly to your 2D array’s rows and columns. Add this loop right after defining your maze array to position every widget:
# Loop through each row and column to place widgets in the window for row_idx, row in enumerate(maze): for col_idx, widget in enumerate(row): widget.grid(row=row_idx, column=col_idx)
This will align each widget exactly where it sits in your array—row 0, column 0 is the top-left corner, row 4, column 3 is the bottom-right, etc.
Accessing Your 2D Maze Array
Great news—you already have full access to your maze array! The maze variable stores all your widget objects, so you can grab any cell using row and column indices. For example:
- Get the widget at the top-left corner:
maze[0][0] - Check if a cell is a wall (Label) or empty space (Button):
isinstance(maze[1][1], tkinter.Button) - Modify a widget later (like changing a wall to an empty space):
# Example: Convert a wall to an empty space new_icon = PhotoImage(file="Player_Icon_Cover.png") maze[0][1].config(image=new_icon) maze[0][1].icon = new_icon # Don't forget the image reference!
Quick Start for Click-to-Move Functionality
For your click-to-move feature, you can bind a click event to your empty space buttons. Here’s a simple example to get you started:
First, add a variable to track the player’s starting position:
player_pos = [1, 1] # [row, column] – starts at the first empty space in row 1
Then update your invisblock() function to handle clicks:
def invisblock(): icon = PhotoImage(file="Player_Icon_Cover.png") def on_click(event): # Get the position of the clicked button clicked_row = event.widget.grid_info()["row"] clicked_col = event.widget.grid_info()["column"] # Check if the clicked cell is adjacent to the player (basic movement rule) if (abs(clicked_row - player_pos[0]) == 1 and clicked_col == player_pos[1]) or \ (abs(clicked_col - player_pos[1]) == 1 and clicked_row == player_pos[0]): # Swap images to simulate player movement (replace with a dedicated player image later) old_player_cell = maze[player_pos[0]][player_pos[1]] new_player_cell = maze[clicked_row][clicked_col] old_icon = old_player_cell.icon new_icon = new_player_cell.icon old_player_cell.config(image=new_icon) old_player_cell.icon = new_icon new_player_cell.config(image=old_icon) new_player_cell.icon = old_icon # Update the player's position player_pos[0], player_pos[1] = clicked_row, clicked_col block = tkinter.Button(window, image=icon) block.icon = icon block.bind("<Button-1>", on_click) # Bind left-click to the movement function return block
This is a basic setup—you can expand it later to prevent moving into walls, add a dedicated player image, or track score.
内容的提问来源于stack exchange,提问作者Paul Brown

