MATLAB的GUI小游戏:你话我猜

  使用MATLAB中的GUI设计一个小游戏——你话我猜,最终效果如图所示:
主界面
  这是主界面,有四个选项,单击文字前面的图标即可跳转至子界面,如图所示:
子界面
  这是子界面,有3个选项,单击Start倒计时开始,单击Right则答对个数+1,单击Next则调至下一题,直到倒计时为0。

一、创建GUI

  打开MATLAB(本游戏编译环境为2014a),选择HOME->New->GUI,在弹出的窗口中选择Blank GUI,点击OK,即可创建空白GUI。
新建GUI
选择空白GUI
  将新建的GUI命名为Games_1。在MATLAB左侧的Current Folder中可以看到有2个文件,一个为Games_1.m和Games_1.jpg,其中.m为MATLAB编译文件,.jpg为GUI文件。右击Games_1.jpg并选择Open in GUIDE即可看到GUI界面。
GUI界面
  左侧为控件栏,拖动至中间空白区域即可创建,中间区域为GUI界面,运行对应的.m文件即可显示界面。

二、在主界面添加背景图片和文字

  MATLAB中在GUI添加背景图片的常用做法是:创建一个坐标系,将图片添加至坐标系中,然后将坐标系的坐标轴设置为不可见,为了将文字写在图片上,可将该坐标系设置为下一层。打开Games_1.m,在function Games_1_OpeningFcn函数中输入代码。   

1
2
3
4
5
6
Games.ax = axes('units','normalized', 'position',[0 0 1 1]); %单位化
uistack(Games.ax,'down'); %把新创建的坐标系在下移一层
Games.img = imread('Games1.jpg'); %打开图片
Games.IH = image(Games.img); % 显示图片
colormap gray % 设置窗口的调色板为灰色
set(Games.ax,'handlevisibility','off','visible','off');%把创建的坐标系句柄设为不可见

  其次,需要在图片上面打印文字。同样的创建一个坐标系并将其坐标轴设置为不可见,利用text()函数即可打印文字。  

1
2
3
4
5
6
7
8
9
Games2.ax=axes('units','normalized','pos',[0 0 1 1]); 
text(0.2,0.9,'游戏环节之你话我猜','fontsize',80) %第一个数横坐标,第二个数纵坐标
text(0.5,0.8,'请任选一项,开始你的表演!','fontsize',40,'color','b')
text(0.1,0.48,'成语','fontsize',80,'color','b')
text(0.1,0.18,'体育','fontsize',80,'color','b')
text(0.66,0.48,'演技王','fontsize',80,'color','b')
text(0.63,0.18,'知识百科','fontsize',80,'color','b')
text(0.80,0.04,'Copyright@cxx','fontsize',30)
set(Games2.ax,'handlevisibility','off','visible','off');

  最终效果如图所示:
最终效果

三、添加控件和控件图标,实现单击图标即可跳转至子界面

3.1 添加控件并实现单击控件跳转至子界面

  右击Games_1.fig,选择open in GUIDE,在控件栏中拖动Push Button至中间空白区域,双击控件即可更改属性。首先设置其Tag属性,将其更改为chengyu,以便区别,并将String属性去掉,不显示控件上的文字,并调整位置和大小,和文字位置相匹配。此时点击Games_1.m或Games_1.fig的运行即可看到控件,在Games_1.m中会出现该控件的回调函数,即function chengyu_Callback(),在GUI界面中右击控件选择View Callbacks中Callback也可跳转至该函数。回调函数用于响应控件时执行的操作。比如新建一个子界面Games_2,并在回调函数中添加run(‘Games_2’),即可实现跳转。
控件

3.2 设置控件的背景图片

  利用set()函数设置对应控件中的CData属性为读取的图片即可实现。设置前需要对图片的像素进行修改,以便能符合控件的大小。

1
2
3
4
5
A=imread('button_start.jpg');   %读取图片  
set(handles.chengyu,'CData',A); %将按钮的背景图片设置成A
set(handles.tiyu,'CData',A);
set(handles.yanjiwang,'CData',A);
set(handles.zhishibaike,'CData',A);

  最终效果如图所示:
最终效果动   

四、子界面的界面设计和控件的回调函数

4.1 子界面的界面设计

  子界面的背景和控件添加方法和主界面类似,为了提高程序的运行效率,可将所有的读取操作放在主界面中执行,即添加全局变量,将图片存储在全局变量中,然后在子界面相应的函数中调用该全局变量。(MATLAB中的全局变量需要先用global声明,每次调用前也需要声明。)然后创建3个edit text控件,分别用于显示词语、倒计时的时间和答对个数。最终效果如图所示:
子界面动

4.2 读取文件并显示

  本游戏的玩法为:点击Start,显示框显示词语同时倒计时开始,当回答正确时点击Right,此时答对个数+1并读取下一个词语,当点击Next时,会直接读取下一个词语,但答对个数不变。在这过程中,倒计时一直在进行,直到倒计时显示为0,当所有词语都显示完后,点击Next和Right均无效。
  所以首先要从excel表中读取词语,为了提高程序运行效率,将读取操作写在主界面的函数中,并设置其为全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Games_1_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
