Python语言自动玩游戏的数字拼图游戏程序代码QZQ

import sys
import random
import pygame

# 初始化pygame
pygame.init()

# 游戏常量
SIZE = 3 # 3x3 拼图
CELL = 120 # 每个格子的像素大小
WIDTH = CELL * SIZE
HEIGHT = CELL * SIZE
EMPTY = SIZE * SIZE # 空格的表示值
ANIMATION_SPEED = 8 # 动画速度(降低速度让移动更明显)
ANIMATION_FRAMES = 15 # 固定动画帧数

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
LIGHT_GRAY = (230, 230, 230)

# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT + 60))
pygame.display.set_caption("数字拼图(修复版)")


# 设置字体
def get_font(size):
"""获取合适的字体"""
try:
return pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial"], size)
except:
return pygame.font.SysFont(None, size)


# 字体对象
font = get_font(72)
small_font = get_font(28)


class Animation:
"""处理方块移动动画 - 采用帧计数方式更稳定"""

def __init__(self, start_pos, end_pos, value):
self.start_pos = start_pos # (x, y)
self.end_pos = end_pos # (x, y)
self.current_pos = list(start_pos)
self.value = value
self.frame = 0 # 当前动画帧
self.complete = False

# 计算每帧的移动距离
self.dx = (end_pos[0] - start_pos[0]) / ANIMATION_FRAMES
self.dy = (end_pos[1] - start_pos[1]) / ANIMATION_FRAMES

def update(self):
"""更新动画位置"""
if self.complete:
return

self.frame += 1
# 计算当前位置
self.current_pos[0] = self.start_pos[0] + self.dx * self.frame
self.current_pos[1] = self.start_pos[1] + self.dy * self.frame

# 检查动画是否完成
if self.frame >= ANIMATION_FRAMES:
self.current_pos = list(self.end_pos)
self.complete = True


def create_board():
"""创建打乱的拼图,确保可解"""
board = list(range(1, SIZE * SIZE)) + [EMPTY]
while True:
random.shuffle(board)
if is_solvable(board):
break
return board


def is_solvable(board):
"""判断拼图是否可解"""
inversions = 0
for i in range(len(board)):
for j in range(i + 1, len(board)):
if board[i] != EMPTY and board[j] != EMPTY and board[i] > board[j]:
inversions += 1

