Linux下的扫雷


基于:C语言,GTK+2.0,Sqlite3

使用工具:VMware,MobaXterm,Sublime Text3

一丶下载及运行

下载链接:https://pan.baidu.com/s/1L5Z-S6Zy08dUVv6txAhB0g?pwd=qi5h
提取码:qi5h

若只进行游玩,只需下载“扫雷”文件,并安装mysql运行库

打开Linux系统,打开终端,输入 sudo apt-get install libmysqlclient-dev 回车

然后将下载的“扫雷”文件于Linux内打开即可

若无法将文件从Windows拖入Linux,则输入以下指令

sudo apt-get autoremove open-vm-tools
sudo apt-get install open-vm-tools-desktop

然后重启虚拟机,即可将文件拖入Ubuntu中

二丶功能说明

1.游戏主界面:

2.登陆/注册模块:

登陆功能:

输入用户名和密码,点击登陆,将于数据库查询用户名是否存在

若不存在,则弹窗消息(该用户不存在!)

若存在,则检查输入框密码与该用户密码是否相同,

若相同则登陆成功

否则,弹窗消息(登陆失败!)

注册功能:

输入用户名和密码,点击注册,将于数据库查询用户名是否存在

若存在,则弹窗消息(该用户已存在!)

若不在,则将输入框用户名和密码写入数据库

登陆成功后,主界面:

“登陆”变为“注销”,按下注销后回到未登录状态

“游客模式”更改为“开始游戏”

2.游戏模块:

点击“游客模式/开始游戏”,弹出游戏界面

若未点击到地雷,则显示该处3×3包围范围内的地雷数量:

若点击到空白处:向周围扩散触发按钮,直至遇到数字

若所有非地雷单元均被点开,则游戏胜利,弹出胜利消息框

上传按钮:

若未登陆,则为灰,不可触发,

若已登陆,则记录(用户名,本局游戏地雷数,完成游戏所用时间,地图大小,地雷量%)

并上传至数据库,表gamerank

重玩按钮:重新载入游戏界面

返回按钮:返回主菜单

若点中地雷,则显示所有地雷位置,并弹窗(游戏结束!)

点击确定退出游戏界面,返回主菜单

3.游戏设置界面

可更改“游戏地图大小”“炸弹数量百分比(非精确)”

原理与登陆注册相同,不过并不写入数据库

而是更改两个加载游戏界面时会读取的全局变量mapsize,boomnumber。

如:10×10:1%(左)  50×50:50%(右)

4.排行榜:

点击后弹出游戏胜利排行榜

读取数据库中,由已登录的胜利界面上传的游戏数据,按照排雷数量排序

(注:为防止数据过多仅有完成游戏的游戏数据可上传,即仅胜利数据)

(另:图中负数时间与0时间,均为测试数据)

5.退出游戏

点击后结束进程。

 

 

三丶实现思路

登陆/注册模块:

在登陆按钮的信号函数中调用此函数,参数为两个输入框中的内容

注册同理,注册按钮的信号函数中调用此函数,参数为两个输入框中的内容

游戏模块:

1.地雷数:

首先,定义两个整数变量mapsize和gamelevel

其中,mapsize代表地图大小,gamelevel代表游戏难度

再定义一个二维数组A,遍历A并赋值A中的每一个元素一个随机数

该随机数以当前系统时间为种子,并余以100,即被限制在(0~99)中

由于扫雷游戏中,一个非雷方框周围最多有8个雷,即下图(红色代表有雷)

则可能的数字有0(空白),1,2,3,4,5,6,7,8

没有9,则可使用9代表地雷

如果数组A中,元素随机出的数小于gamelevel,则将该元素置为9,否则,置为0

如图,代表gamelevel的数越大,则有越多的元素被置为9(地雷)

即实现了游戏难度等级越大,游戏中的地雷越多

输出该数组A,并适当地排列,即可得到一张仅有0(非雷)和9(地雷)组成的游戏地图

2. 显示周围地雷数量:

很简单,遍历数组A中的所有元素,判断该元素周围所有元素是否为9

若是,则该元素的值+1

输出数组A:

则地雷地图的底层功能已经实现

3. 图形界面的实现:

3.1地雷按钮

创建一个GtkWidget的二维数组B

使用gtk_toggle_button控件实现按下按钮后不回弹的效果

遍历数组B,并给每一个元素赋值gtk_toggle_button

使用gtk_widget_set_sensitive防止再次点击回弹按钮

所有非空按钮信号函数赋为onclick,如下

