当前位置: 首页 > news >正文

Python语言自动玩游戏的消消乐游戏程序代码3QZQ

import pygame
import sys
import random
import time
import math
from pygame.locals import *

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 700
GRID_SIZE = 8
CELL_SIZE = 60
MARGIN = 50
FPS = 60

# 颜色定义
BACKGROUND = (40, 44, 52)
GRID_BACKGROUND = (30, 34, 42)
GRID_LINE = (56, 60, 74)
COLORS = [
(241, 76, 76), # 红色
(76, 173, 241), # 蓝色
(76, 241, 157), # 绿色
(241, 214, 76), # 黄色
(185, 76, 241), # 紫色
(241, 147, 76) # 橙色
]
TEXT_COLOR = (220, 220, 220)
HIGHLIGHT = (255, 255, 255, 100)
MATCH_HIGHLIGHT = (255, 255, 255, 150)

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Match-3 游戏(按 A 切换AI模式,R 重置)")
clock = pygame.time.Clock()

# 字体 - 使用系统默认字体,确保兼容性
try:
# 尝试加载中文字体
font = pygame.font.SysFont("simhei,microsoftyahei,arial", 24)
small_font = pygame.font.SysFont("simhei,microsoftyahei,arial", 20)
except:
# 如果失败则使用默认字体
font = pygame.font.Font(None, 36)
small_font = pygame.font.Font(None, 24)


class Animation:
def __init__(self):
self.animations = []

def add_swap(self, cell1, cell2, duration=0.3):
i1, j1 = cell1
i2, j2 = cell2

# 计算屏幕坐标
x1 = MARGIN + j1 * CELL_SIZE + CELL_SIZE // 2
y1 = MARGIN + i1 * CELL_SIZE + CELL_SIZE // 2
x2 = MARGIN + j2 * CELL_SIZE + CELL_SIZE // 2
y2 = MARGIN + i2 * CELL_SIZE + CELL_SIZE // 2

self.animations.append({
'type': 'swap',
'cells': [cell1, cell2],
'start_pos': [(x1, y1), (x2, y2)],
'end_pos': [(x2, y2), (x1, y1)],
'progress': 0,
'duration': duration,
'start_time': time.time()
})

def add_fall(self, from_cell, to_cell, duration=0.4):
i1, j1 = from_cell
i2, j2 = to_cell

# 计算屏幕坐标
x1 = MARGIN + j1 * CELL_SIZE + CELL_SIZE // 2
y1 = MARGIN + i1 * CELL_SIZE + CELL_SIZE // 2
x2 = MARGIN + j2 * CELL_SIZE + CELL_SIZE // 2
y2 = MARGIN + i2 * CELL_SIZE + CELL_SIZE // 2

self.animations.append({
'type': 'fall',
'cell': to_cell, # 最终位置
'from_pos': (x1, y1),
'to_pos': (x2, y2),
'progress': 0,
'duration': duration,
'start_time': time.time()
})

