WIN 7 宋体替换法【非一般的方法,可成功替换,并非错误显示为I,II】

本文提供了一种在Windows 7系统中替换宋体字体的方法,包括获取winsxs目录权限、替换simsun.ttc文件及使用系统字体替换工具等内容。

1. 先去winsxs目錄下的这个目录 获得这个目录权限:

C:/Windows/winsxs/x86_microsoft-windows-font-truetype-simsun_31bf3856ad364e35_6.1.7600.16385_none_fadf752dd10266d5

 

2.替换这个目录的simsun.ttc为自己想要替换的字体,比如我一直在用的是   “等宽替换宋体版”请勿下载替换非等宽的,会导致其他问题

http://behindchoice.blogbus.com/logs/34753324.html

下载后得到解压后的simsun.ttc

 

3.替换完成后刪除fonts目錄下的simsun.ttc,最好用的是unlock,官网是

http://ccollomb.free.fr/unlocker/

 

Unlocker 1.8.8 Portable - From this website的下载地址

http://ccollomb.free.fr/unlocker/unlocker1.8.8-portable.zip

安装后直接在文件点击右键->unlock后在弹出对话框中点击删除

 

4.重启后宋体丢失,在管理員 命令行模式 去WINSXS目錄下的相應目錄:
C:/Windows/winsxs/x86_microsoft-windows-font-truetype-simsun_31bf3856ad364e35_6.1.7600.16385_none_fadf752dd10266d5

 

在此目錄下
mklink /h simsun.ttc c:/windows/fonts/simsun.ttc

 

参考

http://bbs.themex.net/showthread.php?t=16856105&page=2

 

 

后来整了半天这样还是不行!!在个别属性页的快捷键上如(o)显示为乱。不知道为何。。

最后在极限的群里找了系统字体替换工具 给替换成功了!若有朋友需要,我可发给他们请给我发右键或者是发私信。

 

 已证实这种替换方法不行,需要使用 win7系统字体替换工具。。。

 

 

附件 win7系统字体替换工具 已经上传:

 

 

 

 

