基于游戏化学习的编程教学模式研究

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于游戏化学习的编程教学模式研究作者:张立立徐博文杨金柱王彤高东博
来源:《高教学刊》2022年第26期
摘要:为引导学生能够对编程课程产生浓厚兴趣,该文设计实现C/S网络体系架构的象
棋棋牌室系统,包括支持多并发的异步收发服务器端及棋牌室客户端。

其中,网络通信使用基于TCP协议 socket套接字通信。

经测试,系统能够实现客户端创建房间、桌面管理,以及棋
盘与棋子的可视化等各项功能。

通过对此软件的开发设计过程,锻炼学生的编程能力及对软件开发的学习兴趣。

关键词:C/S架构;象棋;Qt;TCP协议;系统设计
中图分类号:G642 文献标志码:A 文章编号:2096-000X(2022)26-0052-04
Abstract: In order to guide students to have a strong interest in programming courses, this paper designs and implements a chess room system based on C/S network architecture, including asynchronous transceiver server and chess room client. Among them, the network communication uses socket based on TCP protocol. After testing, the system can achieve client to create rooms,desktop management, as well as the visualization of chessboard and chess pieces and other functions. Through the development and design process of this software, students' programming ability and learning interest in software development are trained.
Keywords: C/S Architecture; Chess; Qt; TCP Protocol; system design
学习利用cpp知识[1]、参考Qt手册[2],综合运用计算机网络,操作系统原理(多线程同步),数据结构,数据库技术,MVC设计模式[3],面向对象程序设计方法[4],软件工程学科等知识开发实际系统[5]。

熟悉应用软件的开发过程[6],要求软件界面美观,操作简便,符合象棋棋牌室的实际游戏场景。

基于以上基本教学要求,本文开发了一套象棋棋牌室游戏系统,课程目标是通过学生熟悉的网络游戏入手,逐步完善游戏功能,让学生在编程学习中建立信心和成就感,从而对编程产生兴趣,进行更深入的研究和探索。

一、系统功能介绍
系统由服务器、客户端两部分组成,客户端具有选座界面、对局界面。

用户启动客户端软件之后,客户端显示界面并自动尝试与服务器建立连接,若连接成功,界面显示“已连接”;若连接失败,系统显示“未连接”,用户可以通过“重新连接”按钮来重新连接服务器。

服务器连接成功后,用户可以输入用户名、密码向服务器发送登录请求,服务器校验后向客户端发送成功/失败反馈。

若已有客户端使用此用户名登录,则不可以重复登陆。

完成登陆后,系统显示当前登录的用户名和积分。

此时,客户端显示选座界面,用户可以:(1)创建比赛对局(房间);(2)取消创建的对局(房间);(3)加入已有的对局(房间);(4)观战正在进行的对局。

当找到对手(加入房间/创建的房间被加入)或选择观战模式之后,界面切换到对局界面。

非观战模式下,用户可以依据棋规移动棋子,移动不符合棋规时,系统不响应。

双人对战过程中如果某一方获胜,对战终止。

此时,胜负两方分別加减积分,客户端返回选座界面;如果有一方点击“退出/认输”按钮,则判定这一方为负,其他同上。

观战过程中,点击“退出/认输”按钮,客户端返回选座界面。

流程如图1所示。

二、系统详细设计及方案
整个系统由一个中心服务器和若干个客户端组成。

用户功能上主要有对局系统和棋牌室座位管理系统两部分。

服务器和客户端均利用C++和Qt框架编写。

为了实现了多人时操作、客户端网络通信不影响用户操作,使用了多线程技术。

服务器和客户端之间采用TCP协议[7]进行通信,服务器采用改进过的bio模式,即为每个客户端连接建立两个线程分别用来收发网络消息。

选座系统、棋规判定系统和棋盘模型等均位于服务器端。

客户端部分除了网络模块之外,仅保存视图。

服务器端连接mysql数据库[8]存储用户名、密码和积分信息。

(一)Qt简介
Qt 是一个跨平台的C++应用程序开发框架。

它提供给开发者建立图形用户界面所需的功能,广泛用于开发GUI程序,也可用于开发非GUI程序。

Qt是完全面向对象的,很容易扩展,并且允许真正地组件编程。

(二)网络通信及消息处理
服务器端由一个线程负责建立TCP连接,连接建立成功后,开启两个新的线程用来进行socket通信[9]。

一个线程用于向客户端发送数据,相当于“生产者消费者”模型中的消费者。

在没有需要发送的消息时利用Qt框架的WaitCondition等待(相当于优化后的自旋锁,可以有效降低cpu使用率)。

当需要发送消息时,其他线程设置好此消息线程对象的消息内容成员,并唤醒此线程(相当于打开自旋锁),就可以实现消息发送。

在使用Qt的信号与槽连接时,使用Qt::Dirrectconnection连接方案,否则会因为目标线程阻塞而无法唤醒线程发送消息。

另一个线程用于接收客户端数据,对于每一次接收的数据。

利用Qt的信号与槽机制注册到UserConnection类的doRecv函数。