if SIZE % 2 == 1:
return inversions % 2 == 0
else:
empty_row = SIZE - (board.index(EMPTY) // SIZE)
return (empty_row % 2 == 0) == (inversions % 2 == 1)


def draw_board(board, animations, is_ai_mode):
"""绘制游戏界面,包括动画"""
screen.fill(WHITE)

# 绘制模式信息和操作提示
mode_text = "AI自动模式" if is_ai_mode else "人工模式"
mode_surf = small_font.render(f"模式: {mode_text} (F1切换)", True, BLACK)
hint_surf = small_font.render("方向键移动空格(人工模式)", True, BLUE)
screen.blit(mode_surf, (10, 10))
screen.blit(hint_surf, (10, 35))

# 绘制格子背景
for i in range(SIZE):
for j in range(SIZE):
rect = pygame.Rect(j * CELL, i * CELL + 60, CELL, CELL)
pygame.draw.rect(screen, LIGHT_GRAY, rect)
pygame.draw.rect(screen, GRAY, rect, 2)

# 收集正在动画的数字,避免重复绘制
animating_values = [anim.value for anim in animations]

# 绘制静态方块(不在动画中的)
for i in range(SIZE):
for j in range(SIZE):
val = board[i * SIZE + j]
if val != EMPTY and val not in animating_values:
x = j * CELL + CELL // 2
y = i * CELL + 60 + CELL // 2
text_surf = font.render(str(val), True, BLACK)
text_rect = text_surf.get_rect(center=(x, y))
screen.blit(text_surf, text_rect)

# 绘制动画中的方块
for anim in animations:
if not anim.complete:
x, y = anim.current_pos
text_surf = font.render(str(anim.value), True, BLACK)
text_rect = text_surf.get_rect(center=(int(x), int(y)))
screen.blit(text_surf, text_rect)

pygame.display.flip()


def move_with_animation(board, direction):
"""移动空格并创建动画"""
idx = board.index(EMPTY)
row, col = idx // SIZE, idx % SIZE
animations = []

# 计算移动后的位置和动画 - 使用格子左上角坐标计算中心位置
if direction == 'UP' and row < SIZE - 1:
# 空格向上移动(数字向下移动)
num_idx = idx + SIZE
num_val = board[num_idx]

# 计算起始和结束位置(中心坐标)
start_x = col * CELL + CELL // 2
start_y = (row + 1) * CELL + 60 + CELL // 2
end_x = col * CELL + CELL // 2
end_y = row * CELL + 60 + CELL // 2

animations.append(Animation((start_x, start_y), (end_x, end_y), num_val))
board[idx], board[num_idx] = board[num_idx], board[idx]

elif direction == 'DOWN' and row > 0:
# 空格向下移动(数字向上移动)
num_idx = idx - SIZE
num_val = board[num_idx]

start_x = col * CELL + CELL // 2
start_y = (row - 1) * CELL + 60 + CELL // 2
end_x = col * CELL + CELL // 2
end_y = row * CELL + 60 + CELL // 2

animations.append(Animation((start_x, start_y), (end_x, end_y), num_val))
board[idx], board[num_idx] = board[num_idx], board[idx]

elif direction == 'LEFT' and col < SIZE - 1:
# 空格向左移动(数字向右移动)
num_idx = idx + 1
num_val = board[num_idx]

start_x = (col + 1) * CELL + CELL // 2
start_y = row * CELL + 60 + CELL // 2
end_x = col * CELL + CELL // 2
end_y = row * CELL + 60 + CELL // 2

animations.append(Animation((start_x, start_y), (end_x, end_y), num_val))
board[idx], board[num_idx] = board[num_idx], board[idx]

elif direction == 'RIGHT' and col > 0:
# 空格向右移动(数字向左移动)
num_idx = idx - 1
num_val = board[num_idx]

start_x = (col - 1) * CELL + CELL // 2
start_y = row * CELL + 60 + CELL // 2
end_x = col * CELL + CELL // 2
end_y = row * CELL + 60 + CELL // 2

animations.append(Animation((start_x, start_y), (end_x, end_y), num_val))
board[idx], board[num_idx] = board[num_idx], board[idx]

return animations


def is_win(board):
"""判断是否完成拼图"""
for i in range(SIZE * SIZE - 1):
if board[i] != i + 1:
return False
return True


# AI求解部分
def find_empty(board):
"""找到空格的位置"""
return board.index(EMPTY)


def heuristic(board, goal):
"""启发式函数:计算曼哈顿距离"""
distance = 0
for i in range(SIZE * SIZE):
if board[i] != EMPTY and board[i] != goal[i]:
val = board[i]
goal_idx = goal.index(val)
r1, c1 = i // SIZE, i % SIZE
r2, c2 = goal_idx // SIZE, goal_idx % SIZE
distance += abs(r1 - r2) + abs(c1 - c2)
return distance


def get_neighbors(board):
"""获取所有可能的下一步状态"""
neighbors = []
idx = find_empty(board)
row, col = idx // SIZE, idx % SIZE

# 上移
if row < SIZE - 1:
new_board = board[:]
new_board[idx], new_board[idx + SIZE] = new_board[idx + SIZE], new_board[idx]
neighbors.append(('UP', new_board))
# 下移
if row > 0:
new_board = board[:]
new_board[idx], new_board[idx - SIZE] = new_board[idx - SIZE], new_board[idx]
neighbors.append(('DOWN', new_board))
# 左移
if col < SIZE - 1:
new_board = board[:]
new_board[idx], new_board[idx + 1] = new_board[idx + 1], new_board[idx]
neighbors.append(('LEFT', new_board))
# 右移
if col > 0:
new_board = board[:]
new_board[idx], new_board[idx - 1] = new_board[idx - 1], new_board[idx]
neighbors.append(('RIGHT', new_board))

return neighbors


def a_star_solve(board):
"""使用A*算法求解拼图,返回移动方向序列"""
goal = list(range(1, SIZE * SIZE)) + [EMPTY]
if board == goal:
return []

open_set = [board]
came_from = {}
direction_from = {} # 记录到达该状态的移动方向
g_score = {tuple(board): 0}
f_score = {tuple(board): heuristic(board, goal)}

while open_set:
current = min(open_set, key=lambda x: f_score[tuple(x)])

if current == goal:
# 重建路径
path = []
while tuple(current) in came_from:
path.append(direction_from[tuple(current)])
current = came_from[tuple(current)]
return path[::-1] # 反转路径

open_set.remove(current)

for direction, neighbor in get_neighbors(current):
tentative_g = g_score[tuple(current)] + 1

if tuple(neighbor) not in g_score or tentative_g < g_score[tuple(neighbor)]:
came_from[tuple(neighbor)] = current
direction_from[tuple(neighbor)] = direction
g_score[tuple(neighbor)] = tentative_g
f_score[tuple(neighbor)] = tentative_g + heuristic(neighbor, goal)

if neighbor not in open_set:
open_set.append(neighbor)

return None


def main():
"""游戏主函数"""
board = create_board()
goal = list(range(1, SIZE * SIZE)) + [EMPTY]
is_ai_mode = False # 初始为人工模式
ai_moves = [] # AI的移动方向序列
current_animations = [] # 当前的动画列表
clock = pygame.time.Clock()

while True:
clock.tick(60) # 60 FPS

# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
# 按F1切换模式
if event.key == pygame.K_F1:
is_ai_mode = not is_ai_mode
if is_ai_mode:
# 计算AI移动序列
ai_moves = a_star_solve(board)
elif not is_ai_mode and not current_animations:
# 人工模式且没有动画时才能移动
if event.key == pygame.K_UP:
anims = move_with_animation(board, 'UP')
current_animations.extend(anims)
elif event.key == pygame.K_DOWN:
anims = move_with_animation(board, 'DOWN')
current_animations.extend(anims)
elif event.key == pygame.K_LEFT:
anims = move_with_animation(board, 'LEFT')
current_animations.extend(anims)
elif event.key == pygame.K_RIGHT:
anims = move_with_animation(board, 'RIGHT')
current_animations.extend(anims)

# AI模式且没有动画且有移动步骤时自动移动
if is_ai_mode and not current_animations and ai_moves:
direction = ai_moves.pop(0)
anims = move_with_animation(board, direction)
current_animations.extend(anims)

# 更新动画
for anim in current_animations[:]:
anim.update()
if anim.complete:
current_animations.remove(anim)

# 绘制游戏界面
draw_board(board, current_animations, is_ai_mode)

# 检查是否胜利且没有动画
if not current_animations and board == goal:
win_font = get_font(48)
win_surf = win_font.render("恭喜完成!", True, RED)
screen.blit(win_surf, (WIDTH // 2 - win_surf.get_width() // 2,
HEIGHT // 2 - win_surf.get_height() // 2 + 30))
pygame.display.flip()
pygame.time.wait(2000) # 显示2秒
# 重新开始游戏
board = create_board()
ai_moves = []
current_animations = []


if __name__ == "__main__":
main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/925228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

温州网站开发培训北京网站制作外包

http://blog.csdn.net/dandelion_gong/article/details/51673085 Unix下可用的I/O模型一共有五种&#xff1a;阻塞I/O 、非阻塞I/O 、I/O复用 、信号驱动I/O 、异步I/O。此处我们主要介绍第三种I/O符复用。 I/O复用的功能&#xff1a;如果一个或多个I/O条件满足&#xff08;输…

看动漫什么网站好企业网站的分类有哪三种

目录&#xff1a;系统学习 Java IO---- 目录&#xff0c;概览 PipedInputStream 类使得可以作为字节流读取管道的内容。 管道是同一 JVM 内的线程之间的通信通道。 使用两个已连接的管道流时&#xff0c;要为每个流操作创建一个线程&#xff0c; read() 和 write() 都是阻塞方法…

浙江自己如何做网站鹰潭手机网站建设

xin3721网络学院为广大学员&#xff0c;准备了丰富了教学视频。为了更好的让大学配合视频进行学习&#xff0c;拓展学员的知识面&#xff0c;我站特整理了大量的&#xff0c;技术文章&#xff0c;供学员参考。因此本教案需配合视频教程学习&#xff0c;视频教程地址为&#xff…

赛前训练4 字符串哈希

A 显然长度具有单调性,于是二分长度+map存储哈希值判断即可。实现 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <…

wordpress企业网站建设智慧农业项目方案

EventBus是android 下高效的发布/订阅事件总线机制&#xff0c;可以代替传统的Intent&#xff0c;Handler&#xff0c;BroadCast 或者Fragment&#xff0c;Activity&#xff0c;Service&#xff0c;线程之间传递数据&#xff0c;是一种发布订阅设计模式&#xff08;观察者模式&…

上海著名的网站制作公司杭州网站商场开发

美术教案第三课:曲曲直直(三年级美术下册教案)教学目标:认知目标:能够认识生活中的各种曲线和直线,说说曲线、直线给自己的感受.能力目标:能够用绘画、剪贴等方法表现曲线和直线的画面,培养学生自主探究的能力和创造能力.情感目标:通过收集不同直线、曲线材料进行创作,培养学生…

处处吻

你爱热吻却永不爱人 练习为乐但是怕熟人 你爱路过去索取见闻 陌路人变得必有份好感 你热爱别离 再合再离 似花瓣献技 叫花粉遍地 噢噢 你在播弄这穿线游戏 跟他结束 他与她再一起 你小心 一吻便颠倒众生 一吻便救一个人…

ThreadLocal原理与使用详解

ThreadLocal原理与使用详解 一、ThreadLocal 介绍 1.1 定义与核心特性定义:Java 官方文档描述,ThreadLocal 类用于提供线程内部的局部变量,多线程环境下通过 get() 和 set() 方法访问时,能保证各线程变量相对独立于…

WinCC监控框架实战解析:打通物联网网关的关键步骤

WinCC监控框架实战解析:打通物联网网关的关键步骤pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

2025国庆Day1

模拟赛 T1 对h离散化,枚举x,分类讨论某些位置淹没后段的个数的变化情况即可 可恶的毒瘤出题人竟然造了一个高度全0的hack 注意特判此时答案为0 #include<iostream> #include<cstdio> #include<cstdli…

网站内部链接有什么作用wordpress极慢

1005 K 次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数组&#xff1a; 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后&#xff0c;返回数组 可能…

2025 年包装印刷厂家 TOP 企业品牌推荐排行榜,西安,陕西,咸阳包装印刷,礼盒,定制,设计,优质,品质,环保,生产包装印刷公司推荐!

引言在当前包装印刷行业发展进程中,企业面临着诸多亟待解决的问题。一方面,部分企业设备陈旧,难以满足市场对高精度、高质量包装印刷产品的需求,色彩还原度不足、套印偏差等问题频发,影响产品外观质感与品牌形象;…

python-dotenv正则表达式应用:麻烦变量名的匹配技巧

python-dotenv正则表达式应用:麻烦变量名的匹配技巧2025-10-02 18:54 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; dis…

2025 编码器厂家 TOP 企业品牌推荐排行榜,无磁,光学,脉冲,绝对型,伺服,机械多圈,工业,二进制,拉线编码器公司推荐

引言在当前工业自动化快速发展的背景下,编码器作为高精度闭环控制系统中位置和速度反馈的关键传感器,其市场需求日益增长。然而,行业内却面临着诸多问题,不同厂家的产品质量参差不齐,部分厂家缺乏核心技术创新能力…

2025 年玻璃钢水箱厂家 TOP 企业品牌推荐排行榜,30 吨,订做,消防,专业,方形,拼装式,屋顶,大型玻璃钢水箱推荐这十家公司!

引言随着建筑、化工、食品、医药等行业的快速发展,市场对玻璃钢水箱的需求持续攀升,但行业发展过程中也面临诸多问题。部分生产厂家技术储备不足,生产的产品质量稳定性差,无法满足不同行业对水箱设备的严苛要求;有…

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频语义理解与智能检索进阶 - 实践

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频语义理解与智能检索进阶 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !import…

Spark专题-第三部分:性能监控与实战优化(1)-认识spark ui - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

禁止DataGridView自动根据数据源的结构生成列

代码展示: this.dgv_SysAdmin.AutoGenerateColumns = false;