点击按钮,遍历数组B,取得该被点按钮在数组中的坐标(n,m),传入change()函数中

Change函数的功能为:

当点击按钮时,获取数组A表上坐标为(n,m)元素的值

若该值不为9,则改变数组B中(n,m)位置按钮的文本为该值

其中该值为0时,文本应为空(“”)

若该值为9,则代表点击到地雷,改变该位置按钮文本为“X”,弹出窗口,结束游戏

如此,则可实现数组B与数组A一一对应,用数组A操控数组B。具体代码如下:

4. 空白展开功能的实现:

当点击空白时,理应将周围的空白一起显露

思路为:当点击空白时,遍历该空白按钮周围上下左右4个位置的值

若为0,则递归那个值为0的位置,如此递归下去,直至所有空白都递归

另外,虽只递归周围的0位,但也要将本0位周围的非0位按钮触发,又0位周围必无地雷

即可实现以数字为空白区域边缘的效果

如下图:

函数名为void blank(int n,int m),(n,m)由按键的信号函数提供,同上change()

若周围有值为0,则再次调用函数

如点击位为(n,m),传入blank(n,m),判断出(n+1,m)位为0

则再次调用blank(n+1,m),以此类推,即可实现空白展开

代码如下:

5. 判断胜利:

当场上所有非地雷按钮均被触发时,则为胜利

思路:标记每一个被点击或被递归的按钮,以其值置为10标记为已点击,如上图blank中

其中,mapboom即为本文中的数组A

然后,每次点击或递归时,执行update()函数

效果为,遍历当前数组A中的值,若数组A中不存在小于9的数(0-8)

则代表所有非地雷按钮均已触发,则弹出“胜利窗口”

6. 规避递归错误

需要注意,当递归到数组A的边缘时,如(0,0)位,明显(0-1,0)位不存在

此时无法判断,程序会崩溃,则需要在数组外围预置一组数据,将该数据置为10

此时输出如图:

不规则是因为10位两位,与个位无法对齐

大于10是因为该位置参与地雷数的判断,加上了周围的地雷数,不影响判剩条件

7. 游戏选项的实现

在最开始定义了两个整型参数mapsize和gamelevel;

每次生成游戏界面会调用这两个参数,只需将其设置为全局变量

再通过游戏界面和交互按钮,更改这两个参数

即可实现自定义“地图大小”和“难度等级”

由于在规避递归错误时,预留了2行和2列

则用户更改的mapsize和实际的mapsize须有2的差值,来实现图形上的游戏地图大小控制

8. 胜利界面/游戏结束界面

游戏胜利时,弹出胜利界面

若已登录,即iflogin ==1时,则上传按钮为可用,否则不可用,原理同游戏按钮

重新游玩则是销毁游戏界面并重新初始化并显示游戏界面,略

返回主菜单,略

游戏结束界面,略

9. 游戏地图按钮的排列

说完基本逻辑,说说图形的实现:

首先,游戏界面窗口随地图大小改变而改变

同时,表格布局与按钮数相同

批量对按钮进行布局和信号函数的赋值

如此,即可实现按钮的自动排列

排行榜的实现:

胜利界面的上传有

其中,

时间为:“弹出胜利界面时的系统时间”减去“打开游戏界面时系统时间”

即为所消耗的时间

gamepoint为排雷数量,在弹出胜利界面时,遍历数组A中值为9的元素个数即可得到

Name,mapsize,gamelevel等前文已有说明,不再赘述

排行榜:

数据库中所有数据按照排雷数降序排列,则有

将读取的RankList赋给一个字符指针数组P,其长度为行r乘以列c

排除无效第一行无效数据,则i从5开始依次赋给P

列出数据:

每一次gtk_clist_append,只能赋p[0]-p[5]的数据

则每一次赋值后,p内数据前移5,如下图,即可实现数据更新

需注意,需在数组尾部预留5个有数据的空间,否则将超出数组空间,程序将崩溃

四丶待优化

  1. 图形界面过于简陋,未美化
  2. 胜利界面信息过少,可添加排雷数,使用时间等信息
  3. 技术原因,暂无法实现右键标记地雷
  4. 代码性能低,算法未优化,许多遍历,应该时可以优化的
  5. 上传数据只能本地,不可云同步,后面有机会我将数据库上传至我的云服务器并连接,实现云同步排行榜

更新日志:

2023/9/14

更换数据库为mysql,重写登陆/注册,上传,排行榜部分,现在可以云同步用户账号和用户游戏数据


, ,

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

您可以选择

后再评论