matlab 实现2048游戏

% 游戏名称:2048
% 实现的功能:2048基本游戏主体、分数显示、难度选择、历史记录、对应图片显示等

% 完成时间:2018.06.24

@图片需另外下载或自己制作




function game2048()  % 主函数

initialize()  % 初始化
hardAndNumberProbability()  % 选择初始化难度
dispdata()  % 显示初始化结果

end


function initialize()   % 初始化函数,生成界面以及初始化游戏

global griddata hb photo2048 score scoreHandle gameover;  % 全局变量

griddata = zeros(4);   % 初始化4X4矩阵数据
rand_i = randi(16);
griddata(rand_i) = 2;   % 随机位置生成一个2
score = 0 ;  % 初始化分数
gameover = 0;  % 初始化游戏结束标志位

figHandle = figure('Name','2048','MenuBar','none',...    % 生成主窗口
    'ToolBar','none','NumberTitle','off',...
    'Units','normalized', 'Position',[0.39 0.30 0.3 0.6],...
    'KeyPressFcn',@keyevent);

for xi =0:15  % 生成4*4按钮矩阵
    ix=rem(xi,4);
    iy = fix((xi+0.5)/4);
    uicontrol(figHandle,'Style','pushbutton',...
        'Units','normalized','position',[ix*0.25 iy*0.20 0.245 0.195],'KeyPressFcn',@keyevent)
end

hb = findall(gcf, 'Style', 'pushbutton');% 获得16个方格的句柄值

photo2048 = struct('p2',{imread('2.jpg')},'p4',{imread('4.jpg')},'p8',{imread('8.jpg')},...     % 读取显示的图片
    'p16',{imread('16.jpg')},'p32',{imread('32.jpg')},'p64',{imread('64.jpg')},...
    'p128',{imread('128.jpg')},'p256',{imread('256.jpg')},'p512',{imread('512.jpg')},...
    'p1024',{imread('1024.jpg')},'p2048',{imread('2048.jpg')},'p4096',{imread('4096.jpg')},...
    'p8192',{imread('8192.jpg')});

% 这里需要导入图片
uicontrol(figHandle,'Style','text','Units','normalized',...    % 生成2048标志
    'Position',[0.01,0.81,0.3 0.15],'String','2048@',...
    'FontSize',25,'FontName','微软雅黑');

uicontrol(figHandle,'Style','text','Units','normalized',...    % 生成分数标志
    'Position',[0.35 0.81 0.18 0.07],'String','分数:','FontSize',18);

scoreHandle = uicontrol(figHandle,'Style','pushbutton','Units','normalized',...
    'Position',[0.51,0.81,0.24 0.09],'String','0','FontSize',15,'KeyPressFcn',@keyevent);  % 生成分数显示框

uicontrol(figHandle,'Style','pushbutton','Units','normalized',...
    'Position',[0.75 0.9 0.245 0.09],'String','历史记录','FontSize',13,'Callback',@file,'KeyPressFcn',@keyevent) % 生成历史记录按钮

uicontrol(figHandle,'Style','pushbutton','Units','normalized',...
    'Position',[0.75 0.81 0.245 0.09],'String','选择难度',...
    'FontSize',13,'Callback',@hardAndNumberProbability,'KeyPressFcn',@keyevent) % 生成选择难度按钮

uicontrol(figHandle,'Style','pushbutton','Units','normalized',... % 生成重新游戏按钮
    'Position',[0.51,0.9,0.24,0.09],'String','从新开始游戏',...
    'FontSize',13,'Callback',@reset,'KeyPressFcn',@keyevent)

end

function hardAndNumberProbability(hObject,handles)     % 难度判断及2.4.8出现的概率

global hardPop hardOption;
hardOption = dialog('Name','难度选择','Units','normalized','Position',[0.43 0.45 0.12 0.10]);  % 难度选择
hardPop = uicontrol(hardOption,'Style','popupmenu','Units','normalized',...  % 弹出式菜单
    'Position',[0.31 0.5 0.4 0.4],'String',{'简单','中等','困难'},...
    'FontSize',20);
