1 运行效果
2 设计思路
将每一个按键设计成按钮,使用循环的方式生成按钮组,主要功能:
(1)随机打乱。防止产生死局。
(2)完成检测。
(3)计时显示。
3 程序代码
clear;close all;clc;
GUI();
function GUI()
% 定义主界面
Fig = figure('Position',[400,50,600,850],...% 界面位置、大小
'NumberTitle','off',... % 关闭'figure 1'
'Name','数字拼图游戏',...% 主界面命名
'Units','normalized','MenuBar','none');% 相对位置、关闭工具栏
% 定义网格区域(游戏界面)
Pln = uipanel(Fig,'Position',[0.1,0.1,0.805,0.85]);
% buttons = zeros(3,3);
% 定义按钮
count=1;
for i=1:3
for j=1:3
buttons(count)=uicontrol(Pln,'Style', 'pushbutton',...
'String', num2str(count),'FontSize',23,...
'Position',[(j-1)*160,(3-i)*160,160,160]);
% buttons(count).CData = imread("D:\photos\eason.jpg");
count = count+1;
end
end
buttons(9).String=[];
buttons(9).CData=[];
% 初始时间、初始计数值、开始标记
MoveCount = 0;
StartTime = 0;
% 定义每一个按钮的回调函数
buttons(1).Callback = @MoveButton1;
buttons(2).Callback = @MoveButton2;
buttons(3).Callback = @MoveButton3;
buttons(4).Callback = @MoveButton4;
buttons(5).Callback = @MoveButton5;
buttons(6).Callback = @MoveButton6;
buttons(7).Callback = @MoveButton7;
buttons(8).Callback = @MoveButton8;
buttons(9).Callback = @MoveButton9;
% 定义'游戏开始','重新开始'按钮
StatButton = uicontrol(Pln,'Style','pushbutton','String','游戏开始','FontSize',16,...
'Position',[80,600,160,60]);
StatButton.Callback = @StartGame;
ReStartButton = uicontrol(Pln,'Style','pushbutton','String','重新开始','FontSize',16,...
'Position',[260,600,160,60]);
ReStartButton.Callback = @RestartGame;
% 定义计时、计数显示框
TimeVal = uicontrol(Pln,'Style','edit','String','','Position',[90,500,140,50],'FontSize',16);
NumbVal = uicontrol(Pln,'Style','edit','String','','Position',[250,500,140,50],'FontSize',16);
uicontrol(Pln,'Style','text','String','时间:','Position',[120,550,80,40],'FontSize',16);
uicontrol(Pln,'Style','text','String','移动步数:','Position',[270,550,100,40],'FontSize',16);
% 创建定时器
t = timer ('TimerFcn',{@TimeDisplay,TimeVal},'ExecutionMode','fixedRate','StartDelay',1);
% 保存每一个按钮的初始位置
InitialPos=cell(1,9);
for i=1:9
InitialPos{i}=buttons(i).Position;
end
function StartGame(~,~)
shuffbutton();
TimeVal.String = '0 s';
NumbVal.String = '';
start(t);
IsComplete();
end
% 每一个按钮的回调函数
function MoveButton1(~,~)
SwapPosition(buttons(1));
IsComplete();
end
function MoveButton2(~,~)
SwapPosition(buttons(2));
IsComplete();
end
function MoveButton3(~,~)
SwapPosition(buttons(3));
IsComplete();
end
function MoveButton4(~,~)
SwapPosition(buttons(4));
IsComplete();
end
function MoveButton5(~,~)
SwapPosition(buttons(5));
IsComplete();
end
function MoveButton6(~,~)
SwapPosition(buttons(6));
IsComplete();
end
function MoveButton7(~,~)
SwapPosition(buttons(7));
IsComplete();
end
function MoveButton8(~,~)
SwapPosition(buttons(8));
IsComplete();
end
function MoveButton9(~,~)
IsComplete();
end
% 打乱函数定义
function shuffbutton(~,~)
global EmptyButtonPos
count=1;
shuffpos = Stalemate();
for i=shuffpos+1 % 解释
buttons(count).Position=cell2mat(InitialPos(i));
count = count+1;
end
EmptyButtonPos = InitialPos(9);
end
% 判断是否完成
function IsComplete(~,~)
NewButtonPos = cell(1,9);
for i=1:9
NewButtonPos{i} = buttons(i).Position;
end
IsOrNo = isequal(NewButtonPos,InitialPos);
NumbVal.String = num2str(MoveCount);
% 游戏结束,计时结束
if IsOrNo
warndlg('恭喜你完成拼图!!!','数字拼图游戏');
stop(t);
TimeVal.String = [num2str(StartTime),'s'];
end
end
function RestartGame(~,~)
stop(t);
shuffbutton();
StartTime = 0;
MoveCount = 0;
TimeVal.String = '0 s';
NumbVal.String = num2str(MoveCount);
start(t);
end
% 交换位置
function SwapPosition(butt)
Pos = butt.Position;
UpButton = Pos + [0 160 0 0];
DownButton = Pos + [0 -160 0 0];
LButton = Pos + [-160 0 0 0];
Rbutton = Pos + [160 0 0 0];
if UpButton==buttons(9).Position
temp = Pos;
butt.Position = buttons(9).Position;
buttons(9).Position = temp;
MoveCount = MoveCount + 1;
end
if DownButton==buttons(9).Position
temp = Pos;
butt.Position = buttons(9).Position;
buttons(9).Position = temp;
MoveCount = MoveCount + 1;
end
if LButton==buttons(9).Position
temp = Pos;
butt.Position = buttons(9).Position;
buttons(9).Position = temp;
MoveCount = MoveCount + 1;
end
if Rbutton==buttons(9).Position
temp = Pos;
butt.Position = buttons(9).Position;
buttons(9).Position = temp;
MoveCount = MoveCount + 1;
end
end
function TimeDisplay(hObject,eventdata,x)
StartTime = StartTime + 1;
TimeVal.String = [num2str(StartTime),'s'];
end
% 存在死局,用此函数生成可以复原的序列
function shuffpos = Stalemate()
isok = 1;
while isok
shuffpos = abs(randperm(9)-9);
yespos = [1:8,0];
shuffCount = count_inversions(shuffpos);
yesCount = count_inversions(yespos);
if shuffCount == yesCount
isok = 0;
end
end
function inversions = count_inversions(state)
n = length(state);
inversions = 0;
for i = 1:n-1
for j = (i+1):n
if state(i) > state(j)
inversions = inversions + 1;
end
end
end
end
end
end