这样就形成了如下设计。

每个抽象的UserConnection对应一个实际的用户连接。

所有连接(UserConnection)共享一个RoomManager类的对象roommanager。

所有连接(UserConnection)共享一个数据库操作类。

每个连接有一个独立的连接抽象层(组合了收发线程的TCPConnection类)用于管理收发线程。

对于服务器的消息发送,调用连接抽象层的send函数即可向客户端发送消息。

对于服务器的消息接收,直接回调doRecv函数,相应的业务就可以在此函数中得到处理,而无需考虑网络具体实现。

用这样类似java web中servlet的方式可以对底层的网络部分更好地封装,降低耦合便于拓展。

客户端的网络模块设计与服务器类似,只是不同于服务器多个连接,客户端仅有收发两个线程。

(三)对局系统的实现
系统整体采用mvc设计模式,便于降低代码耦合性,有利于组件的重用。

如图2所示。

客户端的ChessView等类继承自Qt的Widget,用来与用户交互。

服务器的ChessField类是棋盘模型,棋规判定、胜负判定等业务逻辑在此类中实现。

这个类聚合了抽象类ChessPiece的不同实现,对应不同种类的棋子。

每个子类有各自的边界判断,移动判断函数。

控制器为上文提到的UserConnection类。

(四)座位管理系统的实现
每一个UserConnection中都有一个相同的RoomManager类指针指向一个共享的RoomManager对象,程序截图如图3所示。

可以看到:该类提供了新建房间、加入房间、观看对局等接口,接收的参数是User,用户连接使用时通过传入this指针就可以实现操作。

存储的数据结构使用了键值对(QMap),其结果如图4所示。

对于一个没有对手的“单人房间”,在room_struct当中存放两个nullptr,这时键UserConnection代表房间,作为房间句柄。

“加入比赛”时,为新加入的人也创建一个键值对,即一个“房间”分配两个空间,这样可以更加高效地定位棋盘模型和对手。

调用roomInfo函数不直接返回该数据结构,而是将冗余的第二份房间信息去除,这样得到的QMap的键UserConnection 可以唯一标识一个房间,作为房间句柄使用。

程序截图如图5所示。

这个类同时也维护用户列表,提供重复登陆判断等接口。

三、系统测试
(一)系统调试和难点分析
1. 并發过程中数据一致性问题
问题描述:调试时,程序运行过程中出现非预期的不合理结果。

比如修改某些数据不生效等情况。

原因:roommanager共享对象在多线程环境下有可能同时被多个线程同时写入,进而出现数据一致性问题。

解决方案:roommanager等多线程共享对象,在需要写入时需要用Qt提供的QMutex互斥锁对给资源加锁[10],在修改完成后释放互斥锁,在此过程中其他的线程将不能进行修改。

2. 客户端连接释放问题
问题描述:调试过程中,客户端程序突然终止连接后,服务器程序常常无响应或是异常终止。

而作为一个服务器,因为某客户端的某些行为导致崩溃是不能接受的。

原因:C++语言是不同于java一类具有垃圾回收器的编程语言,需要手动管理内存及相应的资源。

在客户端中断连接以后,必须要结束为该用户创建的连接线程,释放内存,清除所有此用户的对局状态信息,同时从已登陆用户列表中移除该用户。

解决方案:必须找到合理的方式释放资源。

在线程创建过程中将RecvThread类的die信号与TCPConnection类的析构方法连接。

当检测到客户端连接中断后,RecvThread发出die信号。

这时,首先析构TCPConnection对象,在~TCPConnection()中析构UserConnection类的对象。

为了清除所有此用户的对局状态信息,同时从已登陆用户列表中移除该用户:UserConnection类的析构方法调用RoomManager::logoff,此函数释放所有包含UserConnection的对局。

并在users:QSet中删除这个User,从而实现将该用户标记为非登陆状态。

完成以上这些之后,关闭TCPSendThread线程,由于此线程处于阻塞状态(等待网络消息的生产者生产消息),故不能直接结束线程。

使用Qt提供的terminate()函数强制终止线程有会带来一系列的问题,比如影响到其他正常运行的线程。

故设计了如图6所示的interrupt方法。

最后,需要终止TCPRecvThread。

(二)系统运行界面
图7为系统登录界面,正确输入用户名和密码后,点击登录按钮,可以进入到选座系统界面,如图8所示。

选座完成后,点击建立房间,进入对战模式,如图9所示。

四、结束语
本文给出了使用C++和Qt技术进行象棋棋牌室游戏软件的设计方案,详细介绍了系统各部分的功能原理、运行流程及具体的实现方案,最后对系统各个功能进行测试。

本设计案例重在巩固学生对理论知识的理解,让学生明白只有通过实践才能验证所学所得、才能熟练掌握课程知识。

在实践中多层次全方位的学习知识、在实践中加深对所学知识的印象,锻炼软件开发的能力,以及对系统调试和解决实际问题的能力。

另一个线程用于接收客户端数据,对于每一次接收的数据。