hardPush = uicontrol(hardOption,'Style','pushbutton','Units','normalized',...   % 确定按钮
    'position',[0.3 0.05 0.4 0.32],'String','确定','FontSize',20,'Callback',@pushCallback);
end

function pushCallback(hObject,handles)  % 难度选择 确定按钮 回调函数
global hardPop hardOption hardNum
hardNum = get(hardPop,'Value');
close(hardOption)
end

function keyevent(~, event)  % 检测键盘输入和数组合并   最重要

global griddata gameover;

oldgriddata = griddata;    % 判断数组是否相等,以判别存在不能移动但又不是游戏结束的情况
switch event.Key
    case 'uparrow'
        disp('上键')
        hasBeenChangeData=standardRightSlip(rot90(griddata,-1));
        griddata = rot90(hasBeenChangeData);
    case 'leftarrow'
        disp('左键')
        hasBeenChangeData = standardRightSlip(flip(griddata,2));
        griddata = flip(hasBeenChangeData,2);
    case 'downarrow'
        disp('下键')
        hasBeenChangeData=standardRightSlip(rot90(griddata));
        griddata = rot90(hasBeenChangeData,-1);
    case 'rightarrow'
        disp('右键')
        griddata=standardRightSlip(griddata);
    case 'escape'
        return
    otherwise
        return
end

if isequal(oldgriddata,griddata)  % 判断数组是否相等,以判别存在不能移动但又不是游戏结束的情况
    
else
    randNum();  % 调用随机生成数字函数
end

dispdata()   % 调用显示函数
if gameover ==0
    gameoverFun()   % 调用检测游戏状态函数
end
end


function griddata = standardRightSlip(griddata)   % 标准右滑动,数据合并

global score

for iix = 1:4
    rowData = griddata(iix,:);
    rowData = rowData(rowData>0);
    lenRow = length(rowData);
    
    switch lenRow
        case 0
            griddata(iix,:) = [0 0 0 0];
        case 1
            griddata(iix,:) = cat(2,[0 0 0],rowData);
        case 2
            if rowData(1) ==  rowData(2)
                rowData(2) = rowData(1)+rowData(2);
                score = score + rowData(2);
                rowData(1) = 0;
            end
            griddata(iix,:) = cat(2,[0 0],rowData);
        case 3
            
            if rowData(2) ==  rowData(3)
                rowData(3) = rowData(2)+rowData(3);
                score = score + rowData(3);
                rowData(2) = [];
                griddata(iix,:) = cat(2,[0 0],rowData);
                continue;
            elseif rowData(1) ==  rowData(2)
                rowData(2) = rowData(1)+rowData(2);
                score = score + rowData(2);
                rowData(1) = 0;
                griddata(iix,:) = cat(2,[0],rowData);
            else
                griddata(iix,:) = cat(2,[0],rowData);
            end
        case 4
            
            if rowData(3) ==  rowData(4)
                rowData(4) = rowData(3)+ rowData(4);
                score = score + rowData(4);
                rowData(3) = [];
                if rowData(1) ==  rowData(2)
                    rowData(2) = rowData(1)+rowData(2);
                    score = score + rowData(2);
                    rowData(1) = [];
                    griddata(iix,:) = cat(2,[0 0],rowData);
                    continue
                else
                    griddata(iix,:) = cat(2,[0],rowData);
                    continue
                end
            elseif rowData(2) ==  rowData(3)
                rowData(3) = rowData(2)+rowData(3);
                score = score + rowData(3);
                rowData(2) = [];
                griddata(iix,:) = cat(2,[0],rowData);
                continue
            elseif rowData(1) ==  rowData(2)
                rowData(2) = rowData(1)+rowData(2);
                score = score + rowData(2);
                rowData(1) = [];
                griddata(iix,:) = cat(2,[0],rowData);
            end
        otherwise
            errordlg('程序存在BUG!','错误!')
    end
    
end
end


function randNum()   % 随机生成数字函数

