ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:45.67KB ,
资源ID:16672509      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/16672509.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(使用GTK+库实现一个扫雷程序文档格式.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

使用GTK+库实现一个扫雷程序文档格式.docx

1、13 gtk_widget_show_all(window);14 gtk_main();15 return 0;16 对代码进行简单说明:01 控制流程gtk_init,gtk_main是控制流程函数,gtk_init是建立GTK程序的初始化环境,gtk_init可以接受命令行参数。而gtk_main函数则开始GTK函数的主循环。此外,还有一gtk_main_quit函数,它的功能是退出gtk环境。02 控件和控件管理这部分的函数和数据结构占据了GTK+库的大部分。GtkWidget就是控件的数据结构,这个程序里有两个控件,window和label,window是程序的主窗口控件,而labe

2、l是附着于程序窗口上一个显示文字内容(这里文字内容是“GTK+”)的控件。gtk_window_new将创建一个窗口,它接受参数以生成不同类型的窗口,这里的参数是GTK_WINDOW_TOPLEVEL。gtk_label_new将生成一个带有文字内容的控件。gtk_widget_show_all用来显示窗口。关于窗口控件,它们之间有一个树型关系,即顶层窗口包含子窗口,子窗口又可以包含新的子窗口。子窗口只有一个上层窗口作为,但可以包含多个子窗口(树型关系)。在这个程序里,gtk_container_add即把label作为子窗口添加到window窗口中。03 事件处理关于事件,包含有:鼠标的点击

3、、键盘的输入。事件处理函数负责把这些事件绑定到控件上,并指定事件发生时的处理函数。在这个程序里,g_signal_connect函数把delete_event事件绑定到window控件上,并且指明了当发生这一件事件时,调用gtk_main_quit函数。即退出GTK+环境。总结:GTK+程序流程1 初始化环境在main函数的一开始处调用gtk_init函数,标志着进入GTK+环境。2 生成控件使用各种可以创建控件的函数(*_widget_new,比如gtk_window_new,gtk_label_new)创建控件。3 关联各个控件间关系即使用gtk_container_add函数将各个控件组

4、织成“一棵树”。4 绑定各种事件到控件上使用g_signal_connect函数把事件及发生事件时调用的函数绑定到控件上。5 显示根窗口使用gtk_widget_show函数显示根窗口控件。6 启动GTK+主函数调用gtk_main函数进入事件处理循环。7 关联根窗口退出事件使用 g_signal_connect(G_OBJECT(window), gtk_main_quit, NULL);函数将退出事件绑定到跟窗口以退出GTK环境,释放资源。2 事件处理与界面布局2.1 事件处理所谓的事件 (event), 在这里用来描述执行过程中所遇到的状况。 键盘输入,鼠标的移动,计时通知等等,皆是硬件

5、的事件.。大家很容易就能想象事件发生的原因跟过程。来自软件本身产生的事件则不这么明确. 例如一个 button 被按下的事件,窗口大小被调整的事件, 画面需要更新的重绘事件, 档案内容被更新的事件 许多都是依系统的设计而被定义出来的。在 GTK 中在每个 widget 上都可能会发生好几种事件。事实上,在程序设计时多半都是在写如何处理各种事件。这些事件处理的 function (event handler) 以 g_signal_connect() 注册到指定的 widget 中。让指定的 object 在发生 name 事件时呼叫 func (可指定自己的额外参数 func_data):gu

6、int g_signal_connect (GObject *object, const gchar *name, GCallback func, gpointer func_data);返回值 代表这个 signal connection 的 id。object 要处理事件的对象。我们用的widget 可以通过 G_OBJECT() 转换, 如G_OBJECT(window).name 事件的名称, 请参考 GTK 文件上的列表.func 当事件发生后会呼叫这个 callback function.func_data 提供给 func 的额外数据. 一般不需提供而使用 NULL.callba

7、ck function的参数和返回值格式最正确的格式可以在 GTK 的参考手册中各个 widget 的Signal Prototypes列表里查到。例如GtkButton下的几个:clicked void user_function(GtkButton *button, gpointer user_data);enterleave要在 button 被按下时执行某个 function 我们可以 connect 那个 function 到 button 的 事件. 用:void on_clicked() g_print(Hello world!n. g_signal_connect(G_OBJE

8、CT(button), G_CALLBACK(on_click), NULL);在自己定义的callback function中传回TRUE表示这个事件已经被处理完毕。传回FALSE则GTK会继续找是否还有其它合适的 event handler。2.2 界面布局GTK 中用 box 来排放 widget 可说是最常见也最容易写的. 一个 box 的功能主要是容纳以及计算里面 widget 的大小, 最后决定自己要占用的空间大小. Box 又分为 HBox 跟 VBox. HBox 把里面的 widget 以左右横排, vbox 则上下直排.hbox 跟 vbox 的建立跟基本的 widget

9、一样, 各为 gtk_hbox_new() 和 gtk_vbox_new(), 不过需要提供两个参数: homogeneous (每个格子等宽/等高) 及 spacing (格子之间的距离, 单位为 pixel).GtkWidget *box1;GtkWidget *box2;box1=gtk_hbox_new(FALSE, 4); /* 不等宽, 间隔 4px */box2=gtk_vbox_new(TRUE, 0); /* 等高, 无间隔 (0px) */将 widget 放入 box 里可以使用 gtk_box_pack_start() 或是 gtk_box_pack_end() 两个

10、function. gtk_box_pack_start() 会将 widget 依从左到右 (hbox) 或从上到下 (vbox) 的顺序找位置存放, gtk_box_pack_end() 则是倒着放过来. 3 扫雷程序程序中出现的数据类型以及函数请自行参阅GTK+文档。 功能分析在挖雷的过程中,玩家可以掀开或标记某个格子,假如掀开的格子有地雷,游戏结束。否则显示周围有多少地雷。游戏中也应该提供一个数字,避免让玩家需要计算剩下多少地雷。当所有不含地雷的格子都被掀开后,恭喜玩家并结束游戏,此外也需要计算游戏时间,以反映玩家对游戏的熟练程度。至于其它功能如提供玩家改变地雷数目,格子数目等等,目前

11、不考虑包含。 具体实现格子:struct block gint count; /* 周围有多少地雷 */ gboolean mine; /* 是否藏有地雷 */ gboolean marked; /* 是否被标记过 */ gboolean opened; /* 是否已被掀开 */ GtkWidget *button;雷区:static struct block *map; /* 地雷区资料 */static gint width=10; /* 地雷区宽度 */static gint height=10; /* 地雷区高度 */static gint mines=20; /* 地雷数量 */布雷

12、:/* 以随机数安置地雷 */gint size=width*height;gint i=0;while(i0)/* 左上 */ if(col0) mapindex-width-1.count+;/* 正上 */ mapindex-width.count+;/* 右上 */ if(col0) mapindex-1.count+;/* 右 */ if(colwidth-1) mapindex+1.count+; if(row0) mapindex+width-1.count+;/* 正下 */ mapindex+width.count+;/* 右下 */ if(colwidth-1) mapin

13、dex+width+1.count+; i+;全局数据:static GtkWidget *mine_label; /* 显示剩余地雷数 */static GtkWidget *time_label; /* 显示游戏时间 */static gint button_size=16; /* button 大小 */设置界面及关联事件处理函数:GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; gint i, j index; vbox=gtk_vbox_new(FALSE, 0); /* 存放 label 的第一个 hbox */ hbox=gt

14、k_hbox_new(FALSE, 0); label=gtk_label_new(Mines: gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 4); mine_label=gtk_label_new(0 gtk_box_pack_start(GTK_BOX(hbox), mine_label, FALSE, FALSE, 2);Time: time_label=gtk_label_new( gtk_box_pack_start(GTK_BOX(hbox), time_label, gtk_widget_show_all(hbox

15、); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* width x height 个 button 的格子 */ for(i=0, index=0; iheight; i+) for(j=0; jbutton)14 case 1: /* 鼠标左键 */15 /* 从 index 算出发生事件格子的行列 */16 row=index/width;17 col=index%width;18 /* 掀开格子 */19 open_block(col, row);20 break;21 case 2: /* 鼠标中键 */22

16、break;23 case 3: /* 鼠标右键 */24 /* 已掀开的格子不做记号 */25 if(mapindex.opened=TRUE)26 break;27 /* 原来有记号则消掉, 沒有则画上记号 */28 if(mapindex.marked!=TRUE)29 mapindex.marked=TRUE;30 gtk_button_set_label(31 GTK_BUTTON(widget), 32 marked_count+;33 else34 mapindex.marked=FALSE;35 gtk_button_set_label(36 GTK_BUTTON(widget

17、), 37 marked_count-;38 39 /* 显示新的地雷数 */40 g_snprintf(buf, 4, %d41 MAX(0, mines-marked_count);42 gtk_label_set_text(GTK_LABEL(mine_label), buf);43 4445 return TRUE;46 说明:第09行检查游戏是否已经结束。若游戏已结束,玩家按下button也没有反映。第11行将callback接受的data换成数字的index来使用。这个index也就是在g_signal_connect()中每个button自己的index。第19行使用了open_

18、block()來掀开指定的格子。 open_block()是接下來要说明的函数。第45行传回TRUE表示這个事件已经被处理完毕, GTK不需要再寻找其他callback function处理。open_block()特别说明:當玩家掀开一块周围完全沒有地雷的格子时 (count=0), 可以安全的掀开周围的八个格子. 若这八个格子之中又有遇到相同的情況则那个格子周围又可以继续掀开. 因此我们准备了open_block 這个重复呼叫自己的 recursive function, 并由它來检查遊戏是否结束.01 void open_block(gint x, gint y)02 03 gint i

19、ndex;04 GtkWidget *button;0506 index=x+y*width;0708 if(game_over=TRUE | mapindex.marked=TRUE)09 return; /* 游戏已结束或防止玩家误翻有记号的格子 */11 button=mapindex.button;12 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),13 TRUE); /* 改变 button 状态为按下 */1415 if(mapindex.opened=TRUE) /* 掀开的格子保持按下状态即可 */16 retur

20、n;1718 mapindex.opened=TRUE; /* 格子状态为掀开 */1920 if(mapindex.mine=TRUE) /* 若藏有地雷 */21 gtk_button_set_label(GTK_BUTTON(button), *22 gameover(FALSE); /* 踩到地雷游戏結束 */23 return;24 2526 if(mapindex.count0) /* 若周围有地雷 */27 gchar buf2;28 g_snprintf(buf, 2, , mapindex.count);29 gtk_button_set_label(GTK_BUTTON(b

21、utton), buf);30 3132 opened_count+; /* 已掀开的格子又多了一个 */3334 if(opened_count+mines=width*height)35 gameover(TRUE); /* 所有空地都被翻完時游戏结束 */36 return;37 3839 if(mapindex.count=0) /* 若周围沒有地雷 */40 /* 掀开周围格子 */41 if(y42 if(x0) open_block(x-1, y-1);43 open_block(x, y-1);44 if(x0) open_block(x-1, y);47 if(xwidth-

22、1) open_block(x+1, y);48 if(y0) open_block(x-1, y+1);50 open_block(x, y+1);51 if(xwidth-1) open_block(x+1, y+1);52 53 54 第 12,13 行使用了 GtkToggleButton 的 gtk_toggle_button_set_active() 將 button 設定成按下的状态。 TRUE 是按下, FALSE 则是未按下的状态。第 21 行以 gtk_button_set_label() 来改变 button 上显示的文字。第 28 行的 g_snprintf() 是 GLIB 版本的 snprintf(), 确保在各平台上都可以使用。第 3953 行是在掀开周围沒有地雷 (count=0) 的格子時自动將四周格子也加以掀开的部份. 周围的每個格子都要先检查是否超出地雷区范围。函数

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1