#define UNICODE #define _UNICODE #include <windows.h> #include <math.h> #include <wchar.h> // 宽字符支持 #define WIN_WIDTH 600 #define WIN_HEIGHT 500 #define BALL_RADIUS 10 #define GRAVITY 0.0008 #define REBOUND_FACTOR 0.5 #define GROUND_Y (WIN_HEIGHT - 150) // 地面高度 // 控件 ID #define IDC_HEIGHT_INPUT 201 // 高度输入框 #define IDC_BOUNCES_INPUT 202 // 次数输入框 #define IDC_SUBMIT_BUTTON 203 // 提交按钮 #define TIMER_ID 101 // 定时器 ID // 小球结构体 typedef struct { double x, y; // 小球位置 (像素) double vy; // 垂直速度 double maxHeight; // 当前反弹的最高高度 (像素) int bounces; // 当前反弹次数 int maxBounces; // 最大反弹次数 BOOL isActive; // 小球是否在运动状态 BOOL isFalling; // 小球是否处于下落状态、 double holdTime; // 停留时间(毫秒) } Ball; Ball ball; // 小球全局变量 double totalDistance = 0.0; // 小球累计总运动距离 double reboundHeights[100]; // 每次反弹高度记录 HWND heightInput; // 高度输入框句柄 HWND bouncesInput; // 次数输入框句柄 HWND submitButton; // 提交按钮句柄 HWND mainHwnd; // 主窗口句柄 HWND outputHwnd = NULL; // 结果窗口句柄 int scrollOffset = 0; // 当前滚动条的偏移量 int lineHeight = 20; // 每行内容的高度 int totalOutputHeight = 0; // 全部内容高度 SCROLLINFO scrollInfo; // 滚动条的状态 void InitializeBall(double initialHeightMeters, int maxBounces) { if (initialHeightMeters <= 0 || maxBounces <= 0) { return; // 防止异常参数导致错误初始化 } double initialHeightPixels = initialHeightMeters * 2.0; // 假设 1 米 = 2 像素 ball.x = WIN_WIDTH / 2.0; // 小球水平居中 ball.y = GROUND_Y - initialHeightPixels; // 小球从用户设置的高度开始下落 ball.vy = 0; // 初始速度为 0 ball.maxHeight = initialHeightPixels; // 最大位置为初始输入高度 ball.bounces = 0; // 当前反弹次数设为 0 ball.maxBounces = maxBounces; // 设置最大反弹次数 ball.isActive = TRUE; // 激活运动 ball.isFalling = TRUE; // 初始状态设为下落(不运动) ball.holdTime = 2000.0; // 在初始高度停留 2 秒 totalDistance = 0.0; // 总路程初始化为 0 memset(reboundHeights, 0, sizeof(reboundHeights)); // 清空反弹高度记录 } // 小球的物理逻辑更新 void UpdateBall(DWORD deltaTime) { if (!ball.isActive) return; // 如果小球处于活动状态,直接返回 // 如果当前还有 "停留时间",则不更新下落状态 if (ball.holdTime > 0) { ball.holdTime -= deltaTime; // 减小停留时间 if (ball.holdTime <= 0) { ball.holdTime = 0; // 停留时间结束,开始正常运动 } return; // 返回,不执行后续更新运动逻辑 } if (ball.isFalling) { // 小球下落状态 ball.vy += GRAVITY * deltaTime; // 更新速度(v = v0 + gt) ball.y += ball.vy * deltaTime; // 更新位置(y = y0 + vt) if (ball.y >= GROUND_Y - BALL_RADIUS) { // 碰到底部地面 ball.y = GROUND_Y - BALL_RADIUS; // 确保小球停在地面 ball.isFalling = FALSE; // 切换为上升状态 totalDistance += ball.maxHeight; // 累加下落距离 ball.bounces++; if (ball.bounces <= ball.maxBounces) { // 如果反弹次数未达到上限 reboundHeights[ball.bounces - 1] = ball.maxHeight * REBOUND_FACTOR; // 记录反弹高度 totalDistance += reboundHeights[ball.bounces - 1]; // 累加反弹的上升距离 ball.maxHeight *= REBOUND_FACTOR; // 新的反弹高度是之前高度的一半 ball.vy = -sqrt(2 * GRAVITY * ball.maxHeight); // 更新为反向(向上)的初速度 } if (ball.bounces >= ball.maxBounces) { // 达到最大反弹次数,停止运动 ball.isActive = FALSE; } } } else { // 小球处于上升状态 ball.y += ball.vy * deltaTime; // 更新上升时的位置 ball.vy += GRAVITY * deltaTime; // 受到重力减速(逐渐变慢) if (ball.vy >= 0) { // 当速度大于等于零时(达到了最高点) ball.isFalling = TRUE; // 切换为下落状态 } } } // 绘制小球 void RenderBall(HDC hdc) { HBRUSH hBrush = CreateSolidBrush(RGB(139, 69, 19)); // 棕色小球 HBRUSH oldBrush = SelectObject(hdc, hBrush); Ellipse(hdc, (int)(ball.x - BALL_RADIUS), (int)(ball.y - BALL_RADIUS), (int)(ball.x + BALL_RADIUS), (int)(ball.y + BALL_RADIUS)); SelectObject(hdc, oldBrush); DeleteObject(hBrush); } // 绘制地面 void RenderGround(HDC hdc) { HPEN hPen = CreatePen(PS_SOLID, 2, RGB(0, 128, 0)); // 绿色 HPEN oldPen = SelectObject(hdc, hPen); MoveToEx(hdc, 0, GROUND_Y, NULL); LineTo(hdc, WIN_WIDTH, GROUND_Y); SelectObject(hdc, oldPen); DeleteObject(hPen); } // 渲染整体场景 void RenderScene(HDC hdc) { RenderGround(hdc); // 绘制地面 RenderBall(hdc); // 绘制小球 } LRESULT CALLBACK OutputWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SIZE: { // 在窗口大小调整时,设置滚动条范围 RECT clientRect; GetClientRect(hwnd, &clientRect); // 设置滚动条属性 totalOutputHeight = ball.bounces * lineHeight + 100; // 高度=反弹数量+顶部信息 int windowHeight = clientRect.bottom; scrollInfo.cbSize = sizeof(SCROLLINFO); scrollInfo.fMask = SIF_RANGE | SIF_PAGE; scrollInfo.nMin = 0; // 滚动条最小位置 0 scrollInfo.nMax = totalOutputHeight; // 滚动条最大位置=总高度 scrollInfo.nPage = windowHeight; // 可视区域高度=窗口高度 SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE); break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); wchar_t buffer[256]; int offset = -scrollOffset; // 根据滚动偏移调整绘制位置 HFONT hFont = CreateFontW(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"SimSun"); // 使用宋体 HFONT oldFont = SelectObject(hdc, hFont); // 显示运动结束提示 swprintf(buffer, 256, L"小球运动结束"); TextOutW(hdc, 10, offset + 10, buffer, wcslen(buffer)); offset += lineHeight; // 显示总路程 swprintf(buffer, 256, L"小球总路程:%.2f 米", totalDistance / 2.0); TextOutW(hdc, 10, offset + 10, buffer, wcslen(buffer)); offset += lineHeight; // 显示每次反弹高度 for (int i = 0; i < ball.bounces; i++) { swprintf(buffer, 256, L"第 %d 次反弹高度:%.2f 米", i + 1, reboundHeights[i] / 2.0); TextOutW(hdc, 10, offset + 10, buffer, wcslen(buffer)); offset += lineHeight; } SelectObject(hdc, oldFont); DeleteObject(hFont); EndPaint(hwnd, &ps); break; } case WM_VSCROLL: { // 滚动条消息 int scrollDelta = 0; switch (LOWORD(wParam)) { case SB_LINEDOWN: // 用户点击向下箭头 scrollDelta = lineHeight; break; case SB_LINEUP: // 用户点击向上箭头 scrollDelta = -lineHeight; break; case SB_THUMBPOSITION: // 用户点击滚动条滑块 case SB_THUMBTRACK: // 用户拖动滚动条滑块 scrollDelta = HIWORD(wParam) - scrollOffset; break; } // 更新滚动偏移量 scrollOffset += scrollDelta; if (scrollOffset < 0) scrollOffset = 0; // 限制最小偏移 if (scrollOffset > totalOutputHeight - scrollInfo.nPage) // 限制最大偏移 scrollOffset = totalOutputHeight - scrollInfo.nPage; // 更新滚动条位置 scrollInfo.fMask = SIF_POS; scrollInfo.nPos = scrollOffset; SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE); // 触发窗口重绘 InvalidateRect(hwnd, NULL, TRUE); break; } case WM_DESTROY: outputHwnd = NULL; return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } } void ShowOutputWindow(HINSTANCE hInstance) { if (outputHwnd != NULL) { // 如果结果窗口已经存在 InvalidateRect(outputHwnd, NULL, TRUE); // 强制刷新窗口内容 return; } // 定义结果窗口类名 const wchar_t OUTPUT_CLASS_NAME[] = L"OutputWindow"; WNDCLASSW wc = {0}; wc.lpfnWndProc = OutputWindowProc; // 设置结果窗口过程 wc.hInstance = hInstance; wc.lpszClassName = OUTPUT_CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 注册窗口类 RegisterClassW(&wc); // 创建新结果窗口 outputHwnd = CreateWindowW( OUTPUT_CLASS_NAME, L"运动结果", WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL ); ShowWindow(outputHwnd, SW_SHOW); // 显示结果窗口 } // 主窗口过程函数 LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static DWORD lastTime = 0; switch (uMsg) { case WM_CREATE: // 添加输入控件 CreateWindow(L"STATIC", L"初始高度 (米):", WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 140, 110, 30, hwnd, NULL, NULL, NULL); heightInput = CreateWindow(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 140, 100, 30, hwnd, (HMENU)IDC_HEIGHT_INPUT, NULL, NULL); CreateWindow(L"STATIC", L"落地次数:", WS_VISIBLE | WS_CHILD, 20, WIN_HEIGHT - 100, 110, 30, hwnd, NULL, NULL, NULL); bouncesInput = CreateWindow(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 130, WIN_HEIGHT - 100, 100, 30, hwnd, (HMENU)IDC_BOUNCES_INPUT, NULL, NULL); submitButton = CreateWindow(L"BUTTON", L"提交", WS_VISIBLE | WS_CHILD, 250, WIN_HEIGHT - 120, 100, 40, hwnd, (HMENU)IDC_SUBMIT_BUTTON, NULL, NULL); SetTimer(hwnd, TIMER_ID, 10, NULL); // 设置定时器,每 10ms 刷新 return 0; case WM_COMMAND: if (LOWORD(wParam) == IDC_SUBMIT_BUTTON) { // 提交按钮处理 wchar_t heightBuffer[256], bouncesBuffer[256]; GetWindowText(heightInput, heightBuffer, 256); // 获取输入高度 GetWindowText(bouncesInput, bouncesBuffer, 256); // 获取反弹次数 // 转换用户输入 double height = _wtof(heightBuffer); // 输入高度转换为浮点数 int bounces = _wtoi(bouncesBuffer); // 输入反弹次数转换为整数 // 验证输入合法性 if (height <= 0 || height > 150) { // 限制高度范围为 0 ~ 150 MessageBox(hwnd, L"高度超出范围!请输入 0 到 150 之间的数值。", L"输入无效", MB_ICONERROR); return 0; } if (bounces < 1) { // 限制反弹次数为大于等于 1 的正整数 MessageBox(hwnd, L"落地次数无效!请输入大于等于 1 的正整数。", L"输入无效", MB_ICONERROR); return 0; } // 如果小球当前正在运动,则重置运动 if (ball.isActive) { KillTimer(hwnd, TIMER_ID); // 停止原来的定时器,避免重复更新 } // 初始化小球参数,重新开始模拟 InitializeBall(height, bounces); // 初始化小球参数 SetTimer(hwnd, TIMER_ID, 10, NULL); // 启动定时器,进行物理更新 InvalidateRect(hwnd, NULL, TRUE); // 强制刷新主窗口 } break; case WM_TIMER: if (wParam == TIMER_ID) { // 定时器触发响应 DWORD currentTime = GetTickCount(); // 当前时间戳 DWORD deltaTime = currentTime - lastTime; // 时间差计算 lastTime = currentTime; if (ball.isActive) { // 如果小球处于活动状态 UpdateBall(deltaTime); // 更新物理状态 RECT groundAbove = { 0, 0, WIN_WIDTH, GROUND_Y }; InvalidateRect(hwnd, &groundAbove, TRUE); // 刷新窗口地面以上部分 } else { KillTimer(hwnd, TIMER_ID); // 停止定时器 ShowOutputWindow((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE)); // 显示结果窗口 } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RenderScene(hdc); // 渲染当前场景(包括小球和地面) EndPaint(hwnd, &ps); break; } case WM_DESTROY: KillTimer(hwnd, TIMER_ID); PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const wchar_t CLASS_NAME[] = L"BouncingBallWindow"; WNDCLASS wc = {0}; wc.lpfnWndProc = MainWindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); if (!RegisterClass(&wc)) return 0; mainHwnd = CreateWindow( CLASS_NAME, L"小球反弹模拟", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, WIN_WIDTH, WIN_HEIGHT, NULL, NULL, hInstance, NULL); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }改一下代码规范
08-08
# -*- coding: UTF-8 -*- """ 海龟迷宫闯关游戏 - 完整优化版 """ import turtle # 导入海龟绘图模块 import random # 导入随机数模块 import time # 导入时间模块 game_title = '小海龟大迷宫闯关小游戏' # 游戏名字 level = 1 # 当前关卡,从1开始 '''绘制地图用的全局变量''' txt_path = 'map/map1.txt' # 地图信息文本文件路径及名称 road_color = (191, 217, 225) # 迷宫通道的颜色 R, C = 0, 0 # 迷宫地图的总行数R、总列数C cell_size = 20 # 一个格子的尺寸 area_sign = {} # 记录入口和出口索引位置 mazeList = [] # 地图列表 '''海龟对象''' map_t = turtle.Turtle() # 绘制地图的海龟 map_t.speed(0) # 设置绘图速度最快(地图绘制) sign_t = turtle.Turtle() # 绘制入口和出口标记的海龟 auto_t = turtle.Turtle() # 自动走迷宫的海龟 auto_t.pensize(5) # 画笔粗细(自动) auto_t.speed(0) # 设置绘图速度最快(手动) auto_t.ht() # 隐藏海龟光标 manual_t = turtle.Turtle() # 手动走迷宫的海龟 manual_t.pensize(5) # 画笔粗细(手动) manual_t.speed(0) # 设置绘图速度最快(手动) manual_t.shape('turtle') # 设置海龟光标为小海龟(手动) manual_t.ht() # 隐藏手动走迷宫所用的海龟光标(手动) # 要探索4个方向对应索引的变化规则 direction = [ (1, 0), # 右 (-1, 0), # 左 (0, 1), # 上 (0, -1) # 下 ] # 计时相关变量 start_time = 0 timer_t = turtle.Turtle() # 显示计时器的海龟 def imoveto(ci, ri): """ 功能:根据索引位置移动海龟(不画线) :param ci: 列索引 :param ri: 行索引 :return: """ auto_t.penup() # 抬笔 cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置 auto_t.goto(cx, cy) # 移动到指定位置 auto_t.pendown() # 落笔 auto_t.shape('turtle') # 设置海龟光标的形状 auto_t.color('red') # 设置画笔颜色为红色 auto_t.st() # 显示海龟光标 def c_move_to(t, ctuple): # 移动到指定位置 """ 功能:根据坐标位置移动到指定位置(不画线) :param t: 海龟对象 :param ctuple: 记录坐标位置的元组 :return: """ t.ht() # 隐藏海龟光标 t.penup() # 抬笔 t.goto(ctuple[0], ctuple[1]) # 移动到坐标指定的位置 t.pendown() # 落笔 def itoc(ituple): """ 将索引位置转换为实际坐标位置 :param ituple: 行、列索引组成的元组 :return: 实际坐标位置 """ ci = ituple[0] ri = ituple[1] tx = ci * cell_size - C * cell_size / 2 # 根据索引值计算每个正方形的起点(x坐标) ty = R * cell_size / 2 - ri * cell_size # 根据索引值计算每个正方形的起点(y坐标) cx = tx + cell_size / 2 # 正方形中心的x坐标 cy = ty - cell_size / 2 # 正方形中心的y坐标 return (cx, cy) def ctoi(cx, cy): """ 根据cx和cy求在列表中对应的索引 :param cx: x轴坐标 :param cy: y轴坐标 :return: 元组,(ci,ri) """ ci = ((C - 1) * cell_size / 2 + cx) / cell_size # 计算列索引 ri = ((R - 1) * cell_size / 2 - cy) / cell_size # 计算行索引 return (int(ci), int(ri)) # 返回行列索引的元组 def get_map(filename): """ 功能:读取保存地图的文本文件内容到列表 :param filename: 地图文件名 :return: 地图列表 """ try: with open(filename, 'r', encoding='utf-8') as f: # 打开文件 fl = f.readlines() # 读取全部行 maze_list = [] # 保存地图的列表 for line in fl: # 将读取的内容以空格分割为二维列表 line = line.strip() # 去掉空格 if line: # 确保不是空行 line_list = line.split(" ") # 以空格进行分割为列表 maze_list.append(line_list) # 将分割后的列表添加到地图列表中 return maze_list # 返回地图列表 except FileNotFoundError: print(f"地图文件 {filename} 未找到!") return [] def draw_square(ci, ri, colorsign): """ 功能:绘制组成地图的小正方形 :param ci: 列索引 :param ri: 行索引 :param colorsign: 填充颜色 :return: """ tx = ci * cell_size - C * cell_size / 2 # 根据索引值计算每个正方形的起点(x坐标) ty = R * cell_size / 2 - ri * cell_size # 根据索引值计算每个正方形的起点(y坐标) map_t.penup() # 抬笔 map_t.goto(tx, ty) # 移动到绘图起点(正方形的左上角) if colorsign == '1': # 判断是否为墙(如果为墙,则随机生成填充颜色) r = random.randint(100, 130) # 红色值 g = random.randint(150, 180) # 绿色值 b = random.randint(200, 220) # 蓝色值 map_t.fillcolor(r, g, b) # 指定填充颜色 map_t.pencolor(r//2, g//2, b//2) # 设置边框颜色 else: map_t.fillcolor(colorsign) # 设置为指定的通道颜色 map_t.pencolor(100, 100, 100) # 设置边框颜色 map_t.pendown() # 落笔 map_t.begin_fill() # 填充开始 for i in range(4): # 绘制正方形 map_t.fd(cell_size) map_t.right(90) map_t.end_fill() # 填充结束 def draw_map(mazelist): """ 功能:遍历地图列表绘制迷宫地图 :param mazelist: 保存地图数据的列表 :return: """ turtle.tracer(0) # 隐藏动画效果 global area_sign # 全局变量,记录入口和出口索引位置 map_t.ht() # 隐藏海龟光标 for ri in range(R): # 遍历行 for ci in range(C): # 遍历列 item = mazelist[ri][ci] if item in ['1']: # 判断墙 draw_square(ci, ri, '1') # 绘制墙 elif item == "S": # 判断入口 draw_square(ci, ri, road_color) # 绘制通道 draw_sign(ci, ri, '入口') # 标记入口 area_sign['entry_i'] = (ci, ri) # 保存入口索引 elif item == "E": # 判断出口 draw_square(ci, ri, road_color) # 绘制通道 draw_sign(ci, ri, '出口') # 标记出口 area_sign['exit_i'] = (ci, ri) # 保存出口索引 else: draw_square(ci, ri, road_color) # 绘制通道 turtle.tracer(1) # 显示动画效果 def draw_sign(ci, ri, word): """ 功能:绘制入口和出口标记 :param ci: 列索引 :param ri: 行索引 :param word: 标记文字内容 :return: """ cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置 sign_t.ht() # 隐藏海龟光标 sign_t.penup() # 抬笔 sign_t.goto(cx, cy) # 移动到标记位置 sign_t.color('red') # 设置画笔为红色 sign_t.write(word, align='center', font=('黑体', 12, 'normal')) # 绘制标记文字 def win_tip(): """ 功能:制作过关提示 :return: """ global level, start_time elapsed_time = time.time() - start_time c_move_to(manual_t, (0, 0)) manual_t.color('blue') if level == 3: message = f'\n恭喜您顺利通关!\n总用时: {elapsed_time:.1f}秒\n按Enter键退出游戏' manual_t.write(message, align='center', font=('黑体', 20, 'bold')) turtle.onkey(turtle.bye, 'Return') # 监听按下Enter键退出游戏 else: message = f'\n恭喜过关!用时: {elapsed_time:.1f}秒\n按下Enter进入下一关!' manual_t.write(message, align='center', font=('黑体', 20, 'bold')) level += 1 manual_t.color('red') turtle.onkey(level_init, 'Return') # 监听按下Enter键 def manual_move(d): """ 功能:手动走迷宫时通用探索并移动函数 :param d: 向不同方面走时索引的变化规则 :return: """ dc, dr = d # 将表示方向的元组分别赋值给两个变量dc和dr,其中dc为x轴方向,dr为y轴方向 current_x = round(manual_t.xcor(), 1) current_y = round(manual_t.ycor(), 1) rici = ctoi(current_x + dc * cell_size, current_y + dr * cell_size) # 获取行列索引 ci, ri = rici # 检查索引是否在有效范围内 if not (0 <= ri < R and 0 <= ci < C): return point = mazeList[ri][ci] # 获取地图列表中对应点的值 if point == '0': # 通路 manual_t.color('red') mazeList[ri][ci] = '$' # 将当前位置标记为已探索 manual_t.forward(cell_size) # 向前移动 elif point == '$': # 已探索 manual_t.color(road_color) # 绘制和通道相同颜色的线,达到擦除痕迹的效果 # 将当前位置的前一个点设置为未探索 prev_ri, prev_ci = ctoi(current_x, current_y) if 0 <= prev_ri < R and 0 <= prev_ci < C: mazeList[prev_ri][prev_ci] = '0' manual_t.forward(cell_size) manual_t.color('red') elif point == 'E': # 出口 win_tip() def up_move(): # 朝上 manual_t.setheading(90) # 设置海龟朝向 manual_move(direction[2]) # 手动探索并移动 def down_move(): # 朝下 manual_t.setheading(270) # 设置海龟朝向 manual_move(direction[3]) # 手动探索并移动 def left_move(): # 朝左 manual_t.setheading(180) # 设置海龟朝向 manual_move(direction[1]) # 手动探索并移动 def right_move(): # 朝右 manual_t.setheading(0) # 设置海龟朝向 manual_move(direction[0]) # 手动探索并移动 def manual_path(): """ 功能:手动走迷宫 :return: """ global start_time start_time = time.time() # 记录开始时间 update_timer() # 启动计时器 manual_t.clear() # 清除绘图 auto_t.ht() # 隐藏海龟 auto_t.clear() # 清除绘图 global mazeList # 定义全局变量 mazeList = get_map(txt_path) # 重新读取地图数据 c_move_to(manual_t, itoc(area_sign['entry_i'])) # 移动到入口位置 manual_t.st() # 显示手动走迷宫所用的海龟光标 manual_t.width(3) # 设置画笔粗细为3像素 manual_t.color('red') # 设置画笔为红色 turtle.listen() # 监听键盘事件 turtle.onkey(up_move, 'Up') # 按下向上方向键 turtle.onkey(down_move, 'Down') # 按下向下方向键 turtle.onkey(left_move, 'Left') # 按下向左方向键 turtle.onkey(right_move, 'Right') # 按下向右方向键 def auto_path(): """ 功能:查看答案(自动走迷宫) :return: """ global mazeList # 定义全局变量 mazeList = get_map(txt_path) # 重新读取地图数据 manual_t.ht() # 隐藏海龟 manual_t.clear() # 清除绘图 auto_t.clear() # 清除绘图 auto_t.pensize(5) # 设置画笔粗细 auto_t.speed(1) # 绘图速度(慢速以便观察) auto_t.ht() # 隐藏海龟光标 find(mazeList) # 开始探索 def find(mazeList): """ 功能:开始探索 :param mazeList: 地图列表 :return: """ auto_t.clear() # 清空帮助 start_r, start_c = 0, 0 for ri in range(R): for ci in range(C): item = mazeList[ri][ci] if item == "S": start_r, start_c = ri, ci auto_t.penup() # 抬笔 draw_path(start_c, start_r) find_next(mazeList, start_c, start_r) def find_next(mlist, ci, ri): """ 功能:递归搜索判断是否为通路 :param mlist: 地图列表 :param ci: 列索引 :param ri: 行索引 :return: 布尔值,表示是否为通路 """ if mlist[ri][ci] == "E": imoveto(ci, ri) # 移动到出口 return True if not (0 <= ci < C and 0 <= ri < R): # 判断位置是否不合法 return False if mlist[ri][ci] in ['1', '$']: # 判断是否为墙或者已探索过的 return False mlist[ri][ci] = "$" # 标记已探索过 for d in direction: # 尝试从不同方向探索是否为通路,如果发现一条通路,则不再继续探索 dc, dr = d # 将索引变化规则的值分别赋值给dc和dr,其中dc为x轴方向,dr为y轴方向 found = find_next(mlist, ci + dc, ri + dr) # 递归调用 if found: # 如果是通路则绘制线路 draw_path(ci, ri) # 绘制线路 return True # 返回True,不再探索 return False # 当所有方向都不通时,返回False def draw_path(ci, ri, color="green"): # 自动绘制用 """ 功能:根据索引位置移动海龟(画线) :param ci: 列索引 :param ri: 行索引 :param color: 画笔颜色 :return: """ auto_t.st() # 显示海龟光标 cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置 auto_t.color(color) auto_t.goto(cx, cy) def update_timer(): """ 更新并显示计时器 """ if manual_t.isvisible(): # 只在手动模式下显示计时器 elapsed_time = time.time() - start_time timer_t.clear() timer_t.ht() timer_t.penup() timer_t.goto(0, R * cell_size / 2 + 20) timer_t.color("purple") timer_t.write(f"用时: {elapsed_time:.1f}秒", align="center", font=("宋体", 14, "normal")) turtle.ontimer(update_timer, 100) # 每100毫秒更新一次 def draw_game_info(): """ 绘制游戏信息(标题、关卡、操作说明) """ # 绘制游戏标题 title_t = turtle.Turtle() title_t.ht() title_t.penup() title_t.goto(0, R * cell_size / 2 + 60) title_t.color("purple") title_t.write(game_title, align="center", font=("黑体", 24, "bold")) # 绘制关卡信息 level_t = turtle.Turtle() level_t.ht() level_t.penup() level_t.goto(0, R * cell_size / 2 + 30) level_t.color("navy") level_t.write(f"关卡: {int(level)}", align="center", font=("楷体", 18, "bold")) # 绘制操作说明 hint_t = turtle.Turtle() hint_t.ht() hint_t.penup() hint_t.goto(0, -R * cell_size / 2 - 40) hint_t.color("darkgreen") hint_t.write("操作说明: ↑↓←→移动海龟 | F1:自动寻路 | F2:手动模式 | R:重新开始", align="center", font=("宋体", 12, "normal")) def restart_game(): """ 重新开始当前关卡 """ global mazeList manual_t.clear() auto_t.clear() turtle.clear() level_init() def level_init(): """ 功能:关卡初始化(手动绘制关卡数) """ global txt_path, level, mazeList, R, C # 清除所有绘图 manual_t.clear() auto_t.clear() turtle.clear() # 设置关卡地图文件 if level == 1: # 第一关 txt_path = "map/map1.txt" elif level == 2: # 第二关 txt_path = "map/map2.txt" elif level == 3: # 第三关 txt_path = "map/map3.txt" else: turtle.bye() # 退出程序 return # 获取地图数据 mazeList = get_map(txt_path) if not mazeList: print("无法加载地图,游戏结束") turtle.bye() return R, C = len(mazeList), len(mazeList[0]) # 设置窗口尺寸(根据地图大小调整) turtle.setup(width=C * cell_size + 200, height=R * cell_size + 200) turtle.bgcolor("#f0f8ff") # 设置背景色为淡蓝色 turtle.title("海龟迷宫闯关游戏") # 绘制游戏信息 draw_game_info() # 绘制地图 draw_map(mazeList) # 设置键盘监听 turtle.listen() turtle.onkey(auto_path, "F1") # F1键自动寻路 turtle.onkey(manual_path, "F2") # F2键手动模式 turtle.onkey(restart_game, "r") # R键重新开始 turtle.onkey(restart_game, "R") # R键重新开始 # 创建地图文件(如果不存在) def create_map_files(): """创建默认地图文件""" import os os.makedirs("map", exist_ok=True) # 第一关地图 if not os.path.exists("map/map1.txt"): with open("map/map1.txt", "w", encoding="utf-8") as f: f.write("1 1 1 1 1 1 1 1 1 1\n") f.write("1 S 0 0 0 1 0 0 0 1\n") f.write("1 1 1 0 1 1 0 1 0 1\n") f.write("1 0 0 0 0 0 0 1 0 1\n") f.write("1 0 1 1 1 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 0 0 1\n") f.write("1 1 1 1 1 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 0 0 1\n") f.write("1 0 1 1 1 1 1 1 1 1\n") f.write("1 E 1 1 1 1 1 1 1 1\n") # 第二关地图 if not os.path.exists("map/map2.txt"): with open("map/map2.txt", "w", encoding="utf-8") as f: f.write("1 1 1 1 1 1 1 1 1 1\n") f.write("1 S 0 0 0 1 0 0 0 1\n") f.write("1 1 1 0 1 1 0 1 0 1\n") f.write("1 0 0 0 0 0 0 1 0 1\n") f.write("1 0 1 1 1 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 0 0 1\n") f.write("1 1 1 1 1 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 0 0 1\n") f.write("1 0 1 1 1 1 1 1 1 1\n") f.write("1 0 0 0 0 0 0 0 E 1\n") f.write("1 1 1 1 1 1 1 1 1 1\n") # 第三关地图 if not os.path.exists("map/map3.txt"): with open("map/map3.txt", "w", encoding="utf-8") as f: f.write("1 1 1 1 1 1 1 1 1 1 1 1\n") f.write("1 S 0 0 0 1 0 0 0 0 0 1\n") f.write("1 1 1 0 1 1 0 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 1 0 0 0 1\n") f.write("1 0 1 1 1 1 1 1 0 1 1 1\n") f.write("1 0 0 0 0 0 0 0 0 0 0 1\n") f.write("1 1 1 1 1 1 1 1 1 1 0 1\n") f.write("1 0 0 0 0 0 0 0 0 0 0 1\n") f.write("1 0 1 1 1 1 1 1 1 1 1 1\n") f.write("1 0 0 0 0 0 0 0 0 0 E 1\n") f.write("1 1 1 1 1 1 1 1 1 1 1 1\n") # 主程序入口 if __name__ == "__main__": # 创建地图文件(如果不存在) create_map_files() # 初始化游戏 level = 1 level_init() # 隐藏海龟光标 turtle.ht() # 启动游戏主循环 turtle.mainloop()随机生成迷宫
最新发布
08-25
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值