You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Pygame的Mastermind游戏:网格功能异常及索引越界问题排查

Fixing the IndexError in Your Pygame Mastermind Game

Let's break down why you're hitting that IndexError and fix it, plus clean up some messy parts of your code to get grid clicks and text input working as expected.

Why the IndexError Happens

Your blocks list is initialized to hold array_width * array_height = 4 * 8 = 32 elements (indices 0 to 31). But right now:

  1. When you click anywhere on the screen, you calculate row and column without checking if those values are within your grid's bounds (rows 0-3, columns 0-7).
  2. If you click outside the 4x8 grid (like the text box area), row or column will be larger than 3 or 7, making row * array_height + column exceed 31—hence the out-of-range error.
  3. You're also looping through all grid cells for every click, which means you're updating the blocks list multiple times for a single click, leading to unexpected behavior.

Step-by-Step Fixes

1. Merge Duplicate Event Handlers

You have two separate if event.type == pygame.MOUSEBUTTONDOWN blocks—merge them into one to avoid conflicts and redundant code.

2. Add Bounds Checking for Grid Clicks

Before updating blocks, verify that the clicked row and column are within your grid's valid range:

if 0 <= row < array_width and 0 <= column < array_height:
    # Only update blocks if click is inside the grid

3. Remove Redundant Loops

You don't need to loop through all grid cells to find which one was clicked—calculate the position once, check bounds, then update the corresponding block.

4. Clean Up Text Input Logic

Merge your duplicate KEYDOWN handlers into one to handle backspace, regular input, and enter submission in a single place.

5. Simplify Grid Initialization

Your grid was initialized as 10x10 but you only use 4x8—adjust it to match your actual grid size to avoid confusion.

Optimized Code

Here's the revised code with all these fixes applied:

import pygame

# Color definitions
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

# Grid dimensions
WIDTH = 20
HEIGHT = 20
MARGIN = 5
array_width = 4  # Number of rows in our grid
array_height = 8  # Number of columns in our grid

# Initialize grid and state arrays
grid = [[0 for _ in range(array_height)] for _ in range(array_width)]
colors = [(0, 0, 0) for _ in range(array_width * array_height)]
blocks = [False for _ in range(array_width * array_height)]

# Pygame setup
pygame.init()
WINDOW_SIZE = [300, 300]
screen = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Mastermind (WIP)")
clock = pygame.time.Clock()

# Text input setup
base_font = pygame.font.Font(None, 32)
user_text = ""
input_rect = pygame.Rect(10, 250, 100, 50)
color_active = pygame.Color('lightskyblue3')
color_passive = pygame.Color('gray15')
color = color_passive
active = False

done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        
        # Handle mouse clicks (grid + text box)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            pos = pygame.mouse.get_pos()
            
            # Check if click is on the text input box
            if input_rect.collidepoint(event.pos):
                active = True
            else:
                active = False
                # Calculate grid coordinates only if not clicking the text box
                column = pos[0] // (WIDTH + MARGIN)
                row = pos[1] // (HEIGHT + MARGIN)
                
                # Only update blocks if within grid bounds
                if 0 <= row < array_width and 0 <= column < array_height:
                    block_index = row * array_height + column
                    blocks[block_index] = not blocks[block_index]
                    print(f"Click {pos} -> Grid coordinates: ({row}, {column})")
                    print(f"Block {block_index} toggled to {blocks[block_index]}")
        
        # Handle keyboard input for text box
        elif event.type == pygame.KEYDOWN:
            if active:
                if event.key == pygame.K_BACKSPACE:
                    user_text = user_text[:-1]
                elif event.key == pygame.K_RETURN:
                    print(f"Submitted text: {user_text}")
                    # Add logic here to process the guess (e.g., change grid colors)
                    if user_text == "green":
                        for r in range(array_width):
                            for c in range(array_height):
                                if blocks[r * array_height + c]:
                                    colors[r * array_height + c] = GREEN
                    elif user_text == "blue":
                        for r in range(array_width):
                            for c in range(array_height):
                                if blocks[r * array_height + c]:
                                    colors[r * array_height + c] = BLUE
                    user_text = ""  # Clear input after submission
                else:
                    user_text += event.unicode

    # Update text box color based on active state
    color = color_active if active else color_passive

    # Draw everything
    screen.fill(BLACK)  # Clear screen first
    
    # Draw grid
    for row in range(array_width):
        for column in range(array_height):
            block_index = row * array_height + column
            pygame.draw.rect(
                screen,
                colors[block_index],
                [(MARGIN + WIDTH) * column + MARGIN,
                 (MARGIN + HEIGHT) * row + MARGIN,
                 WIDTH, HEIGHT]
            )
    
    # Draw text input box
    pygame.draw.rect(screen, color, input_rect, 2)
    text_surface = base_font.render(user_text, True, WHITE)
    screen.blit(text_surface, (input_rect.x + 5, input_rect.y + 5))

    clock.tick(60)
    pygame.display.flip()

pygame.quit()

Key Improvements in This Code:

  • No more IndexError because we check if clicks are within the grid bounds before updating blocks
  • Merged duplicate event handlers for cleaner, more maintainable logic
  • Added text submission logic (press Enter to apply color to toggled blocks)
  • Simplified grid initialization to match your actual 4x8 grid
  • Clearer variable names and debug prints to help with testing

Now when you click grid cells, they'll toggle their state without errors, and typing a color name (like "green" or "blue") and pressing Enter will apply that color to all toggled blocks.

内容的提问来源于stack exchange,提问作者Luke Williams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 04:47:49