简单五子棋Web项目报告
课 程 | Web应用程序设计 | 项目名称 | 简单双人五子棋对战 | 成绩 | ||||||||||
专业班级 | XXX | 组别 | 无 | 学号 | XXX | 指导教师 | XXX | |||||||
姓 名 | XXX | 同组人姓名 | 无 | 完成日期 | XXX |
功能描述
1.用户的注册及登录功能
玩家可以在完成游戏账户的注册,注册完成后,此账号可以用来进行登录。
2.玩家匹配功能
玩家登录之后,可以进入游戏大厅(人人对战),挑战在线的玩家,对方同意之后,双方即可进入对战界面。该游戏默认黑子是先手,在进入游戏页面的同时,随机分配黑白子。
3.玩家对战功能
玩家点击开始游戏,表示已准备,对战双方都准备之后,方可进行对战。屏幕上方会提示由谁落子,玩家交替落子,最后由系统判断输赢。
4.局内聊天功能
玩家在对战的同时,可以进行局内聊天。
5.认输功能
如果玩家想认输,点击认输按钮,即可进行结算,并退出游戏。
- 前端页面设计
1.欢迎页面设计
选中状态:
点击登录按钮,弹出登录界面:
点击注册按钮,弹出注册界面:
2.游戏大厅页面设计
点击匹配按钮,进行匹配:
用户收到挑战时:
3.对战页面设计
战败界面:
战胜界面:
- 后端接口的设计
- 玩家相关的接口
登录接口(“/user/login”),请求方式为POST,接口参数为chessUser,HttpSession,前端请求需要传入的参数是用户id和用户密码password。这里有一个判断,当这个欢迎页面加载的时候,会首先判断用户是否已经登录。这里查询数据库的相关操作,使用了框架Mybatis-plus,目的是简化代码量。
登录成功后,将用户的登录信息存储在会话对象中,并且,为了后面游戏玩家列表数据的获取,还需要把登录信息存储进applicationContext对象中。这里单独用了一个addUserList方法封装。
注册接口(“/user/registry”),请求方式为POST,接口参数为chessUser和HttpSession.前端传入的参数是用户注册ID和用户注册密码,因为我将玩家数据表的ID字段设置为了主键,因此在这个接口中,需要判断用户注册的ID是否已经在数据表中存在了,并返回提示信息。
注销登录接口(“/user/logout”),请求方式为POST,接口参数为chessUser和HttpSession,前端传入的是已登录用户ID,接口根据这个ID去session对象中移除记录,并且同时要在applicationContext中保存的用户列表List移除记录。
获取已登录用户ID列表(“/user/getList”),请求方式是Get,接口参数为HttpSession,前端请求无参数。
2.对战相关的接口
准备游戏接口(“/fight/start/”),该接口的意思是,玩家在游戏界面点击开始游戏,表示自己进入已准备状态,需要等待对方进入准备状态,当双方进入装备状态,即可激活棋盘,开始下棋。
请求方式是Post,接口参数为Map<String,Boolean> map和HttpSession,前端传入的参数为isQuery,类型是boolean,如果isQuery为false,表示该请求是玩家点击开始游戏按钮触发的,表示玩家是准备状态;如果isQuery为true,表示是玩家轮询对方是否已经准备好的请求。
玩家匹配接口(“/fight/match”),请求方式为Post,接口参数为Map<String,String>和HttpSession,前端传入的参数有enemyID和userID。
当前端传入enemyID和userID时,说明是玩家发起匹配的请求,此时将玩家的匹配信息放入applicationContext中;若前端未传入参数,说明是玩家轮询是否有人挑战他的请求,此时就是取出applicationContext里的信息,并返回查询结果。如果双方都同意匹配,则直接跳转进游戏界面。
玩家响应匹配接口(“/fight/response”),请求方式是Post,接口参数为Map<String,String>和HttpSession,前端传入的参数有三种情况,分别对应三种情况:
如果传入的参数是userID和enemyID,说明这是玩家对用户发起匹配的成功响应,这时开始随机分配黑白子,然后进入游戏界面;如果没有收到任何数据,表示这是玩家在轮询对方是否对自己发送的匹配请求进行相应;如果收到的数据是“refuse”,表示这是玩家拒绝了对方的匹配请求,玩家会清空applicationContext对象里面保存的匹配信息,目的是:当对方轮询时,发现信息被清空就停止轮询,并显示被拒绝的信息。
加载游戏玩家信息接口(“/fight/getMsg”),请求方式为Post,接口参数为Chessmessage和HttpSession,前端无需传入任何参数。这个接口完成的功能是在加载游戏界面时,显示对战双方的ID以及所执棋子的颜色。
上传以及获取棋子信息接口(“/fight/fighting”),请求方式为Post,接口参数为ChessMessage和HttpSession,前端传入的参数有两种情况:如果前端传入的参数是id、color和position,那么表示这个请求是玩家在落完子之后上传的棋子的信息;如果前端请求时没有携带任何有效数据,说明这是玩家在轮询对方的落子信息。
这里我直接将落子信息封装成ChessMessage,存储的时候直接用了key=”position”,value = chessMessage,这样其实每一次有新的棋子信息,就会覆盖原来的value。在获取信息的时候,判断了一下chessMessage里面的id成员变量是否和session里面的userID一致,这样是为了避免玩家获取自己的棋子信息。
玩家认输接口(“/fight/giveup”),请求方式是Post,接口参数为ChessMessage和HttpSession,前端传入的参数也有两种方式:如果前端传入的是玩家id,说明这是玩家点击认输按钮触发的请求,此时将玩家认输信息保存在applicationContext中;如果前端未传入任何数据,说明这是玩家轮询对方是否认输,此时返回轮询结果。
局内聊天接口(“/fight/chat”),请求方式为Post,接口参数为ChessMessage和HttpSession,前端传入的参数有两种:如果前端传入的参数为玩家id和消息内容chat,说明是玩家发送了聊天消息,此时将玩家聊天内容存储在applicationContext中;如果前端没有传入任何数据,说明是轮询对方的消息,这里要区别新旧消息,我是直接用的老师的方法,在返回消息列表之前,遍历消息,如果消息字串中包含”*”字符,说明是旧消息,就不获取,同时,获取之后,也要在新消息字符串中加入字符”*”,表示已读。最后返回新消息列表。
判断输赢接口(“/fight/win”),请求方式为Post,接口参数为ChessMessage和HttpSession,前端的传入的参数也分两种:如果传入的参数为玩家id,说明玩家赢了棋局,此时在applicationContext保存该信息;如果前端没有传入任何数据,说明这是玩家在轮询对方是否赢得棋局,此时查询applicationContext中的相关数据,返回结果。
遇到的问题及解决方法
1.访问静态资源报404: 翻了一下SpringBoot的官方文档,SpringBoot静态资源的默认路径 是 classpath:/static 和 classpath:/public 和 classpath:/resources 和 classpath:/META-INF/resources,默认将/**所有访问映射到以下目录。
如果想修改默认配置,可以自己写一个MVC配置类去替代默认配置,一开始我也是这样做的,写了一个配置类:
也可以直接在yml里面配置:spring: mvc: static-path-pattern: /xxxx/**。
后来我发现上次没访问到是因为Maven项目没及时更新,静态资源没有在target目录生成,不是路径的问题,于是我把这个配置类删除了,用默认配置就够了。
我还经常遇到的坑就是:浏览器的自动缓存机制。
这个机制每次让我错的都摸不着头脑,就是明明修改了CSS样式或者JS代码,但是不生效,我打开F12查看源码才知道,浏览器启用了缓存的页面,导致我的网页没更新,于是我就把浏览器缓存关了。
JS动态渲染标签的获取,一开始我忘了动态渲染的元素绑定事件要用on(),导致我一直没获取到玩家列表项。后面查了博客,发现要用on,并且on前面选择器里面的元素必须是非动态渲染的元素,不然依旧获取不到,让我郁闷的是,我在这里卡了几个小时,最后终于成功了。但是这里依然存在BUG,这代码只适用于只有两个用户的情况。
Mybatis-Plus的不熟悉导致项目报错,因为这个框架会给开发者自动生成SQL语句,而我只要调用它封装好的方法就行了,结果我的实体类和数据库表的名字不匹配,生成的语句有问题,导致找不到数据表,或者一些对象属性的不匹配,我只好全部修改了实体类名字和成员变量,最后不报错了
实现局内聊天功能,我测试的时候,发现白子玩家一直获取不到对方发送的消息,我就一直调试检查我的chat接口的代码,发现根本没有问题,然后我也检查了前端JS代码,也没看出问题,最后我只好重构项目(有时候不能不相信一些玄学),最后还是不行,折腾了好久,终于在某天下午,我发现我前端代码给enemyID赋值的时候赋错了,然后这个变量是作为chat接口的参数传进去的,导致白子玩家把对方发的消息当做了自己发的消息,就一直不获取,所以导致白子玩家一直接收不到对方的消息。