微信小程序五子棋开发实战:Canvas绘制与AI权值评估
简介本资源是一套完整的微信小程序五子棋项目开发资料面向前端初学者与小程序入门开发者聚焦小游戏开发实践解决从逻辑实现到界面呈现的全流程学习需求。压缩包共12个文件包含4个JS文件实现棋盘渲染、胜负判定与用户交互逻辑、2个WXSS样式文件定义棋盘布局与动画效果、2个JSON配置文件管理页面路由与基础参数、1个WXML模板文件构建UI结构、1个DOC文档含设计说明与开发报告、1个JPG效果图及1个TXT说明文件整体仅258KB轻量易读。已有47人学习下载内容结构清晰覆盖游戏规则编码、微信原生组件调用、本地存储落子记录等核心知识点并附带可直接运行的源码与图文并茂的开发报告便于理解小程序生命周期、事件绑定机制及小游戏性能优化要点。1. 项目概述这个五子棋小程序到底做了什么做微信小程序开发最头疼的就是找不到一个麻雀虽小五脏俱全的练手项目。课程设计、毕业设计、或者单纯想给自己简历上添一笔小程序经验的十有八九都会碰见五子棋这个题目。为什么因为五子棋的规则简单到三句话能说清但牵扯到的技术点却覆盖了小程序的绝大部分核心能力页面渲染、事件交互、算法实现、状态管理、甚至本地存储和音频播放。这套微信小程序五子棋项目就是一个完整的双人对战人机对战的小程序附带一整套设计报告的写作素材和源码注释。拿到手之后你不需要再从零开始搭建打开微信开发者工具直接导入真机预览就能下棋。适合的人群很明确正在做课程设计或毕业设计的在校生、刚学完小程序基础语法想找实战项目的开发者、以及想研究棋类算法在小程序端怎么落地的爱好者。从功能上看它包含了经典的五子棋双人模式同屏对战也实现了人机对战模式AI分三个难度等级。棋盘大小是标准15×15落子后自动判断胜负赢的时候有高亮提示还有音效反馈。整个项目没有引入任何第三方UI组件库纯原生语法实现这样你在写设计报告的时候对每个模块的实现原理都能讲得很透彻不会被封装好的组件掩盖了底层逻辑。下面我会把整个项目的设计思路、核心算法、关键代码、设计报告写法以及我这段时间调试过程中踩过的坑全部梳理一遍。无论是你想基于它二次开发还是纯粹为了写报告凑内容这篇文章都能帮你省下大量时间。2. 功能需求梳理与页面结构设计2.1 需求拆解从能下棋到好用的差距在哪里拿到五子棋小程序这个需求很多人第一反应就是画一个15×15的棋盘然后点击落子完事。如果真按这个思路交作业功能演示可能没问题但设计报告就没什么可写的了。这个项目的可贵之处在于它把需求拆得比较细分成了基础功能、进阶功能、体验优化三层。基础功能是刚需15×15棋盘渲染、黑白棋子交替落子、落子后判断是否五连。这类功能实现不了项目直接不及格。进阶功能是加分项人机对战模式AI至少能挡住玩家的简单五连否则这个模式的存在就没有意义。体验优化是让项目看起来完整的关键对局结束的弹窗提示、重新开始、悔棋、下棋音效、当前轮次显示、AI计算时的等待状态。这些细节并不复杂但缺了任何一个真机演示的时候就会显得很粗糙。我在实际使用这套源码的时候体会很深它的页面结构规划得相当规矩。整个小程序就三个页面首页模式选择、下棋页对局主界面、对局记录页。三个页面的职责划分得很干净没有把功能塞在一个页面上导致代码臃肿。这一点在写报告的时候特别好用你可以把每个页面的职责和跳转关系画出来就能变成一节完整的页面设计章节。2.2 页面结构设计和导航逻辑首页的布局选择的是上下结构的常规方案顶部是游戏标题和副标题中间是双人模式和AI模式两个大的入口按钮底部放了一个对局记录的文字入口。因为功能就这么多页面级导航层次不超过三层所以没有使用自定义导航栏直接用的微信小程序原生导航栏标题栏设置成欢乐五子棋这样省去了处理胶囊按钮兼容性的麻烦。下棋页是核心整个页面用一个canvas元素渲染棋盘和棋子棋盘底部区域放了一排操作按钮重新开始、悔棋、返回首页。操作按钮配置的是flex布局横向排列每个按钮之间用固定间距隔开。AI模式下的难度选择做成了一次性的弹窗在进入下棋页之前通过参数传递这样设计的好处是游戏过程中不需要处理难度切换带来的状态重置问题逻辑会简单很多。对局记录页是基于Storage实现的每局结束后把对局时间、模式、胜负结果存到本地缓存里页面onShow的时候重新读取渲染。这一点我要多说一句很多课程设计项目会忽略这种小功能但老师答辩的时候问你做了哪些功能你说可以查看历史对局这个亮点效果是立竿见影的。而且这个页面本身代码量很少实现成本低性价比极高。2.3 数据流向和状态管理方案微信小程序虽然没有Vuex这种集中式状态管理器但这套项目的状态管理思路很清晰。全局数据放在App的globalData里局内对局状态放在Page的data里跨页面参数通过URL query传递。这样分级管理的好处是全局数据比如用户第一次打开时需要初始化的配置不会因为页面切换被重置而对局状态棋盘数组、当前轮到谁、是否结束在页面实例存续期间保持一致重新开始的时候只需要reset局内数据即可。有一点值得借鉴的是棋盘数据用一维数组存储而不是二维数组。下标i在15×15的棋盘上对应第Math.floor(i / 15)行、第i % 15列。为什么这么做因为canvas绘制棋子的时候需要把坐标转换成像素坐标而这个转换本身就需要根据行列号计算一维数组配合转换函数反而更直观同时用array.length判断棋盘是否下满也方便。3. 棋盘绘制与落子交互实现3.1 Canvas绘制的核心步骤整个棋盘绘制不复杂但每一步都必须算准像素位置否则会出现棋格被压扁、棋子错位的问题。项目里固定canvas宽度和高度都是300px棋盘四周留白15px每个格子的间距就是(300 - 15 * 2) / 14 19.285px。因为不能用小数像素表示这里使用的是四舍五入后的整数进行绘制画完线之后用ctx.draw()推送到画布上。画线的逻辑分为横线和竖线两个循环。横线的y坐标从15开始每次递增19px画14条间隔线不是15条竖线同理。这就有了15×15个交叉点棋子就落在交叉点上。落子时把点击坐标换算成交叉点坐标的核心代码如下// 点击坐标转换为交叉点坐标 const grid 19; // 格子间距 const offset 15; // 偏移量 const col Math.round((x - offset) / grid); const row Math.round((y - offset) / grid); // 检查边界 if (col 0 || col 14 || row 0 || row 14) return;这里有一个很关键的细节必须先对坐标做边界检查再检查棋盘数组该位置是否为空。如果把顺序反了会出现点击棋盘外区域时报数组越界或者已有棋子的错误在真机上还有可能导致页面卡死。3.2 棋子的绘制与视觉优化棋子用两个圆实现立体感先画一个半径8px的实心圆作为底色再在左上偏移2px的位置画一个半径3px的高亮小圆模拟光线效果。代码上看就是两个ctx.beginPath()ctx.arc()ctx.fill()的组合。白棋用白色填充加灰色描边黑棋用黑色填充加浅灰描边这样在白色背景棋盘上辨识度很高。这里我要分享一个实际踩过的坑如果直接用ctx.arc(x, y, r, 0, 2 * Math.PI)在某些安卓机型上会出现圆形边缘锯齿很严重的情况。解决办法是绘制前加一行ctx.setTransform(1, 0, 0, 1, 0, 0)重置canvas的变换矩阵确保没有历史缩放的残留这样画出来的圆会平滑很多。另一个小技巧是绘制完成后立刻调用ctx.draw(false)这个参数表示不通过回调异步绘制可以避免连点落子时出现上一帧棋子消失的问题。3.3 落子交互的事件绑定细节落子交互绑定的是canvas的bindtap事件事件对象里e.detail.x和e.detail.y就是点击点相对于屏幕的坐标。但这里有一个容易忽略的坑如果canvas的宽度用了rpx单位比如设置成750rpx在不同屏幕尺寸的设备上实际像素宽度是不一样的直接用e.detail.x去算格子会错位。这套项目里canvas的宽高样式与实际像素尺寸一致用的是px单位所以没有踩到这个坑。如果你自己二次开发时发现棋子落不到想落的位置优先检查是不是rpx和px混用了。落子逻辑封装在handleClick方法里整体流程是校验当前游戏是否结束 → 换算坐标 → 校验位置合法性 → 更新棋盘数组 → 绘制棋子 → 判断胜负 → 交换轮次。这个方法写在Page里通过this.setData更新棋盘数组数组变了再触发canvas重绘。用setData更新而不是直接修改this.data的原因是因为setData会触发视图层的数据同步虽然canvas绘制不依赖数据到视图的渲染但这样做能在后续扩展界面UI时避免数据不同步的问题。4. 胜负判断算法最简单的五子棋核心逻辑4.1 遍历方向与边界处理五子棋胜负判断的思路很直接每落下一颗棋子就以这个棋子为起点在四个方向上横、竖、左斜、右斜检查是否存在连续的五个同色棋子。四个方向可以合并成两个循环用坐标增量数组表示const directions [ [1, 0], // 水平方向 [0, 1], // 垂直方向 [1, 1], // 右下对角线 [1, -1] // 右上对角线 ];每个方向都从落子点出发先沿着正方向连续计数遇到不同色或超界就停然后再从落子点出发沿反方向计数。总连续数 5 就说明赢了。这个算法的复杂度是O(4×5)也就是最多检查20个位置性能上完全可以忽略不计。边界处理是这个算法的重灾区。数组下标从0到14在检查方向的时候比如从坐标(14,14)沿[1,1]方向走下一步就是(15,15)访问数组会报错。所以每次访问前必须判断row dr 0 row dr 15 col dc 0 col dc 15。有的同学喜欢把棋盘数组扩大到17×17边缘留一圈空位这样就不需要边界判断了也是一个思路但数据初始化和坐标映射会绕一点个人觉得没必要。4.2 平局判断与游戏状态管理平局条件很简单棋盘数组满了但没人五连。实现上就是在落子后先判断胜负没赢的话检查棋盘数组是否还有空位如果board.length 225不考虑被吃掉的路径说明下满宣告平局。这个项目在游戏状态管理上有一个设计得比较细致的地方用gameOver标志位区分正在对局和已经结束两种状态。在落子方法的第一步就检查if (this.data.gameOver) return这比在胜负判断之后再去阻止后续落子要更干脆。同时turn用 1 和 2 分别代表黑棋和白棋初始值为1落子后turn 3 - turn实现轮换。这个技巧很常用比turn 1 ? 2 : 1的写法简洁。4.3 胜负高亮提示的实现胜负判定之后除了弹窗提示棋盘上还需要把获胜的五颗棋子高亮显示。这里的实现是在胜负判断函数里不仅返回胜负结果还返回获胜棋子的坐标数组。调用方拿到坐标数组后遍历这些位置用红色圆圈重新绘制一层描边。因为红圈是在Canvas上后画的等于是把棋子高亮标记出来了。这个细节虽然不起眼但真机演示的时候观感提升非常明显。我在给学生演示的时候经常说一个五子棋项目如果连获胜高亮都没有评委基本会默认你是网上抄的免费源码。加了这个功能至少表明你理解展示层和逻辑层的分离。代码量也就多了十几行非常划算。5. AI对战从双人模式到人机模式的技术升级5.1 为什么要做AI难度分级双人模式实现之后距离可交付还差一步人机对战。但是一个没有任何博弈策略的AI会让游戏变得很无聊——玩家第一手下中间AI随便下一手玩家第二手连成三子AI依旧乱下。这会让评委质疑项目的完整性。所以这个项目的AI模式划分了三档难度简单、普通、困难。其中困难级别的AI具备基本的攻防意识能挡住玩家的活三和双二不会出现明显的低级失误。从实现成本看三档难度对应的算法差异并不大主要区别在于搜索深度和随机性两个参数。简单AI只考虑当前一步能不能赢不能赢就随机落子普通AI考虑当前一步能不能赢不能赢就优先阻挡玩家的活三困难AI在此基础上还会评估棋型的权重选择威胁最大的位置。5.2 权值评估法的核心思路严格意义上的AI算法有极大极小值搜索、Alpha-Beta剪枝、蒙特卡洛树搜索但这些在小程序端都过于笨重15×15的棋盘搜索深度稍微上一点js就扛不住了。这套源码采用的是经典的权值评估法也叫打分法。思路是遍历所有空位对每个空位分别计算如果黑棋下这里能形成多大的威胁进攻分如果白棋下这里能挡住黑棋多少防守分然后把两者相加作为该位置的总分最后选择总分最高的位置落子。对于每一个待评估的空位需要检查以它为中心的四个方向横、竖、两个斜角统计在这个方向上的连续同色棋子和空格分布然后对照预先设定的棋型表打分。棋型表是权值法的核心举几个常用的例子棋型描述权值五连已经赢了100000活四两端都开放的四个棋子50000冲四只有一端开放的四个棋子8000活三两端都开放的三个棋子3000眠三只有一端开放的三个棋子1000活二两端都开放的两个棋子500眠二只有一端开放的两个棋子100表中的数值不是固定的你可以根据自己的体验调整。核心原则是让成四的权重远大于成三否则AI会只顾着冲自己的活三却挡不住对手马上就要成五的棋。这个项目里用的数值区分度很大实测困难模式下AI能有效挡住玩家的活三和冲四不会出现看着玩家快赢了却去下无关位置的尴尬情况。5.3 AI落子的异步处理AI计算需要一个不短的时间尤其是困难模式遍历225个空位的评估需要几毫秒到几十毫秒。如果直接在主线程里执行计算用户会感觉小程序卡顿了一下更严重的是在部分低端机型上会出现未响应的提示。解决办法是利用小程序提供的wx.nextTick或setTimeout做延迟执行让出主线程给页面渲染留出时间。项目里AI计算用的是setTimeout延迟200ms执行一方面让UI有时间展示AI正在思考的状态另一方面也符合真实对弈的节奏感体验上比秒回应要好。延时执行的时候有一点要注意如果用户在这个延迟期间点击了重新开始按钮AI的回调节奏里必须检查当前对局是否仍然有效否则会出现玩家已经重开了AI还在往旧棋盘上落子的bug。这个项目的做法是在执行AI落子前校验一次gameOver标志同时对局开始时间戳做了一次匹配如果重新开始之后时间戳不一致就放弃本次计算。这个防御性设计很值得学习。6. 设计报告怎么写才能拿高分6.1 设计报告的黄金结构很多同学源码能跑但一写报告就头疼。这篇文章要告诉你的是报告和代码是配套的你不需要编内容源码里每一个模块都能对应上报告的一个章节。这套项目的设计报告大致分六章我按顺序梳理一下第一章是引言写项目背景和意义用两页纸讲清楚为什么要做一个微信小程序版五子棋背景可以写微信小程序生态的普及、移动端休闲游戏的需求不要太长重点是引出你的项目选题。第二章是需求分析把功能分成双人模式、人机对战、对局记录、悔棋、音效、胜负提示这六项每项分别描述功能需求和预期的交互结果。第三章是系统设计内容包括技术选型说明为什么用原生小程序而不是uniapp、页面架构图、数据存储设计。第四章是核心功能实现这一章是最占篇幅的对应源码里三个最核心的算法棋盘绘制、落子逻辑、胜负判断、AI权值评估。每一部分都用需求描述 → 流程图 → 核心代码 → 运行效果的结构展开。第五章是测试写一下在不同机型上的真机测试结果对局记录功能的功能测试以及AI不同难度的胜率测试。如果有条件可以让同学帮忙在不同手机上下载体验然后把反馈写进测试报告。第六章是总结与展望写做项目过程中遇到的问题和解决方式以及未来想优化的方向比如增加联网对战、加入房间系统、增加更高阶的AI算法等。6.2 技术选型部分怎么写才显专业设计报告里技术选型是评委必看的部分。你不能只写本系统使用微信小程序原生开发一句话要把为什么论证出来。可以这样写本系统选择微信小程序原生框架原因有三点——一是因为五子棋是一个实时交互型小游戏原生的Canvas渲染性能相比WebView方案更稳定数据更新和手势交互的响应速度更快二是因为项目需求复杂度适中不涉及多端复用不需要引入uniapp或taro这层抽象增加额外的调试成本三是因为原生小程序在微信开发者工具中提供了完善的真机调试和性能分析工具便于对canvas绘制效率进行优化验证。AI算法部分你要说明为什么选择权值评估法而不是更复杂的搜索树算法。可以这样论证当前项目的人机对战中AI需要在移动端设备上实时响应搜索类算法需要较大的计算量和内存开销对低端安卓机的兼容性不够友好而权值评估法通过预先定义棋型权重在15×15棋盘上即便遍历全部空位做一次评估也只需毫秒级别真正做到了响应快、效果直观、便于后期调整。这种论证方式会让老师觉得你是真的做过对比分析而不是拿了一个算法就往上套。6.3 测试报告的实用套路测试报告不需要写得像专业QA那样复杂但一定要有理有据。项目里配置了一个简单的测试表格模板按功能模块逐项填写测试用例包括测试步骤、预期结果、实际结果。这块我建议你在交付前实际跑一遍把遇到的异常记录进去然后修复后重新测试一遍。这一来一回的记录会让报告的问题发现与解决章节真实可信而不是通篇一切正常。有一个测试方向很多人会忽略不同屏幕尺寸下的兼容性测试。五子棋棋盘依赖canvas的定位如果屏幕比较窄棋盘显示不下或者按钮被顶出屏幕都是可能出现的。你拿着源码在iPhone SE和iPhone 14 Pro Max上各跑一遍从测试结果里截两图放进报告这一章节比你在论文里写一千字都有说服力。7. 源码文件结构与环境配置详解7.1 项目目录逐层解析第一次打开源码你先别急着点运行最好花十分钟把目录结构过一遍。这个项目的目录层级很清晰project/ ├── app.js # 全局逻辑入口 ├── app.json # 全局页面配置 ├── app.wxss # 全局样式 ├── project.config.json # 项目配置文件 ├── pages/ │ ├── index/ # 首页模式选择 │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── game/ # 下棋页核心对局逻辑 │ │ ├── game.js │ │ ├── game.json │ │ ├── game.wxml │ │ └── game.wxss │ └── records/ # 对局记录页 │ ├── records.js │ ├── records.json │ ├── records.wxml │ └── records.wxss ├── utils/ │ ├── board.js # 棋盘数据与绘制工具 │ ├── ai.js # AI权值评估算法 │ └── storage.js # 对局记录存储封装 └── assets/ ├── sounds/ # 音效资源 └── images/ # 图标资源其中utils/board.js和utils/ai.js是核心逻辑的独立模块从页面逻辑里抽出来单独维护这一点做得非常好。小程序虽然是页面驱动但纯逻辑模块独立出来之后不仅能在不同页面复用更重要的是你可以在Node.js环境里写单元测试跑算法不必每次都启动开发者工具。我在调试AI权重的时候就是在本地用Node跑ai.js输入棋盘状态输出候选落点效率提升了不止一倍。7.2 微信开发者工具的导入步骤拿到源码在本地跑通的流程很简单但有几个细节如果你没注意会卡住。第一步安装最新版的微信开发者工具打开之后选择导入项目在目录中选择解压后的项目根目录要保证project.config.json在这一层。第二步填上你自己的AppID如果没有注册小程序账号选测试号也可以正常跑大部分功能。第三步导入后如果提示未找到 app.json说明目录选错了往下一层找到包含app.json的文件夹重新导入即可。还有一个常见的坑是基础库版本问题。如果你用的是比较旧的project.config.json里面锁定的基础库版本可能需要更新否则在开发工具里会提示调试基础库版本过低部分API无法使用。解决办法是在开发者工具右上角详情 → 本地设置里把调试基础库版本切换到一个较新的稳定版本即可。建议至少使用2.20.0以上的版本Canvas相关接口在这个版本之上兼容性较好。7.3 音效和图片资源的引入方式小程序对资源文件的引用路径有严格要求不能直接引用本地图片的绝对路径需要通过相对路径引入。这套项目里音效和图片放在assets/目录下页面中使用相对路径访问比如在game页面里const moveSound wx.createInnerAudioContext(); moveSound.src /assets/sounds/move.wav; moveSound.play();项目里提供了三套音效落子音、胜利音、失败音。音量适中不会刺耳。如果你要自己替换音效注意格式要转成m4a或mp3文件大小建议控制在300KB以内避免影响小程序加载速度。小程序主包大小限制是2MB几个音效文件很容易就超了如果超了把音效文件压缩一下或者用外链地址是常用的解决方案。8. 常见问题与调试技巧实录8.1 Canvas真机显示空白或棋子消失这是小程序开发中最经典的问题。发生的原因通常是canvas的宽高在机型适配时出现了问题特别是在设置了rpx单位时。真机上屏幕宽度和CSS像素宽度不一致如果canvas的上下文使用的是相对坐标计算出的像素坐标和绘制时的画布坐标不匹配就会出现画了但看不到的情况。排查方法很直接在canvas绘制前调用wx.createSelectorQuery()获取canvas节点实际的像素宽度把绘制坐标按实际宽度做一个缩放然后再开始画。还有一个原因和canvas性能有关就是这个项目的棋盘绘制用的ctx.draw()本身是异步方法如果紧接着重新开始游戏上一帧draw还没完成就被新的draw覆盖偶发会出现棋子消失。解决办法是在ctx.draw()的回调里执行后续操作比如判断胜负后的界面更新确保绘制完成后再处理。我在源码里看到这几种场景下都用了回调形式所以正常使用不会触发这个问题但如果你改代码的时候把绘制从回调改成同步逻辑就要特别注意了。8.2 AI模式下的白棋秒落子状态错乱我在调试人机对战时遇到一个很典型的对手操作问题AI走完一步后轮次直接跳到黑棋但页面显示还是白棋回合。排查下来发现是AI落子方法里更新了this.data.turn但页面UI依赖的标志位没有同步更新导致理论上白棋走完了UI还是白棋立场玩家下一次点击落的是黑棋。解决方案是——AI走完棋后不要直接在逻辑层修改turn而是把turn的修改放在AI落子函数的公共回调里和玩家落子共用同一段切换轮次代码。这段代码统一维护turn数据和UI里当前回合指示器的同步更新。如果你在自己的项目里遇到了各种状态错乱类的问题绝大多数都是因为逻辑层的数据更新和UI的数据绑定走的不是同一条路径合二为一才是根治的办法。8.3 棋盘数据被意外修改的三方原因调试过程中发现棋盘数组有时会被意外修改表现为这块明明没落子但判断胜负时发现有子。排查到最后发现是两个原因叠加第一AI算法在评估权值时会临时修改棋盘数组来模拟落子评估完没有完整恢复第二双人模式下玩家快速点击了两个位置第二个落子还没经过合法性校验就被绘制函数读取到了更新后的数组。修复方式是在AI模拟评估前把棋盘数组深拷贝一份评估结束后使用原数组恢复同时在绘制函数里增加一个当前是否正在绘制的标志位绘制期间不接受新的落子请求。这个问题也暴露了一个重要的编码习惯凡是会修改全局状态的函数在入口处显式备份、退出时恢复或提交是避免隐藏bug的有效手段。测试时你可以连续快速落子二十次如果棋盘数据依然整齐说明这个状态管理是健壮的。源码里这部分的处理应该说是做得比较到位的。8.4 卡在加载页或页面白屏的排查路径如果你导入项目后首页白屏优先检查app.json里注册的页面路径是否写对了。这是一个非常常见的低级错误页面文件存在但app.json里pages字段第一个路径写错小程序启动后找不到首页就会白屏。检查方法很简单把pages字段的第一行设置成pages/index/index保存后重新编译。第二个排查点是首页的wxml文件里是否包含根节点。微信小程序的页面模板必须有一个唯一的根节点如果写了两个平级的view在某些基础库版本上会警告但不影响渲染但在低版本基础库上直接白屏。看到控制台有Multiple root nodes这种报错就是这个问题包一层view再编译即可。第三个排查点是全局配置文件里有非法字符。app.json用的是严格的JSON格式不允许有注释也不允许有多余的逗号。如果你用编辑器打开并手动改过导入后报app.json: Expecting }之类的错按提示到对应行把多余逗号删掉就行。这些虽然都是入门级问题但在交作业的前一天最容易让人抓狂写在这里提醒一下。8.5 性能优化低端机上棋盘真机体验卡顿怎么办如果你在低端安卓机上测试可能会发现落子后棋子要过几百毫秒才出现。主要的性能瓶颈在于每次落子都重新绘制了整个棋盘15×15网格全部已有的棋子而不是增量绘制。优化的思路有两种。第一种只在落子位置绘制新棋子不重绘棋盘。由于canvas没有局部清除重绘的API你需要在棋盘背景下画一个白色的圆形区域覆盖掉旧棋格然后在新位置画棋子。但这种方式有一个隐患如果棋子有阴影效果白色覆盖圆会把阴影也抹掉视觉效果不完美。第二种把棋盘网格预先绘制到离屏canvas上每次落子时先用ctx.drawImage把离屏canvas内容贴到主画布底部然后再在上面画棋子。这样每次落子只需画一张图片和当前棋子性能提升显著。这套源码用的是全量重绘的方式因为它更简单并且在中等以上性能的手机上完全流畅。如果你非要追求低端机的极致体验可以用离屏canvas优化方案做二次开发改动量也不算大核心就是新增一个canvas节点专门画网格。9. 从这份源码里还能延伸出什么项目跑通、报告写完如果你还有余力可以考虑几个明确的扩展方向。第一个方向是增加联机对战接入微信小程序的云开发能力用云函数做房间匹配和消息转发这是目前课程设计里面比较少见但含金量高的功能。第二个方向是增加更高级的AI算法在权值评估法的基础上用极小极大搜索加深AI的预判能力这也是可以写进报告未来展望章节的亮点。第三个方向是美化界面把棋盘改成木质纹理棋子加上更真实的渐变高光虽然对功能没有影响但在答辩演示时视觉冲击力是完全不同的。我个人在实际操作中的一个体会是不要小看这套源码里的AI模块。虽然权值评估法并不算高深但它在移动端的性能表现确实很出色如果直接换成搜索类AI在低端机上的卡顿会让你悔不当初。对于学习和授课场景从权值法入门再逐步进化到搜索算法是最稳妥的一条路径。如果你打算把它用到自己的项目里我建议先把AI的棋型权重表打出来贴在电脑前面边调边看效果这样才能真正理解每一档数值变化带来的棋风差异。本文还有配套的精品资源点击获取