def add_match_highlight(self, cells, duration=0.5):
screen_cells = []
for cell in cells:
i, j = cell
x = MARGIN + j * CELL_SIZE + CELL_SIZE // 2
y = MARGIN + i * CELL_SIZE + CELL_SIZE // 2
screen_cells.append((x, y, CELL_SIZE // 2 - 5))

self.animations.append({
'type': 'match',
'cells': screen_cells,
'progress': 0,
'duration': duration,
'start_time': time.time(),
'alpha': 255
})

def add_new_gem(self, cell, duration=0.3):
i, j = cell
x = MARGIN + j * CELL_SIZE + CELL_SIZE // 2
y = MARGIN - CELL_SIZE // 2 # 从上方开始

final_y = MARGIN + i * CELL_SIZE + CELL_SIZE // 2

self.animations.append({
'type': 'new_gem',
'cell': cell,
'start_pos': (x, y),
'end_pos': (x, final_y),
'progress': 0,
'duration': duration,
'start_time': time.time()
})

def update(self):
current_time = time.time()
completed_animations = []

for i, anim in enumerate(self.animations):
elapsed = current_time - anim['start_time']
anim['progress'] = min(elapsed / anim['duration'], 1.0)

# 特殊处理匹配高亮动画
if anim['type'] == 'match':
# 脉冲效果
anim['alpha'] = int(128 + 127 * math.sin(anim['progress'] * math.pi * 4))

if anim['progress'] >= 1.0:
completed_animations.append(i)

# 移除完成的动画(从后往前避免索引问题)
for i in reversed(completed_animations):
self.animations.pop(i)

return len(self.animations) > 0

def draw(self, grid):
for anim in self.animations:
if anim['type'] == 'swap':
# 使用缓动函数使动画更自然
progress = self.ease_in_out(anim['progress'])

for idx, cell in enumerate(anim['cells']):
start_x, start_y = anim['start_pos'][idx]
end_x, end_y = anim['end_pos'][idx]

x = start_x + (end_x - start_x) * progress
y = start_y + (end_y - start_y) * progress

color_idx = grid[cell[0]][cell[1]]
radius = CELL_SIZE // 2 - 5

# 绘制移动中的宝石
pygame.draw.circle(screen, COLORS[color_idx], (int(x), int(y)), radius)
pygame.draw.circle(screen, HIGHLIGHT, (int(x - radius // 3), int(y - radius // 3)), radius // 2)

elif anim['type'] == 'fall':
progress = self.ease_out(anim['progress'])

start_x, start_y = anim['from_pos']
end_x, end_y = anim['to_pos']

x = start_x + (end_x - start_x) * progress
y = start_y + (end_y - start_y) * progress

color_idx = grid[anim['cell'][0]][anim['cell'][1]]
radius = CELL_SIZE // 2 - 5

pygame.draw.circle(screen, COLORS[color_idx], (int(x), int(y)), radius)
pygame.draw.circle(screen, HIGHLIGHT, (int(x - radius // 3), int(y - radius // 3)), radius // 2)

elif anim['type'] == 'match':
for x, y, radius in anim['cells']:
# 绘制高亮环
highlight_surface = pygame.Surface((radius * 2, radius * 2), pygame.SRCALPHA)
pygame.draw.circle(highlight_surface, (*MATCH_HIGHLIGHT[:3], anim['alpha']),
(radius, radius), radius, 4)
screen.blit(highlight_surface, (x - radius, y - radius))

elif anim['type'] == 'new_gem':
progress = self.ease_out(anim['progress'])

start_x, start_y = anim['start_pos']
end_x, end_y = anim['end_pos']

x = start_x + (end_x - start_x) * progress
y = start_y + (end_y - start_y) * progress

color_idx = grid[anim['cell'][0]][anim['cell'][1]]
radius = CELL_SIZE // 2 - 5

pygame.draw.circle(screen, COLORS[color_idx], (int(x), int(y)), radius)
pygame.draw.circle(screen, HIGHLIGHT, (int(x - radius // 3), int(y - radius // 3)), radius // 2)

def ease_in_out(self, t):
return 0.5 * (1 - math.cos(t * math.pi))

def ease_out(self, t):
return 1 - (1 - t) * (1 - t)


class Game:
def __init__(self):
self.grid = []
self.selected = None
self.score = 0
self.ai_mode = False
self.ai_thinking = False
self.animations = Animation()
self.state = "playing" # playing, animating, game_over
self.initialize_grid()

def initialize_grid(self):
# 创建初始网格
self.grid = []
for i in range(GRID_SIZE):
row = []
for j in range(GRID_SIZE):
row.append(random.randint(0, len(COLORS) - 1))
self.grid.append(row)

# 确保初始网格没有可消除的组合
while self.find_matches():
self.remove_matches()
self.fill_grid()

def draw(self):
# 绘制背景
screen.fill(BACKGROUND)

# 绘制网格背景
grid_rect = pygame.Rect(
MARGIN, MARGIN,
GRID_SIZE * CELL_SIZE,
GRID_SIZE * CELL_SIZE
)
pygame.draw.rect(screen, GRID_BACKGROUND, grid_rect)

# 绘制网格线
for i in range(GRID_SIZE + 1):
# 垂直线
pygame.draw.line(
screen, GRID_LINE,
(MARGIN + i * CELL_SIZE, MARGIN),
(MARGIN + i * CELL_SIZE, MARGIN + GRID_SIZE * CELL_SIZE),
2
)
# 水平线
pygame.draw.line(
screen, GRID_LINE,
(MARGIN, MARGIN + i * CELL_SIZE),
(MARGIN + GRID_SIZE * CELL_SIZE, MARGIN + i * CELL_SIZE),
2
)

# 绘制静态宝石(不在动画中的)
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
color_idx = self.grid[i][j]
if color_idx >= 0: # 确保是有效颜色索引
# 检查这个宝石是否在动画中
in_animation = False
for anim in self.animations.animations:
if anim['type'] in ['swap', 'fall', 'new_gem']:
if 'cell' in anim and anim['cell'] == (i, j):
in_animation = True
break
elif 'cells' in anim and (i, j) in anim['cells']:
in_animation = True
break

if not in_animation:
x = MARGIN + j * CELL_SIZE + CELL_SIZE // 2
y = MARGIN + i * CELL_SIZE + CELL_SIZE // 2
radius = CELL_SIZE // 2 - 5

# 绘制宝石主体
pygame.draw.circle(screen, COLORS[color_idx], (x, y), radius)

# 绘制高光效果
highlight_radius = radius // 2
pygame.draw.circle(screen, HIGHLIGHT, (x - radius // 3, y - radius // 3), highlight_radius)

# 绘制动画
self.animations.draw(self.grid)

# 绘制选中的宝石
if self.selected and self.state == "playing":
i, j = self.selected
rect = pygame.Rect(
MARGIN + j * CELL_SIZE + 2,
MARGIN + i * CELL_SIZE + 2,
CELL_SIZE - 4,
CELL_SIZE - 4
)
pygame.draw.rect(screen, HIGHLIGHT, rect, 4)

# 绘制分数
score_text = font.render(f"分数: {self.score}", True, TEXT_COLOR)
screen.blit(score_text, (SCREEN_WIDTH - 250, 20))

# 绘制模式指示器
mode_text = font.render(
"模式: AI自动" if self.ai_mode else "模式: 手动",
True, TEXT_COLOR
)
screen.blit(mode_text, (SCREEN_WIDTH - 250, 60))

# 绘制提示
hints = [
"按 A 切换AI模式",
"按 R 重置游戏",
"手动模式下点击宝石进行交换"
]

for i, hint in enumerate(hints):
hint_text = small_font.render(hint, True, TEXT_COLOR)
screen.blit(hint_text, (SCREEN_WIDTH - 350, SCREEN_HEIGHT - 120 + i * 25))

# 如果AI正在思考,显示提示
if self.ai_thinking:
thinking_text = font.render("AI正在思考...", True, TEXT_COLOR)
screen.blit(thinking_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT - 40))

# 如果正在播放动画,显示状态
if self.state == "animating":
anim_text = small_font.render("动画播放中...", True, TEXT_COLOR)
screen.blit(anim_text, (SCREEN_WIDTH // 2 - 60, 20))

def get_cell_at_pos(self, pos):
x, y = pos
# 检查是否在网格内
if (x < MARGIN or y < MARGIN or
x >= MARGIN + GRID_SIZE * CELL_SIZE or
y >= MARGIN + GRID_SIZE * CELL_SIZE):
return None

# 计算网格索引
j = (x - MARGIN) // CELL_SIZE
i = (y - MARGIN) // CELL_SIZE

return (i, j)

def select(self, cell):
if not cell or self.state != "playing":
self.selected = None
return

i, j = cell

if not self.selected:
self.selected = (i, j)
else:
# 检查是否相邻
si, sj = self.selected
if ((abs(i - si) == 1 and j == sj) or
(abs(j - sj) == 1 and i == si)):
# 添加交换动画
self.animations.add_swap(self.selected, (i, j))
self.state = "animating"

# 交换宝石(实际交换会在动画完成后进行)
self.swap((si, sj), (i, j))

# 检查是否有匹配
matches = self.find_matches()
if matches:
# 添加匹配高亮动画
match_cells = []
for match in matches:
i1, j1, i2, j2 = match
if i1 == i2: # 水平匹配
for j in range(j1, j2 + 1):
match_cells.append((i1, j))
else: # 垂直匹配
for i in range(i1, i2 + 1):
match_cells.append((i, j1))
self.animations.add_match_highlight(match_cells)
else:
# 如果没有匹配,稍后交换回来
pass

self.selected = None
else:
# 选择新的宝石
self.selected = (i, j)

def swap(self, cell1, cell2):
i1, j1 = cell1
i2, j2 = cell2
self.grid[i1][j1], self.grid[i2][j2] = self.grid[i2][j2], self.grid[i1][j1]

def find_matches(self):
matches = []

# 检查水平匹配
for i in range(GRID_SIZE):
for j in range(GRID_SIZE - 2):
if (self.grid[i][j] == self.grid[i][j + 1] == self.grid[i][j + 2] and
self.grid[i][j] != -1):
# 找到匹配,扩展到所有连续相同宝石
k = j + 3
while k < GRID_SIZE and self.grid[i][k] == self.grid[i][j]:
k += 1
matches.append((i, j, i, k - 1)) # 水平匹配

# 检查垂直匹配
for i in range(GRID_SIZE - 2):
for j in range(GRID_SIZE):
if (self.grid[i][j] == self.grid[i + 1][j] == self.grid[i + 2][j] and
self.grid[i][j] != -1):
# 找到匹配,扩展到所有连续相同宝石
k = i + 3
while k < GRID_SIZE and self.grid[k][j] == self.grid[i][j]:
k += 1
matches.append((i, j, k - 1, j)) # 垂直匹配

return matches

def remove_matches(self):
matches = self.find_matches()
if not matches:
return False

# 标记要移除的宝石
to_remove = [[False for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)]

for match in matches:
i1, j1, i2, j2 = match

# 水平匹配
if i1 == i2:
for j in range(j1, j2 + 1):
to_remove[i1][j] = True
# 垂直匹配
elif j1 == j2:
for i in range(i1, i2 + 1):
to_remove[i][j1] = True

# 移除标记的宝石并增加分数
removed_count = 0
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
if to_remove[i][j]:
self.grid[i][j] = -1
removed_count += 1

# 每移除一个宝石得10分
self.score += removed_count * 10

return True

def fill_grid(self):
# 宝石下落
falling_gems = []
for j in range(GRID_SIZE):
# 从底部向上移动宝石
empty_spaces = 0
for i in range(GRID_SIZE - 1, -1, -1):
if self.grid[i][j] == -1:
empty_spaces += 1
elif empty_spaces > 0:
# 记录下落动画
falling_gems.append(((i, j), (i + empty_spaces, j)))
self.grid[i + empty_spaces][j] = self.grid[i][j]
self.grid[i][j] = -1

# 添加下落动画
for from_cell, to_cell in falling_gems:
self.animations.add_fall(from_cell, to_cell)

# 填充顶部空位
new_gems = []
for j in range(GRID_SIZE):
for i in range(GRID_SIZE):
if self.grid[i][j] == -1:
self.grid[i][j] = random.randint(0, len(COLORS) - 1)
new_gems.append((i, j))

# 添加新宝石动画
for cell in new_gems:
self.animations.add_new_gem(cell)

# 检查是否有新的匹配
if self.find_matches():
# 添加匹配高亮动画
matches = self.find_matches()
match_cells = []
for match in matches:
i1, j1, i2, j2 = match
if i1 == i2: # 水平匹配
for j in range(j1, j2 + 1):
match_cells.append((i1, j))
else: # 垂直匹配
for i in range(i1, i2 + 1):
match_cells.append((i, j1))
self.animations.add_match_highlight(match_cells)

def find_best_move(self):
"""AI: 寻找最佳移动"""
best_score = 0
best_move = None

# 检查所有可能的交换
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
# 检查右侧交换
if j < GRID_SIZE - 1:
# 尝试交换
self.swap((i, j), (i, j + 1))

# 评估这个交换
matches = self.find_matches()
if matches:
# 计算这个交换的得分潜力
score_potential = 0
for match in matches:
i1, j1, i2, j2 = match
if i1 == i2: # 水平匹配
score_potential += (j2 - j1 + 1) * 10
else: # 垂直匹配
score_potential += (i2 - i1 + 1) * 10

# 如果这个交换更好,更新最佳移动
if score_potential > best_score:
best_score = score_potential
best_move = ((i, j), (i, j + 1))

# 交换回来
self.swap((i, j), (i, j + 1))

# 检查下方交换
if i < GRID_SIZE - 1:
# 尝试交换
self.swap((i, j), (i + 1, j))

# 评估这个交换
matches = self.find_matches()
if matches:
# 计算这个交换的得分潜力
score_potential = 0
for match in matches:
i1, j1, i2, j2 = match
if i1 == i2: # 水平匹配
score_potential += (j2 - j1 + 1) * 10
else: # 垂直匹配
score_potential += (i2 - i1 + 1) * 10

# 如果这个交换更好,更新最佳移动
if score_potential > best_score:
best_score = score_potential
best_move = ((i, j), (i + 1, j))

# 交换回来
self.swap((i, j), (i + 1, j))

return best_move

def ai_play(self):
"""AI: 执行一步移动"""
if self.ai_thinking or self.state != "playing":
return

self.ai_thinking = True

# 寻找最佳移动
move = self.find_best_move()

if move:
# 添加交换动画
self.animations.add_swap(move[0], move[1])
self.state = "animating"

# 执行移动
self.swap(move[0], move[1])

# 检查是否有匹配
matches = self.find_matches()
if matches:
# 添加匹配高亮动画
match_cells = []
for match in matches:
i1, j1, i2, j2 = match
if i1 == i2: # 水平匹配
for j in range(j1, j2 + 1):
match_cells.append((i1, j))
else: # 垂直匹配
for i in range(i1, i2 + 1):
match_cells.append((i, j1))
self.animations.add_match_highlight(match_cells)

self.ai_thinking = False

def update(self):
# 更新动画
has_animations = self.animations.update()

if has_animations:
self.state = "animating"
else:
if self.state == "animating":
# 动画结束,检查是否需要进一步处理
self.state = "playing"

# 检查是否有匹配需要消除
if self.remove_matches():
self.fill_grid()
self.state = "animating" # 继续播放填充动画
else:
# 检查交换后是否有匹配,如果没有匹配则交换回来
if not self.find_matches():
# 查找最近的一次交换
for anim in reversed(self.animations.animations):
if anim['type'] == 'swap' and anim['progress'] >= 1.0:
# 交换回来
self.swap(anim['cells'][0], anim['cells'][1])
break


def main():
game = Game()
last_ai_move_time = 0
ai_move_delay = 2.0 # AI每次移动的延迟(秒)

# 游戏主循环
while True:
current_time = time.time()

# 处理事件
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()

elif event.type == KEYDOWN:
if event.key == K_a:
# 切换AI模式
game.ai_mode = not game.ai_mode
game.selected = None
elif event.key == K_r:
# 重置游戏
game = Game()

elif event.type == MOUSEBUTTONDOWN and not game.ai_mode and game.state == "playing":
# 手动模式下的鼠标点击
if event.button == 1: # 左键
cell = game.get_cell_at_pos(event.pos)
game.select(cell)

# 更新游戏状态
game.update()

# AI模式下的自动移动
if (game.ai_mode and
current_time - last_ai_move_time > ai_move_delay and
game.state == "playing" and
not game.ai_thinking):
game.ai_play()
last_ai_move_time = current_time

# 绘制游戏
game.draw()

# 更新显示
pygame.display.flip()
clock.tick(FPS)


if __name__ == "__main__":
main()

http://www.hskmm.com/?act=detail&tid=23096

相关文章:

  • Python语言自动玩游戏的数字拼图游戏程序代码ZXQMQZQ
  • 如何找出集合的两个子集使得和相等?
  • Python语言自动玩游戏的俄罗斯方块游戏程序代码QZQ
  • Spring AI(七)Spring AI 的RAG搭建集合火山向量模型+阿里云Tair(企业版)
  • Python语言自动玩游戏的数字拼图游戏程序代码QZQ
  • 赛前训练4 字符串哈希
  • 英语
  • 处处吻
  • ThreadLocal原理与使用详解
  • WinCC监控框架实战解析:打通物联网网关的关键步骤
  • 2025国庆Day1
  • 2025 年包装印刷厂家 TOP 企业品牌推荐排行榜,西安,陕西,咸阳包装印刷,礼盒,定制,设计,优质,品质,环保,生产包装印刷公司推荐!
  • 2025 绝对式编码器厂家 TOP 企业品牌推荐排行榜,增量绝对式编码器,多圈绝对式编码器,二进制绝对式编码器 /ssi 绝对式编码器,拉线绝对式编码器公司推荐!
  • 2025 编码器厂家 TOP 企业品牌推荐排行榜,无磁,光学,脉冲,绝对型,伺服,机械多圈,工业,二进制,拉线编码器公司推荐
  • 2025 年玻璃钢水箱厂家 TOP 企业品牌推荐排行榜,30 吨,订做,消防,专业,方形,拼装式,屋顶,大型玻璃钢水箱推荐这十家公司!
  • 禁止DataGridView自动根据数据源的结构生成列
  • 2025 年压球机厂家 TOP 企业品牌推荐排行榜,新型,高压,节能,双螺旋干粉,对辊,煤粉,超低压压球机公司推荐!
  • 2025 年磨粉机厂家 TOP 企业品牌推荐排行榜,新型磨粉机,超细磨粉机,立式双动力磨粉机,节能磨粉机公司推荐!
  • 2025 年等离子清洗机厂家 TOP 企业品牌推荐排行榜,大气,真空,宽幅,微波,自动化,常压,低温,大腔体,射频,DBD,介质阻挡放电等离子清洗机公司推荐!
  • 完整教程:如何优雅的布局,height: 100% 的使用和 flex-grow: 1 的 min-height 陷阱
  • MyBatis缓存架构深度拆解:从PerpetualCache的LRU陷阱到Redis分布式二级缓存防穿透实战 - 详解
  • 2025柔版印刷机厂家 TOP 企业品牌推荐排行榜,塑编袋,编织袋,阀口袋,重包膜,机组式,卫星式,不换版,FFS 重载膜,水泥袋柔版印刷机公司推荐!
  • 9 30 -
  • Spring 基础核心 - SpringMVC 入门与请求流程
  • (数据结构)链表OJ——刷题练习 - 实践
  • 阿尔法开发板移植ov5640时候一个小的注意事项
  • 使用kraken2 命令对重测序数据进行物种分类
  • 2025/10/2
  • 重测序数据fastp数据质控及fastQC质量评估
  • 8. Spring AI tools/function-call - 教程