Python语言自动玩游戏的连连看游戏程序代码QZQ
import pygame
import sys
import random
import time
import math
from collections import deque
# 初始化pygame
pygame.init()
# 设置中文字体
try:
font = pygame.font.Font("simhei.ttf", 18) # 尝试使用系统自带黑体
title_font = pygame.font.Font("simhei.ttf", 24)
except:
font = pygame.font.SysFont("microsoftyahei", 18) # 备用字体
title_font = pygame.font.SysFont("microsoftyahei", 24)
# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
GRID_SIZE = 40
GRID_WIDTH = 10
GRID_HEIGHT = 8
MARGIN_X = (SCREEN_WIDTH - GRID_WIDTH * GRID_SIZE) // 2
MARGIN_Y = (SCREEN_HEIGHT - GRID_HEIGHT * GRID_SIZE) // 2 + 50
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 120, 255)
YELLOW = (255, 255, 0)
PURPLE = (180, 0, 255)
ORANGE = (255, 165, 0)
CYAN = (0, 255, 255)
LIGHT_BLUE = (173, 216, 230)
COLORS = [RED, GREEN, BLUE, YELLOW, PURPLE, ORANGE, CYAN]
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("连连看游戏(带AI功能)")
class LightningEffect:
"""消除闪电效果类"""
def __init__(self, start_pos, end_pos):
self.start_pos = start_pos
self.end_pos = end_pos
self.particles = []
self.create_lightning()
self.lifetime = 0.5 # 效果持续时间(秒)
self.created_time = time.time()
def create_lightning(self):
"""创建闪电效果的点"""
x1, y1 = self.start_pos
x2, y2 = self.end_pos
# 计算两点之间的距离
distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
segments = max(5, int(distance / 10))
# 生成主要路径点
points = [(x1, y1)]
for i in range(1, segments):
t = i / segments
x = x1 + (x2 - x1) * t
y = y1 + (y2 - y1) * t
# 添加一些随机偏移模拟闪电效果
if i < segments - 1:
offset_range = 10
x += random.uniform(-offset_range, offset_range)
y += random.uniform(-offset_range, offset_range)
points.append((x, y))
points.append((x2, y2))
# 创建粒子效果
for i in range(len(points) - 1):
px1, py1 = points[i]
px2, py2 = points[i + 1]
# 在主路径上添加小粒子
segment_length = math.sqrt((px2 - px1) ** 2 + (py2 - py1) ** 2)
num_particles = max(2, int(segment_length / 5))
for j in range(num_particles):
t = j / num_particles
px = px1 + (px2 - px1) * t
py = py1 + (py2 - py1) * t
# 粒子属性
self.particles.append({
'pos': [px, py],
'size': random.randint(2, 5),
'color': random.choice([BLUE, CYAN, LIGHT_BLUE, WHITE]),
'life': random.uniform(0.2, 0.5)
})
def update(self):
"""更新闪电效果"""
current_time = time.time()
elapsed = current_time - self.created_time
# 更新粒子生命周期
for particle in self.particles:
particle['life'] -= 0.02
# 移除死亡的粒子
self.particles = [p for p in self.particles if p['life'] > 0]
return elapsed < self.lifetime and len(self.particles) > 0
def draw(self, surface):
"""绘制闪电效果"""
# 绘制连接线
if len(self.particles) > 1:
points = []
for particle in self.particles:
if particle['life'] > 0:
points.append(particle['pos'])
if len(points) > 1:
pygame.draw.lines(surface, LIGHT_BLUE, False, points, 2)
# 绘制粒子
for particle in self.particles:
if particle['life'] > 0:
alpha = int(255 * (particle['life'] / 0.5))
color = particle['color']
size = particle['size']
# 创建临时surface实现透明度效果
particle_surface = pygame.Surface((size * 2, size * 2), pygame.SRCALPHA)
pygame.draw.circle(particle_surface, (*color, alpha), (size, size), size)
surface.blit(particle_surface, (particle['pos'][0] - size, particle['pos'][1] - size))
class LianLianKan:
def __init__(self):
self.reset_game()
def reset_game(self):
# 创建游戏板
self.board = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
# 生成成对的图标
icons = []
for i in range(GRID_WIDTH * GRID_HEIGHT // 2):
color = random.choice(COLORS)
icons.extend([color, color])
# 随机打乱图标
random.shuffle(icons)
# 将图标分配到游戏板
for i in range(GRID_HEIGHT):
for j in range(GRID_WIDTH):
self.board[i][j] = icons[i * GRID_WIDTH + j]
# 游戏状态
self.selected = None
self.score = 0
self.moves = 0
self.ai_playing = False
self.ai_speed = 0.5 # AI移动速度(秒)
self.last_ai_move = 0
self.game_over = False
self.lightning_effects = [] # 存储闪电效果
def draw(self):
screen.fill(WHITE)
# 绘制标题
title = title_font.render("连连看游戏", True, BLUE)
screen.blit(title, (SCREEN_WIDTH // 2 - title.get_width() // 2, 10))
# 绘制游戏板
for i in range(GRID_HEIGHT):
for j in range(GRID_WIDTH):
x = MARGIN_X + j * GRID_SIZE
y = MARGIN_Y + i * GRID_SIZE
if self.board[i][j] != 0:
# 绘制方块
pygame.draw.rect(screen, self.board[i][j], (x, y, GRID_SIZE, GRID_SIZE))
pygame.draw.rect(screen, BLACK, (x, y, GRID_SIZE, GRID_SIZE), 2)
# 如果被选中,绘制高亮边框
if self.selected == (i, j):
pygame.draw.rect(screen, YELLOW, (x - 3, y - 3, GRID_SIZE + 6, GRID_SIZE + 6), 3)
# 绘制闪电效果
for effect in self.lightning_effects:
effect.draw(screen)
# 绘制分数和移动次数
score_text = font.render(f"分数: {self.score}", True, BLACK)
moves_text = font.render(f"移动次数: {self.moves}", True, BLACK)
screen.blit(score_text, (20, 20))
screen.blit(moves_text, (20, 60))
# 绘制按钮
pygame.draw.rect(screen, GREEN, (SCREEN_WIDTH - 150, 20, 130, 40))
reset_text = font.render("重新开始", True, WHITE)
screen.blit(reset_text, (SCREEN_WIDTH - 140, 25))
# AI按钮
ai_color = RED if self.ai_playing else BLUE
pygame.draw.rect(screen, ai_color, (SCREEN_WIDTH - 150, 70, 130, 40))
ai_text = font.render("AI自动玩", True, WHITE)
screen.blit(ai_text, (SCREEN_WIDTH - 140, 75))
# 游戏结束提示
if self.game_over:
game_over_text = title_font.render("游戏结束!", True, RED)
screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT - 50))
# 绘制说明
instructions = [
"游戏规则: 点击两个相同的方块,如果可以用不超过两个拐角的线连接,则消除",
"操作说明: 鼠标点击选择方块,按R重新开始,按A切换AI自动游戏"
]
for i, text in enumerate(instructions):
instr = font.render(text, True, BLACK)
screen.blit(instr, (SCREEN_WIDTH // 2 - instr.get_width() // 2, SCREEN_HEIGHT - 100 - i * 30))
def get_grid_pos(self, pos):
x, y = pos
if MARGIN_X <= x < MARGIN_X + GRID_WIDTH * GRID_SIZE and MARGIN_Y <= y < MARGIN_Y + GRID_HEIGHT * GRID_SIZE:
row = (y - MARGIN_Y) // GRID_SIZE
col = (x - MARGIN_X) // GRID_SIZE
return row, col
return None
def can_connect(self, pos1, pos2):
"""检查两个位置是否可以连接(最多两个拐角)"""
if self.board[pos1[0]][pos1[1]] != self.board[pos2[0]][pos2[1]]:
return False
# 检查直接连接(0个拐角)
if self.check_direct_connection(pos1, pos2):
return True
# 检查一个拐角连接
if self.check_one_corner_connection(pos1, pos2):
return True
# 检查两个拐角连接
if self.check_two_corners_connection(pos1, pos2):
return True
return False
def check_direct_connection(self, pos1, pos2):
"""检查直接连接(水平或垂直)"""
r1, c1 = pos1
r2, c2 = pos2
# 在同一行
if r1 == r2:
start, end = min(c1, c2), max(c1, c2)
for c in range(start + 1, end):
if self.board[r1][c] != 0:
return False
return True
# 在同一列
if c1 == c2:
start, end = min(r1, r2), max(r1, r2)
for r in range(start + 1, end):
if self.board[r][c1] != 0:
return False
return True
return False
def check_one_corner_connection(self, pos1, pos2):
"""检查一个拐角连接"""
r1, c1 = pos1
r2, c2 = pos2
# 尝试两个可能的拐角点
corner1 = (r1, c2)
corner2 = (r2, c1)
# 检查拐角点1
if self.board[corner1[0]][corner1[1]] == 0:
if self.check_direct_connection(pos1, corner1) and self.check_direct_connection(corner1, pos2):
return True
# 检查拐角点2
if self.board[corner2[0]][corner2[1]] == 0:
if self.check_direct_connection(pos1, corner2) and self.check_direct_connection(corner2, pos2):
return True
return False
def check_two_corners_connection(self, pos1, pos2):
"""检查两个拐角连接"""
r1, c1 = pos1
r2, c2 = pos2
# 检查所有可能的两个拐角路径
# 水平-垂直-水平路径
for c in range(GRID_WIDTH):
if c == c1 or c == c2:
continue
corner1 = (r1, c)
corner2 = (r2, c)
if self.board[corner1[0]][corner1[1]] == 0 and self.board[corner2[0]][corner2[1]] == 0:
if (self.check_direct_connection(pos1, corner1) and
self.check_direct_connection(corner1, corner2) and
self.check_direct_connection(corner2, pos2)):
return True
# 垂直-水平-垂直路径
for r in range(GRID_HEIGHT):
if r == r1 or r == r2:
continue
corner1 = (r, c1)
corner2 = (r, c2)
if self.board[corner1[0]][corner1[1]] == 0 and self.board[corner2[0]][corner2[1]] == 0:
if (self.check_direct_connection(pos1, corner1) and
self.check_direct_connection(corner1, corner2) and
self.check_direct_connection(corner2, pos2)):
return True
return False
def remove_pair(self, pos1, pos2):
"""移除一对匹配的方块,并添加闪电效果"""
# 添加闪电效果
x1 = MARGIN_X + pos1[1] * GRID_SIZE + GRID_SIZE // 2
y1 = MARGIN_Y + pos1[0] * GRID_SIZE + GRID_SIZE // 2
x2 = MARGIN_X + pos2[1] * GRID_SIZE + GRID_SIZE // 2
y2 = MARGIN_Y + pos2[0] * GRID_SIZE + GRID_SIZE // 2
self.lightning_effects.append(LightningEffect((x1, y1), (x2, y2)))
# 移除方块
self.board[pos1[0]][pos1[1]] = 0
self.board[pos2[0]][pos2[1]] = 0
self.score += 10
self.moves += 1
# 检查游戏是否结束
if all(cell == 0 for row in self.board for cell in row):
self.game_over = True
def find_all_matches(self):
"""查找所有可能的匹配对"""
matches = []
positions = []
# 收集所有非空位置
for i in range(GRID_HEIGHT):
for j in range(GRID_WIDTH):
if self.board[i][j] != 0:
positions.append((i, j))
# 检查所有可能的配对
for i in range(len(positions)):
for j in range(i + 1, len(positions)):
if self.can_connect(positions[i], positions[j]):
matches.append((positions[i], positions[j]))
return matches
def ai_play(self):
"""AI自动玩游戏"""
current_time = time.time()
if current_time - self.last_ai_move < self.ai_speed:
return
self.last_ai_move = current_time
# 查找所有可能的匹配
matches = self.find_all_matches()
if matches:
# 随机选择一个匹配
pos1, pos2 = random.choice(matches)
# 模拟选择第一个方块
self.selected = pos1
# 绘制更新
self.draw()
pygame.display.flip()
pygame.time.delay(int(self.ai_speed * 500))
# 模拟选择第二个方块并消除
if self.can_connect(pos1, pos2):
self.remove_pair(pos1, pos2)
self.selected = None
else:
# 没有找到匹配,游戏可能无法继续
self.ai_playing = False
def handle_click(self, pos):
"""处理鼠标点击"""
if self.game_over:
return
grid_pos = self.get_grid_pos(pos)
if grid_pos is None:
# 检查是否点击了按钮
x, y = pos
if SCREEN_WIDTH - 150 <= x <= SCREEN_WIDTH - 20:
if 20 <= y <= 60: # 重新开始按钮
self.reset_game()
elif 70 <= y <= 110: # AI按钮
self.ai_playing = not self.ai_playing
return
row, col = grid_pos
# 如果点击的位置是空的,忽略
if self.board[row][col] == 0:
return
# 如果没有选中的方块,选中当前方块
if self.selected is None:
self.selected = (row, col)
else:
# 如果点击了已选中的方块,取消选择
if self.selected == (row, col):
self.selected = None
else:
# 尝试连接两个方块
if self.can_connect(self.selected, (row, col)):
self.remove_pair(self.selected, (row, col))
self.selected = None
# 创建游戏实例
game = LianLianKan()
# 游戏主循环
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # 左键点击
game.handle_click(event.pos)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r: # 按R重新开始
game.reset_game()
elif event.key == pygame.K_a: # 按A切换AI模式
game.ai_playing = not game.ai_playing
# 更新闪电效果
game.lightning_effects = [effect for effect in game.lightning_effects if effect.update()]
# AI自动玩游戏
if game.ai_playing and not game.game_over:
game.ai_play()
# 绘制游戏
game.draw()
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()