global griddata hardNum;

yxx=[];
for ix = 1:16
    if griddata(ix) < 1
        yxx=[yxx;ix];
    end
end
hh = randi(length(yxx));
bb = randi(100);
if hardNum == 1
    griddata(yxx(hh))= 2;
elseif hardNum == 2
    if bb >= 70
        griddata(yxx(hh))= 4;
    else
        griddata(yxx(hh))= 2;
    end
elseif hardNum == 3
    if bb >= 80
        griddata(yxx(hh))= 8;
    elseif bb>=50
        griddata(yxx(hh))= 4;
    else
        griddata(yxx(hh))= 2;
    end
end
end

function gameoverFun()   % 判断游戏是否结束及选择后续操作
global griddata gameover score;

for ie = 1:4
    hand = griddata(ie,:);
    lie = griddata(:,ie);
    if ~isempty(hand(hand == 0)) || ~isempty(lie(lie == 0))
        gameover = 0;
        break
    elseif hand(1) == hand(2) || hand(2) == hand(3) || hand(3) == hand(4)
        gameover = 0;
        break
    elseif lie(1) == lie(2) || lie(2) == lie(3) || lie(3) == lie(4)
        gameover = 0;
        break
    else
        if ie ==4
            gameover = 1;
        end
    end
end
if gameover == 1
    player = inputdlg('请输入的你的名字:(如果不输入则随机)');
    fileHandle = fopen('记录.txt','at');
    a = strcat('玩家:',player,'--','分数:',num2str(score),'\n');
    a = char(a);
    fprintf(fileHandle,a);
    fclose(fileHandle);
    overSelection = questdlg('Game Over!!!  是否从新开始游戏?','游戏结束','重新开始','结束游戏','查看分数记录','重新开始');
    if strcmp(overSelection,'重新开始')
        reset()
    elseif strcmp(overSelection,'结束游戏')
        close all
    elseif strcmp(overSelection,'查看分数记录')
        file()
    end
end
end

function dispdata()   % 对应相应的数字显示图片到按钮上
global griddata hb photo2048 scoreHandle score;
dispGriddata = rot90(griddata);
set(hb,'CData',[])
set(scoreHandle,'String',num2str(score))  % 显示分数

for ix =1:16
    switch dispGriddata(ix)
        case 2
            set(hb(ix),'CData',photo2048.p2)
        case 4
            set(hb(ix),'CData',photo2048.p4)
        case 8
            set(hb(ix),'CData',photo2048.p8)
        case 16
            set(hb(ix),'CData',photo2048.p16)
        case 32
            set(hb(ix),'CData',photo2048.p32)
        case 64
            set(hb(ix),'CData',photo2048.p64)
        case 128
            set(hb(ix),'CData',photo2048.p128)
        case 256
            set(hb(ix),'CData',photo2048.p256)
        case 512
            set(hb(ix),'CData',photo2048.p512)
        case 1024
            set(hb(ix),'CData',photo2048.p1024)
        case 2048
            set(hb(ix),'CData',photo2048.p2048)
        case 4096
            set(hb(ix),'CData',photo2048.p4096)
        case 8192
            set(hb(ix),'CData',photo2048.p8192)
    end
end
end

function reset(hObject,handles)   % 重置游戏
global griddata score gameover;

griddata = zeros(4);   % 初始化4X4矩阵数据
rand_i = randi(16);
griddata(rand_i) = 2;
score = 0 ;
gameover = 0;
dispdata()

end

function file(hObject,handles) % 显示排行榜
fileHandle = fopen('记录.txt','rt');

b=textscan(fileHandle,'%s');

b=char(b{1});

rankingList = figure('Name','排行榜','MenuBar','none','ToolBar','none','NumberTitle','off');
axeshandle = axes(rankingList);
axis off
text(axeshandle,'String',b,'Position',[0.05 0.7],'Units','normalized')
fclose(fileHandle);
end



猜你喜欢

转载自blog.csdn.net/weixin_42205310/article/details/80790394