自制的MATLAB拼圖遊戲GUI界面版詳解(上篇)

圖片展示

摘要:這篇博文在早前本人寫的介紹拼圖遊戲的基礎上推出帶有GUI用戶界面的增強版,這裏將通過上、中、下三篇博文詳細介紹利用MATLAB GUI設計的拼圖遊戲完整實現過程,每篇都會附上相應代碼及解釋。上篇主要講解拼圖遊戲中界面設計與圖片選取功能的詳細實現過程。上篇的要點如下:

點擊跳轉至拼圖遊戲全部文件下載頁


1. 前言

    博主是個樂於分享的人,一直以來也在總結、分享與大家的鼓勵中提升自我,我一直認爲文章反映着作者對於生活的態度,而真正優美的文章是在與讀者交流。早前,博主發佈了第一篇CSDN博客:基於MATLAB的拼圖遊戲設計,其中詳細介紹了簡單的MATLAB拼圖遊戲的設計過程。讓我意外的是,該博文自發布以來受到不少博友的關注,同時有朋友發來私信說該文對初學者幫助較大並希望博主能寫一篇介紹有GUI界面的拼圖遊戲的博文。看到這些博主深受感動,但苦於一直太忙拖了許久。想來如今必須得抽出點時間爲大家寫個帶GUI界面的程序並講述一下了。因爲GUI界面版內容較多,這裏限於篇幅分成了上、中、下連續三篇依次講解。希望本文能給對MATLAB GUI界面設計或小遊戲感興趣的朋友有所啓發。


2. 拼圖遊戲實現的功能

    簡單來說,我們要實現的功能有:

    一、通過點擊文件選擇按鈕,彈出一個圖片文件選擇對話框,可選擇任意圖像文件並將選中的文件絕對路徑顯示在一個文本框中,同時將選中的文件顯示在座標軸中。效果如下:

圖片展示

    二、通過一個彈出式菜單實現對拼圖遊戲難度的選擇,即選擇拼圖的階數,對應的開始遊戲後的拼圖也應能夠分成相應數目的拼圖塊。效果如下:

圖片展示

    三、遊戲開始前或進行中,可以對對應的拼圖塊標識相應的數字作爲提示信息,提示的數字應能夠適應相應的拼圖階數。效果如下:

圖片展示

    四、無論何種階數的拼圖,點擊“開始拼圖”按鈕後,在拼圖區點擊拼圖塊能夠移動拼圖並最終能夠完成遊戲,得到完整的拼好的拼圖。效果如下:

圖片展示

3. 拼圖遊戲GUI界面設計

    MATLAB爲用戶提供了強有力的工具——句柄圖形,方便對圖形的各個方面進行控制。很多時候我們需要一個可以反覆使用的實用函數,這時圖形界面作爲交互方法就顯得更有意義,其中利用GUIDE建立GUI是一種簡單快捷的設計方式。特別是作爲一款小遊戲,一個優美簡潔的界面將爲其增色不少,這節介紹拼圖遊戲GUI的設計思路與界面製作過程。

    作爲這個小項目的開始,我們有必要先新建一個文件夾並命名爲jigsaw_GUI用於保存接下來用到的全部文件。也可事先準備兩張喜歡的圖片放在文件夾下作爲後面拼圖使用。打開MATLAB並用其打開到剛剛新建的文件夾下,在命令行輸入“guide”,在彈出的對話框中點擊“確定”,進入GUI設計界面。

圖片展示

    在GUI設計界面中,從左側的GUI對象選擇區依次拖動控件到中間的GUI佈局區。每佈置好一個控件,爲了美觀和方便需要重新設置一下控件名字及控件上顯示的文字等屬性。如拖動一個靜態文本控件(帶TXT字樣的那個)到佈局區,並雙擊該控件調出屬性檢查器,修改“FontName”字體屬性爲“隸書”、“FontSize”字體大小爲16,、顯示的字符串“String”設置爲“自制簡易拼圖遊戲”,“Tag”(對象名)屬性設置爲“text_title”。

圖片展示

    後面的控件可通過類似的方式進行佈置與修改,爲了方便後面顯示圖片我們需要兩個axes(座標軸)控件,分別命名爲axes_originalaxes_jigsaw用於顯示原始圖片與進行拼圖顯示的圖片。爲了能夠設置拼圖的難易程度,我們添加一個彈出式菜單控件(popupMenu),並在“String”屬性中添加多行字符串,每行字符串低代表一個彈出選項,如下:

圖片展示

    我們要設計的拼圖遊戲的整體佈局如下圖所示:

圖片展示

    通過如下的對象瀏覽器,你就能看到我所添加的控件層次及命名情況了,大家可以照着上面的屬性將所有控件拖入佈局區完成GUI界面的設計。爲了方便後面編程,每個控件應該都起一個簡單易識別的名字,大家也可適當調整使得界面更加美觀。完成後可點擊工具欄那個綠色的三角按鈕運行一下看看效果。

    完成界面設計後點擊保存,這時會保存設計好的包含GUI界面的fig文件以及對應的m文件,在m文件中我們可以添加和修改控件的回調函數,以實現我們需要的效果。當然也可以在fig文件中右擊控件,選擇“查看回調”選擇相應回調函數即會進入該函數的編輯界面。在接下來的文章中都會介紹如何爲相應控件添加對應回調函數來實現我們需要的功能。


4. 圖片選擇功能實現

    這裏我們要實現一個簡單的基礎功能:當點擊按鈕時,彈出文件選擇對話框,在對話框中我們可以選擇一個圖像文件,點擊確定後其文件完整路徑顯示在旁邊的文本框中,同時在前面提到的兩個axes(座標軸)中顯示我們選中的圖片。其效果便是如下圖所示的那樣:

圖片展示

    我們還是回到之前的fig文件中,選中之前保存的文件右擊“用guide打開”。打開GUI界面後選中用於文件選擇的按鈕,右擊“查看回調”,選擇“Callback”,就會轉到Callback函數的編輯器中,如下圖所示:

變量顯示

    Callback函數是在創建圖形界面的時候自動生成的,但只是爲你列了一個框架沒有實際的操作執行,因爲我之前爲這個按鈕命名是“pushbutton_path”,所以這裏生成的函數名是pushbutton_path_Callback(),具體看大家自己的命名。回調函數的聲明爲:function 函數名(hObject, eventdata, handles),hObject爲發生事件的源對象(這裏可以視爲該按鈕的句柄);handles爲傳入的GUI數據(可認爲包含了所有控件的句柄,可通過handles訪問到),在這個函數中就可以添加代碼了。

    查看MATLAB官方文檔發現,文件選擇對話框可通過uigetfile函數實現,其調用方式如下:

file = uigetfile 打開一個模態對話框,其中列出了當前文件夾中的文件。用戶可以在這裏選擇或輸入文件的名稱。如果文件存在> 並且有效,當用戶點擊打開時,uigetfile 將返回文件名。如果用戶點擊取消或窗口關閉按鈕 (X ),uigetfile 將返回 0。

 [file,path] = uigetfile('*.png',...
              'Select an icon file','icon.png')

——MATLAB官方文檔》

    具體添加的完整代碼如下:

% --- 點擊圖片文件選擇按鈕(pushbutton_path)時執行.
function pushbutton_path_Callback(hObject, eventdata, handles)
global flag; % 全局變量聲明,flag決定是否能點擊拼圖 

% 彈出文件選擇框,選擇一張圖片
[file,path] = uigetfile({'*.jpg;*.jpeg;*.png;*.bmp;*.tif',...
    '圖片文件 (*.jpg,*.jpeg,*.png,*.bmp,*.tif)'},'選擇一張圖片');

if isequal(file,0) % 若文件不存在
   set(handles.edit_path,'String','請選擇一張圖片');
else
   fileName= fullfile(path,file); % 選擇的圖片絕對路徑
   set(handles.edit_path,'String',fileName); % 顯示選擇的圖片路徑
   pic_data=imread(fileName);
   % 判斷拼圖的階數
   n=get(handles.popupmenu_rank,'value'); 
   rank_Tag=n+2;
   % 選取最短那條邊作爲邊長
   len=min([size(pic_data,1),size(pic_data,2)]);
   len_col=round(len/rank_Tag);% 每個拼圖塊長度
   len_row=round(len/rank_Tag);% 每個拼圖塊寬度
   % 將圖片調整爲正方形
   pic_data=imresize(pic_data,[rank_Tag*len_col rank_Tag*len_row]);
   axes(handles.axes_original) % 確定要顯示的座標軸
   image(pic_data);% 顯示圖片
   axis off; % 關閉座標顯示
   % 顯示拼圖
   axes(handles.axes_jigsaw) 
   image(pic_data);
   axis off;
   % 拼圖塊數字標識
   Tag=[1:1:rank_Tag^2-1,0];
   Tag=reshape(Tag,rank_Tag,rank_Tag);
   Tag=Tag';
   
   % 根據checkbox的是否勾選決定是否顯示拼圖塊數字提示
   ismask=get(handles.checkbox_num,'Value');
   axes(handles.axes_jigsaw);
   for i=1:size(Tag,1)
       for j=1:size(Tag,2)
           text(len_col/2*(2*j-1)-10,len_row/2*(2*i-1),num2str(Tag(i,j)),'FontSize',55-rank_Tag*5,'Color','c')
       end
   end
   if ~ismask % 若未勾選狀態,刪除所有text圖形
       h=findall(gca,'type','text');
       delete(h);
   end
   
   flag=false;% 重選文件後置flag防止誤點擊
