基于STM32F469I-discovery的触屏版中国象棋
项目代码已开源于github:基于STM32F469I-DISCOVERY的触屏版中国象棋
项目简介
中国象棋是中国棋文化,也是中华民族的文化瑰宝,它源远流长,趣味浓厚,基本规则简明易懂,因此广受民众喜爱,是普及最广的棋类项目,至今已流传到十几个国家和地区。
中国象棋使用方形格状棋盘,圆形棋子共有32 个,红黑二色各有16 个棋子,摆放和活动在交叉点上。双方交替行棋,先把对方的将(帅)“将死”的一方获胜。
本项目基于STM32F469I-DISCOVERY
开发板,成功复现了中国象棋的游戏界面与规则,通过开发板上的LCD 触摸屏进行界面的交互,实现了中国象棋的双人对战模式。
设计方案
设计思路
系统的设计主要分为3个模块:
- UI设计:主要负责界面的交互,显示棋局和触摸结果。
- 程序逻辑:主要负责象棋的规则。
- 字库设计:存储棋盘、棋子和旁白文字的数据。
三个模块彼此相对独立,因此分文件编写。
软硬件结构
软件层面使用C语言进行代码的编写,主要使用的高层API有板级支持包(BSP)和硬件抽象库(HAL),用于LCD界面的渲染。
硬件层面主要使用了高性能MCU:STM32F469I、480*800LCD(触摸)显示屏、128Mbits-SDRAM及相关硬件驱动。
系统实现
UI 设计
由于开发板上的LCD 屏幕支持双层显示结构,因此UI 设计也使用双层显示的方式实现:下层LCD 负责棋盘的显示,上层LCD 负责棋子的显示和旁白书写。
下层棋盘样式 |
---|
![]() |
上层棋子样式 |
---|
![]() ![]() |
对于下层的显示,在Flash 中预先保存好棋盘图,在初始化时一次性写入,后续不需要更改。
上层的32 个棋子同样有自己的像素图,显示棋子只需要将对应图像画在上层LCD 对应的棋盘格
交点处。触屏操作主要有两个步骤:
- 第一步是选中棋子,只需要将被选中的棋子突出显示。这里采用的是在对应棋子周围绘制宽度为2 像素的正方形边框,以示突出;
- 第二步是移动棋子, 一方面需要擦除被选中棋子所在位置的图片和选中框,这里只需要将上层LCD 对应位置透明化即可,另一方面是在终点位置绘制新的棋子图片。
需要注意的是,当两次选子均选中本方的棋子时,默认为重新选子
,会擦除上一次的选中框,并绘制在第二次选中的棋子上。程序中还设置了移子规则判断,若移子操作不满足象棋的移子规则,会在旁白提示移子无效,需要重新进行移子操作。
程序逻辑
程序逻辑部分主要是将中国象棋的规则进行了程序实现,并附加旁白提示的功能。
移子操作
移子操作分为两个过程,移子路径获取和移子路径合规判断。
- 移子路径获取移子路径获取是通过两次选中棋子来确定棋子的移动路径。这里的触摸响应通过LCD 屏的外部中断实现,对应开发板的EXIT9 中断。
- 移子路径合规判断移子路径是否合规需要满足象棋的规则,一方面,每个棋子都有自己的移子规则(马走日、象走田等);另一方面,需要保证移子后不立即出现被将军的局面。
局面分析
局面分析也分两步走:判断是否将军和判断是否终局。
- 是否将军可以通过判断车马炮兵是否可以一步到达对方将/帅的位置、将和帅是否“直冲”,来判断是否出现将军的局面。
- 是否终局是否终局需要先确定出现将军局面的情况下进行判断。在被将军的情况下,先尝试主动移动被将军的将/帅,若能逃离将军局面,则未终局;若移动将/帅不能逃离将军局面,则根据“刺客”棋子来进一步判断:

如果将/帅不能通过主动移动逃脱将军,也无法阻止“刺客”棋子的将军,则意味着终局。
旁白显示
旁白显示分为以下四类:
- 移子无效提示
- 将军提示
- 终局提示
- 擦除提示
前三种旁白都在特定的情况下显示,而在解除对应情况后会擦除提示。
悔棋操作
中国象棋支持悔棋操作。悔棋时,需要将棋盘恢复到上一步棋移动之前的棋局。因此每次进行移子时,都需要存储移子的相关信息,包括出发点坐标、终点坐标、被移动棋子的索引、是否吃子以及被吃棋子的索引。这里需要一个栈结构
来存储移子信息,以保证悔棋时的正确顺序。
悔棋采用外部按键中断
的方式实现,使用开发板上的蓝色按钮,对应STM32 的外部中断EXIT0
,在中断回调函数中,根据移子信息恢复之前的棋局,即可完成悔棋操作。
代码目前只实现了一次悔棋
操作,尚未实现栈结构,因此只能执行一次悔棋。如果需要多次悔棋,请自行实现栈结构。
字库设计与获取
旁白文字和棋盘图片均以C 语言数组的方式直接存在程序之中,在显示时直接调用即可。
- 旁白文字
旁白文字采用汉字楷体
进行显示。字的扫描方式是从上到下、从左到右的顺序
进行。字体颜色有红色和黑色两种,移子无效提示使用纯黑色字,将军提示和终局提示使用红/黑代表将军方/获胜方。 - 棋子、棋盘图
棋子和棋盘图片的获取来源是游戏“中国象棋”官网,从官网获取到棋子和棋盘的格式为gif
文件。编写Python
编程语言,使用Pillow
库实现gif
图片到png
图片的格式转换,再使用OpenCV
包从PNG
图片中进行像素级ARGB
提取。最后将提取结果以C 语言常量数组
的格式存储在程序中。
资源使用
下图是STM32CubeIDE 给出的资源实际使用情况:
图片数据占用了项目最多的资源。汉字、棋子和棋盘图以常量C 语言数组的形式保存在程序中,采用ARGB8888 的32 位真彩色表示,即每个像素点用一个32 位的数据表示其颜色,从高到底分别对应8 位透明度、8 位红色、8 位绿色和8 位蓝色, 每个像素点需要4Bytes 的空间存储,而棋盘图像素大小为480x531,棋子像素大小为48x48。因此存储棋盘和棋子图片需要
(
480
×
531
+
14
×
48
×
48
)
×
4
B
y
t
e
s
=
1.095
M
B
(480 × 531 + 14 × 48 × 48) × 4Bytes = 1.095MB
(480×531+14×48×48)×4Bytes=1.095MB
的空间。由于内部FLASH
为2MB,足以保存图片数据。因此直接将图片数据保存在内部FLASH 上,而无需使用开发板上的外部FLASH。这种存储方式也有利于图片数据的快速读取。
总结与改进
本项目基于STM32F469I-DISCOVERY
开发板,实现了触屏版双人对战中国象棋的基本功能。项目结合了多图片显示、汉字显示、触屏交互、图片存储、数据结构、多文件编程
等多个方面内容,是一个综合性较强的项目。
本项目还存在一定的优化空间
,一方面,开发板的有效触控范围较小,如果使用手指进行触摸,误触的可能性较大,可以使用触控笔的方式操作更为精准;另一方面,LCD 的扫描显示仍存在撕裂
现象,存在优化的空间,进一步的改进可以从合理利用总线带宽、更改显示策略(例如下层显示屏不刷新、双缓冲区)等方面入手。