利用Qt的信号与槽机制注册到UserConnection类的doRecv函数。

这样就形成了如下设计。

每个抽象的UserConnection对应一个实际的用户连接。

所有连接(UserConnection)共享一个RoomManager类的对象roommanager。

所有连接(UserConnection)共享一个数据库操作类。

每个连接有一个独立的连接抽象层(组合了收发线程的TCPConnection类)用于管理收发线程。

对于服务器的消息发送,调用连接抽象层的send函数即可向客户端发送消息。

对于服务器的消息接收,直接回调doRecv函数,相应的业务就可以在此函数中得到处理,而无需考虑网络具体实现。

用这样类似java web中servlet的方式可以对底层的网络部分更好地封装,降低耦合便于拓展。

客户端的网络模块设计与服务器类似,只是不同于服务器多个连接,客户端仅有收发两个线程。

(三)对局系统的实现
系统整体采用mvc设计模式,便于降低代码耦合性,有利于组件的重用。

如图2所示。

客户端的ChessView等类继承自Qt的Widget,用来与用户交互。

服务器的ChessField类是棋盘模型,棋规判定、胜负判定等业务逻辑在此类中实现。

这个类聚合了抽象类ChessPiece的不同实现,对应不同种类的棋子。

每个子类有各自的边界判断,移动判断函数。

控制器为上文提到的UserConnection类。

(四)座位管理系统的实现
每一个UserConnection中都有一个相同的RoomManager类指针指向一个共享的RoomManager对象,程序截图如图3所示。

可以看到:该类提供了新建房间、加入房间、观看对局等接口,接收的参数是User,用户连接使用时通过传入this指针就可以实现操作。

存储的数据结构使用了键值对(QMap),其结果如图4所示。

对于一个没有对手的“单人房间”,在room_struct当中存放两个nullptr,这时键UserConnection代表房间,作为房间句柄。

“加入比赛”时,为新加入的人也创建一个键值对,即一个“房间”分配两个空间,这样可以更加高效地定位棋盘模型和对手。

调用roomInfo函数不直接返回该数据结构,而是将冗余的第二份房间信息去除,这样得到的QMap的键UserConnection 可以唯一标识一个房间,作为房间句柄使用。

程序截图如图5所示。

这个类同时也维护用户列表,提供重复登陆判断等接口。

三、系统测试
(一)系统调试和难点分析
1. 并发过程中数据一致性问题
问题描述:调试时,程序运行过程中出现非预期的不合理结果。

比如修改某些数据不生效等情况。

原因:roommanager共享对象在多线程环境下有可能同时被多个线程同时写入,进而出现数据一致性问题。

解决方案:roommanager等多线程共享对象,在需要写入时需要用Qt提供的QMutex互斥锁对给资源加锁[10],在修改完成后釋放互斥锁,在此过程中其他的线程将不能进行修改。

2. 客户端连接释放问题
问题描述:调试过程中,客户端程序突然终止连接后,服务器程序常常无响应或是异常终止。

而作为一个服务器,因为某客户端的某些行为导致崩溃是不能接受的。

原因:C++语言是不同于java一类具有垃圾回收器的编程语言,需要手动管理内存及相应的资源。

在客户端中断连接以后,必须要结束为该用户创建的连接线程,释放内存,清除所有此用户的对局状态信息,同时从已登陆用户列表中移除该用户。

解决方案:必须找到合理的方式释放资源。

在线程创建过程中将RecvThread类的die信号与TCPConnection类的析构方法连接。

当检测到客户端连接中断后,RecvThread发出die信号。

这时,首先析构TCPConnection对象,在~TCPConnection()中析构UserConnection类的对象。

为了清除所有此用户的对局状态信息,同时从已登陆用户列表中移除该用户:UserConnection类的析构方法调用RoomManager::logoff,此函数释放所有包含UserConnection的对局。

并在users:QSet中删除这个User,从而实现将该用户标记为非登陆状态。

完成以上这些之后,关闭TCPSendThread线程,由于此线程处于阻塞状态(等待网络消息的生产者生产消息),故不能直接结束线程。

使用Qt提供的terminate()函数强制终止线程有会带来一系列的问题,比如影响到其他正常运行的线程。

故设计了如图6所示的interrupt方法。

最后,需要终止TCPRecvThread。

(二)系统运行界面
图7为系统登录界面,正确输入用户名和密码后,点击登录按钮,可以进入到选座系统界面,如图8所示。

选座完成后,点击建立房间,进入对战模式,如图9所示。

四、结束语
本文给出了使用C++和Qt技术进行象棋棋牌室游戏软件的设计方案,详细介绍了系统各部分的功能原理、运行流程及具体的实现方案,最后对系统各个功能进行测试。

本设计案例重在巩固学生对理论知识的理解,让学生明白只有通过实践才能验证所学所得、才能熟练掌握课程知识。

在实践中多层次全方位的学习知识、在实践中加深对所学知识的印象,锻炼软件开发的能力,以及对系统调试和解决实际问题的能力。

相关文档
最新文档