# QtSnake **Repository Path**: haozixu/QtSnake ## Basic Information - **Project Name**: QtSnake - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-26 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Qt贪吃蛇作业 ## 架构设计 ### 主要类与关系 #### Game 继承自QObject,为主要的游戏对象,负责保存游戏状态以及状态控制。 #### GameView 继承自QWidget,主游戏视图,用于将游戏画面显示在窗体上,同时处理用户的输入。GameView类为Game类的友元类,持有Game对象的指针。 #### MainWindow 继承自QMainWindow,窗体主界面。持有Game对象与GameView对象。 ### 类的详细信息 #### Game + 保存地图大小(可供扩展) + 保存蛇身、障碍物与食物坐标 + 蛇当前的前进方向,上一前进方向,是否在生长 + 游戏状态、时长、得分等 + 设置定时器进行游戏更新 + 发送状态信号 #### GameView + 根据Game状态将Game中的元素绘制在图形组件上 + 接收游戏状态信号并进行图形更新绘制 + 处理键盘输入并反馈到Game状态 + 响应组件尺寸变化 #### MainWindow + 对Game和GameView对象具有所有权 + 工具栏、菜单栏、按钮等ui组件 + 接收游戏状态信号并对组件状态进行更新 ### 信号与槽 Game对象设置如下两个信号: + gameStateChanged + gameUpdate 当游戏状态改变时,发送gameStateChanged信号。 当定时器事件发生时,发送gameUpdate信号。 GameView和MainWindow均实现对以上两个信号进行响应的槽: + onGameStateChanged + onGameUpdate GameView对信号的相应只需调用update()对图形界面进行更新即可,其重写的paintEvent事件会根据Game状态动态进行绘制。MainWindow的onGameStateChanged会根据新的游戏状态设置按钮等组件是否可用(enabled),而其onGameUpdate主要负责更新需要实时显示的游戏状态组件(如游戏时间)。 ### 其他 #### 游戏状态信息 蛇身坐标信息采用了std::deque进行储存。更新时向队列头部加入蛇头的新坐标,并移除队列尾部坐标。当蛇吃到食物处于生长状态时,额外向队列头部加入生长的新蛇头坐标。 障碍物坐标使用std::set进行保存。 #### 游戏状态保存与加载 Game类实现将自身游戏状态转为JSON对象并保存,同时实现JSON对象文件的加载。 #### 游戏功能 贪吃蛇被禁止原地调头,当键盘接受的方向与蛇当前前进方向相反时不予响应。通常情况下新的食物坐标会距离当前蛇的位置有一定距离。按下空格键可以开始游戏/暂停游戏/继续游戏。 ## 界面设计 ### 初始状态 ![初始界面](screenshots/initial.png) 主界面从上之下依次为:菜单栏、工具栏、游戏信息栏、游戏主视图、状态控制按钮栏。菜单栏和工具栏分别为标准的`QMenuBar`和`QToolBar`组件,游戏信息栏为置入了多个`QLabel`的水平布局。状态控制按钮栏使用了两个水平布局,内容放置`QPushButton`。由于开始游戏按钮和重新开始按钮不会同时可用,所以两个按钮共享一个`QPushButton`,根据游戏状态的不同按钮显示的文字和触发动作都会相应变化。暂停游戏和继续游戏也进行了类似的处理。 初始状态下蛇位于游戏界面中央,红色的为蛇头,灰色的为蛇身,默认方向朝右。请不要吐槽配色,这是我随手选的。粉色上面带点绿的东西是食物(果实),也是我自己随便画的。窗口的绿色应用图标亦是如此。 ### 暂停状态 ![暂停界面](screenshots/paused.png) 图中橙色格子为手动放置的障碍物,其余元素同上。 ### 结束状态 ![结束界面](screenshots/gameover.png)