1、第 39 卷 第 7 期 福 建 电 脑 Vol.39 No.7 2023 年 7 月 Journal of Fujian Computer Jul.2023 呙明辉,男,1980年生,主要研究领域为算法、大数据、多媒体技术。E-mail:。华容道游戏的设计与实现 呙明辉 (长江大学文理学院 湖北 荆州 434020)摘 要 为了培养学生的编程能力,加强计算思维能力的训练,在 C 语言程序设计课程中安排了独立的实践环节。本文运用EasyX 图形库在 Visual Studio 2022 平台上设计开发一个 C 语言版的华容道游戏。通过游戏的开发,达到综合运用 C 语言基本知识和熟悉软件开发流程
2、的目的,为后续的专业课程打好基础。关键词 计算思维;EasyX 图形库;Visual Studio 2022 平台;华容道游戏 中图法分类号 TP311.52 DOI:10.16707/ki.fjpc.2023.07.017 Design and Implementation of Huarong Road Game GUO Minghui (College of Arts and Sciences,Yangtze University,Jingzhou,China,434020)Abstract In order to train students programming ability a
3、nd strengthen the training of computational thinking ability,independent practice links have been arranged in the C language programming course.This article will use EasyX graphics library to design and develop a C language version of Huarong Road game on the Visual Studio 2022 platform.Through the
4、development of the game,to achieve the purpose of learning the basic knowledge of C language and familiar with the software development process,laying a good foundation for the following professional courses.Keywords Computational thinking;EasyX Graphics Library;Visual Studio 2022 Platform;Huarong R
5、oad Game 1 引言 新工科背景对计算机专业教学提出了更高的要求。为切实加快应用型人才培养,突出实践动手环节,在C 语言程序设计课程之后安排一门独立的实践课程,目的是使学生综合掌握 C 语言基础知识,加强学生的计算思维能力的培养,提高其分析问题、解决问题的能力1。但传统的 C 语言课程设计存在题目老旧、内容重复、缺少创新、形式单一等诸多问题,不利于培养学生的创新意识和开拓精神。因此,在新的大环境下,课程改革以项目产出为导向,引入 EasyX 图形库进行 Windows 编程,通过讲解贪食蛇、俄罗斯方块、华容道等小游戏的制作,提高学生的学习兴趣,对提高课程质量具有显著的提升。本文对华容道游
6、戏在 C 语言中的实现进行了较为全面的描述。2 项目简介 华容道是中国古代传统单人拼图游戏,来源于四大名著之一三国演义中的情节2。该游戏和七巧板、九连环被合称为“中国古代三大不可思议的游戏”,极富益智性和趣味性。该游戏属于单人玩的拼图游戏。棋盘是由 5 行4 列的矩形区域构成,其中放置不同大小的棋子。棋子有 4 种类型,包括 22 的曹操、11 的小兵、12 或 21 的武将,如图 1 所示。在程序中,棋盘使用 54 的二维数组表示。每个元素表示对应位置上的棋子,0 表示空,1 表示曹操,2-6 分别表示不同的武将,7-10 表示小兵,此数字同时也是棋子的 ID3,图 1 盘面的数组表示如20
7、23 年 福 建 电 脑 85 图 2 所示。曹操占 4 格,因此在数组中有 4 个元素是 1。图 1 华容道布局:横刀立马 图 2 盘面的数组表示 3 游戏功能分析 游戏功能设计为 3 个模块。(1)初始化模块,主要包括初始化游戏、载入图片、关卡选择等。(2)游戏控制模块,主要包括地图绘制、按键控制、判断移动、移动棋子、过关判定等。(3)统计模块:用于统计玩家走的步数。华容道游戏功能如图 3 所示。图 3 华容道游戏功能模块图 4 关键技术 在 VC2022 中利用 EasyX 免费图形库,完成游戏界面的绘制,使用 ExMessage 函数实现鼠标事件处理机制。关键的地方在于判断棋子是否能够
8、移动、如何将大小不同的棋子实现移动。5 游戏制作过程 5.1 准备图片素材 为每一个棋子准备 2 张图,分别表示选中和未选中的两种状态。为方便编程,图片采用棋子的 ID进行编号,例如曹操 ID 为 1,则使用“1_0.jpg”和“1_1.jpg”来描述该棋子未选中和选中的两种状态,如图 4 所示。图 4 准备图片素材及命名规则 5.2 程序基本流程 游戏开始,进行初始化,包括创建窗口、载入图片、选择布局等。在游戏执行过程中,通过鼠标选择棋子,如果存在空位,则可以进行移动,如果移动超过边界或没有空位则不能移动棋子,然后不断重新绘制地图。如果曹操移动到出口,游戏结束并统计移动步数。游戏流程如图 5
9、 所示。86 呙明辉:华容道游戏的设计与实现 第 7 期 图 5 华容道游戏程序流程图 5.3 全局变量定义 IMAGE img112;/定义 IMAGE 数组,用于显示每个棋子的两个状态 POINT pt11;/根据棋子左上角的坐标,定位棋子的位置 int selected=0;/选定的棋子,初始为空/通过坐标偏移控制上、下、左、右四个方向 struct direction int row_off;/行偏移 int col_off;/列偏移 UP=-1,0,DOWN=1,0,LEFT=0,-1,RIGHT=0,1;struct position int row;int col;int ste
10、p=0;/统计步数 5.4 初始化模块代码实现 初始化模块,主要是初始化游戏界面,载入图片等。主要代码如下:initgraph(WIDTH,HEIGHT);/创建绘图窗口 char name64;for(int i=1;i11;i+)sprintf_s(name,sizeof(name),%d_0.jpg,i);loadimage(&imgi0,name);sprintf_s(name,sizeof(name),%d_1.jpg,i);loadimage(&imgi1,name);/利用文件指针读取布局信息 void readData(int mapROWCOL)FILE*fp;fp=fope
11、n(横刀立马.dat,r);/读取布局信息 if(fp=NULL)return;else for(int i=0;iROW;i+)for(int j=0;jCOL;j+)fscanf(fp,%3d,&mapij);fclose(fp);5.5 游戏控制模块代码实现 canMove()函数判断所选对象能否在指定方向上进行移动,其条件是棋子移动的方向上存在空位或者是其本身。/判断所选对象是否能够移动 bool canMove(struct direction dir)for(int i=0;iROW;i+)for(int j=0;jCOL;j+)if(mapij=selected)if(mapi+
12、dir.row_offj+dir.col_off!=0&mapi+dir.row_offj+dir.col_off!=selected)return false;return true;moveChess()函数用于实现棋子在指定方向上的移动。需要注意的是棋子组成的每个方块都需要2023 年 福 建 电 脑 87 移动,例如曹操由 4 个格子组成,移动时每个格子都需要移动。移动完成后,原来的位置设置为空。void moveChess(struct direction dir)if(!canMove(dir)selected=0;return;/定义一个数组用于记录人物所包含的方块 struct
13、 position blocks4;int count=0;for(int i=0;iROW;i+)for(int j=0;jCOL;j+)if(mapij=selected)mapij=EMPTY;blockscount.row=i;blockscount.col=j;count+;/移动棋子 for(int i=0;i=0&maprow-1col=selected)moveChess(DOWN);if(row+1ROW&maprow+1col=selected)moveChess(UP);if(col+1=0&maprowcol-1=selected)moveChess(RIGHT);br
14、eak;isWin()函数用于判断曹操是否到达出口位置。bool isWin()int p11=0;locPosition(p);if(ptp1.x=finish.col&ptp1.y=finish.row)return true;return false;locPosition()函数用于计算布局中每个棋子左上角格子的坐标位置。void locPosition(int p11)for(int i=0;iROW;i+)for(int j=0;jCOL;j+)if(!contains(mapij,p)/记录每个棋子左上角的坐标位置 ptmapij.x=j;ptmapij.y=i;updateWi
15、ndow()函数用于绘制地图,并判断游戏是否通关4。如果通过则显示通关提示信息。void updateWindow()88 呙明辉:华容道游戏的设计与实现 第 7 期 BeginBatchDraw();/批量绘图但不输出到屏幕 int p11=0;locPosition(p);for(int i=1;i11;i+)/在坐标对应位置显示 IMAGE 数组 if(selected=i)putimage(pti.x*SIZE,pti.y*SIZE,&imgi1);else putimage(pti.x*SIZE,pti.y*SIZE,&imgi0);if(isWin()LOGFONT f;/设置背景
16、的风格为透明 setbkmode(TRANSPARENT);/获取当前字体设置;gettextstyle(&f)/字体高度为 40 f.lfHeight=40;settextcolor(RED);/设置字体 _tcscpy_s(f.lfFaceName,_T(黑体);/设置输出效果为抗锯齿 f.lfQuality=ANTIALIASED_QUALITY;settextstyle(&f);/设置字体样式 TCHAR s50=恭喜通关!;outtextxy(200-textwidth(s)/2,300-textheight(s)/2,s);settextstyle(16,0,_T(宋体);outtextxy(0,500,按任意键继续.);EndBatchDraw();6 系统测试与结果 游戏实现了华容道游戏基本功能,可以通过鼠标点击棋子进行移动,当曹操移动到出口时,游戏结束,效果如图 6 所示。游戏功能还可以进一步完善,如:(1)记录每个棋子是如何进行移动的。(2)设置时间:记录游戏进行的时间。(3)引入声音效果。图 6 游戏通关 7 结束语 本文以华容道游戏为原型,利用 EasyX 完成