头像都是上网找的,如有侵权,请联系删除!
游戏名称:华容道
实现工具:matlab
实现功能:华容道基本功能+五种开局模式+重新开始+关于+步数显示;所有功能符合逻辑并通过自测。
难点:兵的对角移动判断
实现思路:武将和兵都为按键型控件,移动通过鼠标按键按下的位置判断,过程中生成一个5*4的矩阵,用于游戏逻辑判断。
完成日期:2018.06.27
function huarongdao %主函数
global everyHandle wjposition mode step stepHandle %全局变量 everyHandle为控件的句柄值,wjposition是控件的位置元胞数组,mode为游戏模式,step为步数,stepHandle为步数按钮句柄值
windowHandle = figure('Name','华容道','NumberTitle','off','MenuBar','none',...
'ToolBar','none','Position',[650 350 420 560],'WindowButtonDownFcn',...
@emptyClick,'Resize','off'); %emptyClick函数为鼠标按键按下事件函数
axes(windowHandle,'Position',[0 0 0 0]) %创建坐标系,用来检测鼠标按下位置
axis off % 不显示坐标轴
mode = '横刀立马①'; %初始化游戏模式为横刀立马①
step = 0; %初始化步数为0
wjposition = {[110 310 200 200],[10 310 100 200],[310 310 100 200],...% 横刀立马①模式下武将的初始位置 顺序为: {'曹操','张飞','赵云','关羽','马超','黄忠','兵A','兵B','兵C','兵D'};
[110 210 200 100],[10 110 100 200],[310 110 100 200],...
[10 10 100 100],[110 110 100 100],[210 110 100 100],[310 10 100 100]};
wjphoto = {imread('曹操.jpg'),imread('张飞.jpg'),imread('赵云.jpg'),... % 载入武将的图片数据
imread('关羽.jpg'),imread('马超.jpg'),imread('黄忠.jpg'),...
imread('兵A.jpg'),imread('兵B.jpg'),imread('兵C.jpg'),imread('兵D.jpg'),};
for ix = 1:10
uicontrol('parent',windowHandle,'Style','pushbutton',...
'Position',wjposition{ix},'FontSize',30,'Callback',@checked,'CData',wjphoto{ix}) % 生成游戏界面控件
end
everyHandle = flip(findall(gcf,'Style','pushbutton')); %找出游戏将兵的句柄值,并赋予everyHandle
stepHandle = uicontrol('parent',windowHandle,'Style','pushbutton',...
'Position',[10 515 100 45],'String','当前步数','Fontsize',10); %创建游戏步数显示按钮
option = {'选择开局','重新开始','关于'};
for ix = 0:2
uicontrol('parent',windowHandle,'Style','pushbutton',... %创建菜单选项
'Position',[ix*100+110 515 100 45],'String',option{ix+1},...
'Fontsize',13,'Callback',@optionArray)
end
end
function optionArray(hObject,event) %选项回调函数
global everyHandle wjposition mode step stepHandle
switch get(hObject,'String')
case '选择开局'
str2 = {'屯兵东进','兵分三路','齐头并进','横刀立马②','横刀立马①'};
mode = figure('Name','请选择开局模式','ToolBar','none',...
'MenuBar','none','NumberTitle','off',...
'Position',[1100 500 300 300]);
for ix = 1:5
uicontrol('parent',mode,'Style','pushbutton',...
'Position',[50,(ix-1)*57+15,200,50],...
'String',str2{ix},'FontSize',20,'Callback',@modeCallback)
end
case '重新开始'
wjposition = modeFun(mode);
for ix = 1:10
set(everyHandle(ix),'Position',wjposition{ix})
end
step=0;
set(stepHandle,'String','当前步数')
thining(wjposition)
case '关于'
about = figure('Name','关于','ToolBar','none',...
'MenuBar','none','NumberTitle','off',...
'Position',[750 500 400 400]);
aboutA= uicontrol('parent',about,'Style','text','position',[0 0 380 390]);
aboutB= uicontrol('parent',about,'Style','text','position',[20 20 350 270]);
text2={ '★★华容道是古老的中国民间益智游戏,其变化多端、百玩不厌。',...
'★★通过移动各个棋子,帮助曹操从初始位置移到棋盘最下方中部,从出口逃走。',...
'★★不允许跨越棋子,还要设法用最少的步数把曹操移到出口。',...
'★★曹操逃出华容道的最大障碍是关羽,关羽立马华容道,一夫当关,万夫莫开。',...
'★★关羽与曹操当然是解开这一游戏的关键。',...
'★★四个刘备军兵是最灵活的,也最容易对付,如何发挥他们的作用也要充分考虑周全。','',...
'程序版本:1.0','完成时间:2018年6月27日'};
text1={'诗云:','曹瞒兵败走华容,','正与关公狭路逢。','只为当初恩义重,','放开金锁走蛟龙。'};
[textx1,~]=textwrap(aboutA,text1);
[textx2,~]=textwrap(aboutB,text2);
set(aboutA,'String',textx1,'FontSize',10,'HorizontalAlignment','center')
set(aboutB,'String',textx2,'FontSize',10,'HorizontalAlignment','left')
end
end
function modeCallback(hObject,event) % 模式选择回调函数 {'屯兵东进','兵分三路','齐头并进','横刀立马②','横刀立马①'};
global everyHandle wjposition mode step stepHandle
mode = get(hObject,'String') ; % 更新当前选择模式
wjposition = modeFun(mode); %将模式初识位置赋予wjposition
for ix = 1:10
set(everyHandle(ix),'Position',wjposition{ix}) % 将模式初始位置值更新到控件上
end
step=0;
set(stepHandle,'String','当前步数') % 更新步数
thining(wjposition) %将最新的位置更新到5*4的矩阵中
end
function wjposition = modeFun(mode) %模式位置初始函数
switch mode %顺序为 {'曹操','张飞','赵云','关羽','马超','黄忠','兵A','兵B','兵C','兵D'};
case '横刀立马①'
wjposition = {[110 310 200 200],[10 310 100 200],[310 310 100 200],...
[110 210 200 100],[10 110 100 200],[310 110 100 200],...
[10 10 100 100],[110 110 100 100],[210 110 100 100],[310 10 100 100]};
case '横刀立马②'
wjposition = {[110 310 200 200],[10 310 100 200],[310 310 100 200],...
[110 210 200 100],[10 10 100 200],[310 10 100 200],...
[10 210 100 100],[110 110 100 100],[210 110 100 100],[310 210 100 100]};
case '齐头并进'
wjposition = {[110 310 200 200],[10 310 100 200],[310 310 100 200],...
[110 110 200 100],[10 10 100 200],[310 10 100 200],...
[10 210 100 100],[110 210 100 100],[210 210 100 100],[310 210 100 100]};
case '兵分三路'
wjposition = {[110 310 200 200],[10 210 100 200],[310 210 100 200],...
[110 210 200 100],[10 10 100 200],[310 10 100 200],...
[10 410 100 100],[110 110 100 100],[210 110 100 100],[310 410 100 100]};
case '屯兵东进'
wjposition = {[10 310 200 200],[210 310 100 200],[310 310 100 200],...
[10 210 200 100],[10 10 100 200],[110 10 100 200],...
[210 210 100 100],[310 210 100 100],[210 110 100 100],[310 110 100 100]};
end
end
function checked(hObject,event) %按钮回调函数,用来确定当前摁下的是哪一个按钮
global wjHandle everyHandle wj
wjHandle = hObject;
for ix =1:10
if everyHandle(ix) == wjHandle
wj = ix;
break
end
end
end
function emptyClick(~,event) %选定按钮后,鼠标点击空白处的事件函数
global wjHandle wjposition oldPosition
oldax = thining(wjposition);
oldPosition = get(wjHandle,'Position');
mouseXY = get(gca,'CurrentPoint'); %%★★★★★★返回鼠标按下的位置值★★★★★★
mouseXY = mouseXY(1,1:2)-10;
if (1 < mouseXY(1) & mouseXY(1) < 399) & (1 < mouseXY(2) & mouseXY(2) < 499) %判断鼠标按下位置是否超出范围
nx = get(wjHandle,'Position');
if nx(3)==100 & nx(4)==100 %兵的移动判断
wjarray = thining(wjposition);
yy = (nx(1)-10)/100+1;
xx = 5-(nx(2)-10)/100;
if mouseXY(1)-nx(1)>100 & mouseXY(2)-nx(2) >100 %兵的对角移动,原位置为(-1,-1)角
if wjarray(xx-1,yy)
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)]) %右移
elseif wjarray(xx,yy+1)
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)]) %上移
end
elseif mouseXY(1)-nx(1)<0 & mouseXY(2)-nx(2) >100 %兵的对角移动,原位置为(-1,1)角
if wjarray(xx,yy-1)
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)]) %上移
elseif wjarray(xx-1,yy)
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)]) %左移
end
elseif mouseXY(1)-nx(1)<0 & mouseXY(2)-nx(2)<0 %兵的对角移动,原位置为(1,1)角
if wjarray(xx,yy-1)
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)]) %下移
elseif wjarray(xx+1,yy)
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)]) %左移
end
elseif mouseXY(1)-nx(1)>100 & mouseXY(2)-nx(2)<0 %兵的对角移动,原位置为(-1,1)角
if wjarray(xx,yy+1)
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)]) %下移
elseif wjarray(xx+1,yy)
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)]) %右移
end
elseif mouseXY(1)-nx(1)<0 & mouseXY(1)-nx(1)>-200 & mouseXY(2)-nx(2) >0 & mouseXY(2)-nx(2) <100 %向左
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >100 & mouseXY(1)-nx(1) <300 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<100 %向右
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1) <100 & mouseXY(2)-nx(2)>100 & mouseXY(2)-nx(2)<300 %向上
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1) <100 & mouseXY(2)-nx(2)<0 & mouseXY(2)-nx(2)>-200 %向下
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)])
end
elseif nx(3)==100 & nx(4)==200 %张飞、赵云、马超、黄忠移动判断
if mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1) <100 & mouseXY(2)-nx(2)>200 & mouseXY(2)-nx(2)<400 %向上
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1)<100 & mouseXY(2)-nx(2)<0 & mouseXY(2)-nx(2)>-200 %向下
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >-100 & mouseXY(1)-nx(1) <0 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<200 %向左 *
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >100 & mouseXY(1)-nx(1) <200 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<200 %向右 *
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)])
end
elseif nx(3)==200 & nx(4)==100 %关羽移动判断
if mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1) <200 & mouseXY(2)-nx(2)>100 & mouseXY(2)-nx(2)<200 %向上 *
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1)<200 & mouseXY(2)-nx(2)<0 & mouseXY(2)-nx(2)>-100 %向下 *
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >-200 & mouseXY(1)-nx(1) <0 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<100 %向左
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >200 & mouseXY(1)-nx(1) <400 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<100 %向右
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)])
end
elseif nx(3)==200 & nx(4)==200 %曹操移动判断
if mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1) <200 & mouseXY(2)-nx(2)>200 & mouseXY(2)-nx(2)<300 %向上 *
set(wjHandle,'Position',[nx(1) nx(2)+100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >0 & mouseXY(1)-nx(1)<200 & mouseXY(2)-nx(2)<0 & mouseXY(2)-nx(2)>-100 %向下 *
set(wjHandle,'Position',[nx(1) nx(2)-100 nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >-100 & mouseXY(1)-nx(1) <0 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<200 %向左 *
set(wjHandle,'Position',[nx(1)-100 nx(2) nx(3) nx(4)])
elseif mouseXY(1)-nx(1) >200 & mouseXY(1)-nx(1) <300 & mouseXY(2)-nx(2)>0 & mouseXY(2)-nx(2)<200 %向右 *
set(wjHandle,'Position',[nx(1)+100 nx(2) nx(3) nx(4)])
end
end
end
newposition(oldPosition,oldax)
end
function newposition(oldPosition,oldax) %确定新位置是否符合要求,不符合则返回前状态
global wjposition wjHandle wj step stepHandle
wjposition(wj)={get(wjHandle,'Position')};
ax = thining(wjposition);
if sum(ax(:)==0) ~= 2
set(wjHandle,'Position',oldPosition)
wjposition(wj)={get(wjHandle,'Position')};
else
if isequal(ax,oldax)
else
step=step+1;
set(stepHandle,'String',num2str(step))
temporary = get(wjHandle,'Position');
if temporary(1,3:4) == [200 200]
if temporary(1:1:2) == [110 10]
gameover()
end
end
end
end
end
function ax = thining(wjposition) %将图形界面转换成一个5*4的数组,用来判断移动是否符合游戏规则
ax = zeros(5,4);
for ix = 1:10
switch ix
case 1
caocao = wjposition{ix};
yy = (caocao(1)-10)/100+1;
xx = (caocao(2)-10)/100+1;
ax(5-xx:6-xx,yy:yy+1) = [1,1;1,1];
case {2,3,5,6}
zhangfei = wjposition{ix};
yy = (zhangfei(1)-10)/100+1;
xx = (zhangfei(2)-10)/100+1;
ax(5-xx:6-xx,yy) = [1;1];
case 4
guanyu = wjposition{ix};
yy = (guanyu(1)-10)/100+1;
xx = (guanyu(2)-10)/100+1;
ax(6-xx,yy:yy+1) = [1,1];
case {7,8,9,10}
guanyu = wjposition{ix};
yy = (guanyu(1)-10)/100+1;
xx = (guanyu(2)-10)/100+1;
ax(6-xx,yy) = [1];
otherwise
errordlg('程序存在BUG!','错误')
end
end
end
function gameover()
global step
errordlg(strcat('恭喜你通过了游戏,一共用了_',num2str(step),'_步。'),'游戏结束')
end