global Time;
global class1_i; global class2_i; global class3_i; global class4_i;
global class1_Len; global class2_Len; global class3_Len; global class4_Len;
global questions1; global questions2; global questions3; global questions4;
class1_Len=length(questions1);class2_Len=length(questions2); %词语变量长度
class3_Len=length(questions3);class4_Len=length(questions4);
class1_i=0;class2_i=0;class3_i=0;class4_i=0; %词语循环变量
Time=90; %倒计时时间
[~,questions1,~] = xlsread('question1.xlsx');%读取表格,并将其数据放在questions1中
[~,questions2,~] = xlsread('question2.xlsx');
[~,questions3,~] = xlsread('question3.xlsx');
[~,questions4,~] = xlsread('question4.xlsx');

4.3 Start控件

  然后在子界面的Start控件的回调函数中编写代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Start_Callback(hObject, eventdata, handles)
set(handles.Question1,'string','');%清空Question1
global Count_Right; global questions1;global class1_i ;global class1_Len;
global Time;
Count_Right=0;
set(handles.Count_Right,'string',0);
class1_i=class1_i+1;
if class1_i >0 && class1_i< class1_Len+1
questions_number = class1_i;
question_select = questions1(questions_number);
set(handles.Question1,'string',question_select);
end
if class1_i>=class1_Len+1
set(handles.Question1,'string','没有了哦~');
end
t=clock; %记录开始的时间
NowSecond=etime(clock,t);
PrSecond=NowSecond;
while NowSecond<=Time;
if ishandle(handles.second)
set(handles.second,'string',num2str(floor(Time-NowSecond)));
end
pause(0.01)
NowSecond=etime(clock,t); %计算当前流逝的时间(秒)
end

  首先清空词语文本中的内容,即用set()函数将Question1文本控件的String属性设置为空。然后初始化答对个数为0。当词语变量大于0且小于词语数组总长度+1的时候,首先选择词语变量值对应的数组索引中的数据,然后在显示出来,当大于词语数组总长度+1的时候,则显示没有。
  第二段是对倒计时的设置。首先将当前时间放在变量t中,clock记录当前的时间,etime()表示现在时间和t之间的差值。当时间差小于指定的倒计时时间时,会一直倒计时。(不加if判断,当倒计时为0时会有警告,不加暂停程序会一直卡住。)

4.4 Right控件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Right_Callback(hObject, eventdata, handles)
set(handles.Question1,'string','');
global questions1;global Count_Right ; global class1_i ;global class1_Len;
Count_Right=Count_Right+1;
set(handles.Count_Right,'string',Count_Right);
class1_i=class1_i+1;
if class1_i >0 && class1_i< class1_Len+1
questions_number = class1_i;
question_select = questions1(questions_number);
set(handles.Question1,'string',question_select);
end
if class1_i>=class1_Len+1
set(handles.Question1,'string','没有了哦~');
end

  单击该控件,则答对个数文本值+1,其余和Start控件类似。

4.5 Next控件

1
2
3
4
5
6
7
8
9
10
11
12
function Next_Question1_Callback(hObject, eventdata, handles)
set(handles.Question1,'string','');
global questions1; global class1_i ;global class1_Len;
class1_i=class1_i+1;
if class1_i >0 && class1_i< class1_Len+1
questions_number = class1_i;
question_select = questions1(questions_number);
set(handles.Question1,'string',question_select);
end
if class1_i>=class1_Len+1
set(handles.Question1,'string','没有了哦~');
end

  单击该控件,词语变量+1,和Start控件第一部分类似。

五、添加游戏背景音乐,当跳转至子界面时停止

1
2
3
[Y,FS]=audioread('Games1.mp3');         %播放歌曲
Song_Current = audioplayer(Y,FS); %存储当前播放的歌曲
play(Song_Current);

  将当前音乐存储在Song_Current变量中,并设置其为全局变量(方便子函数调用)。并且在每次调用子界面时添加stop(Song_Current)以终止音乐。当退出子界面时,需要重新打开该音乐。这是退出界面的回调函数,在GUI界面中,右击空白处可看到该回调函数,即CloseRequestFcn()。  

1
2
3
4
5
6
function figure1_CloseRequestFcn(hObject, eventdata, handles)
global Song_Current;
[Y,FS]=audioread('Games1.mp3'); %播放歌曲
Song_Current = audioplayer(Y,FS); %存储当前播放的歌曲
play(Song_Current);
delete(hObject);

  最后一步删除整个对象以结束。

六、总结

  本游戏整体比较简单,代码共享在这里,你话我猜。还望大佬们指点改进。

  

  

谢谢老板!
-------------本文结束感谢您的阅读给个五星好评吧~~-------------