end

【代碼解釋】

    代碼第3行首先申明瞭一個全局變量flag,這是一個在後面的文件中也會用到的變量,flag的值決定了點擊拼圖塊後是否對其作出反應,就先寫在這邊了後面會解釋其具體功能;第6行彈出一個文件選擇框,並限定文件格式爲jpg, jpeg, png, bmp, tif類型;第9行判斷是否選擇了有效文件,若不存在,在第10行設置旁邊的靜態文本框顯示字符串“請選擇一張圖片”作爲提示;而當文件存在則執行第12-49行的代碼。

    第12-13行首先得到選擇圖片的絕對路徑,並在路徑顯示的文本中顯示出來;第14行讀取圖片文件。讀取了文件後並不是直接顯示,因爲我們讀入的圖片可能尺寸各異,我們需要適當處理將其縮放爲一個正方形。那邊長該取多少合適呢?這裏簡單考慮,取圖片長寬中最短的那個作爲邊長,直接利用imresize()函數將其縮放爲正方形。第16行爲獲取當初我們設置的用來選擇拼圖階數的彈出菜單控件的實際值,n爲選擇的那一項的序號(如第一項“3階拼圖”的序號爲1),因此可以簡單計算拼圖的階數rank_Tagn+2(如選中第一項rank_Tag=3)。知道階數那麼每個拼圖塊的長寬就可由邊長除以階數得到,第20-21行計算每塊拼圖塊的長寬。

    得到了調整好的拼圖,需要在座標軸中將圖片顯示出來,第24-26行爲在顯示原圖的座標軸顯示原始圖片(未拆分打亂的圖)並關閉座標軸顯示;同理,第28-30行是在拼圖的主座標軸中顯示圖片。

    第31-47行其實是爲了實現另一個功能:爲每塊拼圖塊顯示提示的數字,這一功能在後面會介紹,這裏爲解釋代碼只簡單說一下。第32-34行是得到標識拼圖塊的數字矩陣,因爲當前還沒有打亂拼圖,如果選擇了數字提示這時顯示的一定是如1,2,3;4,5,6;7,8,0的順序數字,所以這裏直接產生一個順序矩陣用於標註。第37行是獲取那個用於是否顯示提示數字的勾選框的值,值爲1表示勾選,0表示未選。第38-43行在每塊拼圖塊的中間位置添加text圖形以顯示對應數字。第44-47行判斷勾選狀態,若未選刪除所有text對象(在圖形上表現爲無數字標識)。


【下載鏈接】
    若您想提前獲得博文中涉及的實現完整拼圖功能的全部程序文件(包括圖片、fig, m文件等),這裏已打包上傳至博主的CSDN下載資源中,下載後運行jigsawGUI.m文件即可運行(實現完整功能)。同時已將文件打包編程成exe的可執行文件,可在我的百度網盤中下載後直接運行。文件下載鏈接如下:

下載鏈接1:博文中涉及的完整程序文件
在這裏插入圖片描述
下載鏈接2:拼圖遊戲打包的可執行EXE文件(已裝MATLAB的用戶下載)
鏈接:https://pan.baidu.com/s/1m0qLu3Un4jDT-NyQwFZs1g
提取碼:j906

下載鏈接3:拼圖遊戲打包的可執行EXE文件(未裝MATLAB的用戶下載)
鏈接:https://pan.baidu.com/s/1uCMJI5O0FsnJKyoK4Lcvmw
提取碼:a1kb

公衆號獲取
    本人微信公衆號已創建,掃描以下二維碼並關注公衆號“AI技術研究與分享”,後臺回覆“JG20190508”即可獲取全部資源文件。


5. 結束語

    上篇的講述就是這麼多了,拼圖的更多功能的實現會在後面的博文中講述,大家也可以參考博主前面的一篇博文:基於MATLAB的拼圖遊戲設計。由於博主能力有限,博文中提及的方法與代碼即使經過測試,也難免會有疏漏之處。希望您能熱心指出其中的錯誤,以便下次修改時能以一個更完美更嚴謹的樣子,呈現在大家面前。同時如果有更好的實現方法也請您不吝賜教。

    大家的點贊和關注是博主最大的動力,如果您想要獲取博文中的完整代碼文件,可通過C幣或積分下載,沒有C幣或積分的朋友可在關注、點贊博文後在評論區留下郵箱,我會在第一時間發送給您。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章