matlab代码_matlab代码实现 - CSDN
精华内容
参与话题
  • MATLAB 经典程序源代码大全

    千次下载 热门讨论 2020-07-30 23:33:08
    本资源经过数模之后总结的一些经典代码。其中函括 1、中国大学生数学建模竞赛题解 2、演示程序 3、微积分和微分方程 4、图形 5、随机模拟和统计分析 6、数学规划 7、数据拟合 8、离散优化 9、方程求根 10、时间序列...
  • MatLab代码大全

    热门讨论 2020-07-30 23:32:36
    MATLAB是由美国mathworks公司发布的主要面对科学计算、可视化以及交互式程序设计的高科技计算环境。它将数值分析、矩阵计算、科学数据可视化以及非线性动态系统的建模和仿真等诸多强大功能集成在一个易于使用的视窗...
  • Matlab有趣代码

    万次阅读 多人点赞 2016-10-07 15:52:36
    Matlab有趣代码标签: Matlab彩蛋xpbombs; %扫雷vibes; %振膜teapotdemo; %茶壶logo; %Matlab logotravel; %路线问题life; %Convay的人生小游戏makevase; %造花瓶truss; %弹弹弹codec; %编码fifteen; %拼图xpquad; %...

    一、彩蛋

    xpbombs; %扫雷
    
    vibes; %振膜
    
    teapotdemo; %茶壶
    
    logo; %Matlab logo
    
    travel; %路线问题
    
    life; %Convay的人生小游戏
    
    makevase; %造花瓶
    
    truss; %弹弹弹
    
    codec; %编码
    
    fifteen; %拼图
    
    xpquad; %超二次曲面
    
    wrldtrv; %坐飞机
    
    spy;  %不加参数就画个狗
    
    earthmap; %地图
    
    cplxdemo; %复杂的XYZ立体图形~黎曼曲面的平面效果
    
    lorenz; %Lorenz吸引子动画显示

    二、代码段

    % 画爱心
    [X, Y] = meshgrid(0.01:0.01:1, 0.01:0.01:1); 
    Zfun =@(x,y)12.5*x.*log10(x).*y.*(y-1)+exp(-((25 ... 
    *x - 25/exp(1)).^2+(25*y-25/2).^2).^3)./25; 
    Z = Zfun(X,Y); 
    figure; 
    surf(Y,Z,X,'FaceColor',[1 0.75 0.65],'linestyle','none'); 
    hold on 
    surf(Y+0.98,Z,X,'FaceColor',[1 0.75 0.65],'linestyle','none'); 
    axis equal; 
    view([116 30]); 
    camlight; 
    lighting phong; % 设置光照和光照模式
    % 说话
    function wav = matlabspeech(txt,voice,pace,fs)
    % matlabspeech('I Love Maple and Matlab')
    % matlabspeech('I Love Maple')
    % matlabspeech('I Love Matlab')
    if ~ispc, error('要求使用Microsoft Win32 SAPI .'); end
    if ~ischar(txt), error('第一个参数是字符串.'); end
    SV = actxserver('SAPI.SpVoice');
    TK = invoke(SV,'GetVoices');
    if nargin > 1
    
    for k = 0:TK.Count-1
    if strcmpi(voice,TK.Item(k).GetDescription)
    SV.Voice = TK.Item(k);
    break;
    elseif strcmpi(voice,'list')
    disp(TK.Item(k).GetDescription);
    end
    end
    
    if nargin > 2
    if isempty(pace), pace = 0; end
    if abs(pace) > 10, pace = sign(pace)*10; end
    SV.Rate = pace;
    end
    end
    if nargin < 4 || ~ismember(fs,[8000,11025,12000,16000,22050,24000,32000,...
    44100,48000]), fs = 16000; end
    if nargout > 0
    
    MS = actxserver('SAPI.SpMemoryStream');
    MS.Format.Type = sprintf('SAFT%dkHz16BitMono',fix(fs/1000));
    SV.AudioOutputStream = MS;
    end
    invoke(SV,'Speak',txt);
    if nargout > 0
    
    wav = reshape(double(invoke(MS,'GetData')),2,[])';
    wav = (wav(:,2)*256+wav(:,1))/32768;
    wav(wav >= 1) = wav(wav >= 1)-2;
    delete(MS);
    clear MS;
    end
    delete(SV);
    clear SV TK;
    pause(0.2);
    end
    % 最炫民族风
    fs = 44100; % sample rate
    dt = 1/fs;
    T16 = 0.125;
    t16 = [0:dt:T16];
    [temp k] = size(t16);
    t4 = linspace(0,4*T16,4*k);
    t8 = linspace(0,2*T16,2*k);
    [temp i] = size(t4);
    [temp j] = size(t8);
    % Modification functions
    mod4=(t4.^4).*exp(-30*(t4.^0.5));
    mod4=mod4*(1/max(mod4));
    mod8=(t8.^4).*exp(-50*(t8.^0.5));
    mod8=mod8*(1/max(mod8));
    mod16=(t16.^4).*exp(-90*(t16.^0.5));
    mod16=mod16*(1/max(mod16));
    f0 = 2*146.8; % reference frequency
    ScaleTable = [2/3 3/4 5/6 15/16 ...
    1 9/8 5/4 4/3 3/2 5/3 9/5 15/8 ...
    2 9/4 5/2 8/3 3 10/3 15/4 4 ...
    1/2 9/16 5/8];
    % 1/4 notes
    do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);
    re0f = mod4.*cos(2*pi*ScaleTable(22)*f0*t4);
    mi0f = mod4.*cos(2*pi*ScaleTable(23)*f0*t4);
    fa0f = mod4.*cos(2*pi*ScaleTable(1)*f0*t4);
    so0f = mod4.*cos(2*pi*ScaleTable(2)*f0*t4);
    la0f = mod4.*cos(2*pi*ScaleTable(3)*f0*t4);
    ti0f = mod4.*cos(2*pi*ScaleTable(4)*f0*t4);
    do1f = mod4.*cos(2*pi*ScaleTable(5)*f0*t4);
    re1f = mod4.*cos(2*pi*ScaleTable(6)*f0*t4);
    mi1f = mod4.*cos(2*pi*ScaleTable(7)*f0*t4);
    fa1f = mod4.*cos(2*pi*ScaleTable(8)*f0*t4);
    so1f = mod4.*cos(2*pi*ScaleTable(9)*f0*t4);
    la1f = mod4.*cos(2*pi*ScaleTable(10)*f0*t4);
    tb1f = mod4.*cos(2*pi*ScaleTable(11)*f0*t4);
    ti1f = mod4.*cos(2*pi*ScaleTable(12)*f0*t4);
    do2f = mod4.*cos(2*pi*ScaleTable(13)*f0*t4);
    re2f = mod4.*cos(2*pi*ScaleTable(14)*f0*t4);
    mi2f = mod4.*cos(2*pi*ScaleTable(15)*f0*t4);
    fa2f = mod4.*cos(2*pi*ScaleTable(16)*f0*t4);
    so2f = mod4.*cos(2*pi*ScaleTable(17)*f0*t4);
    la2f = mod4.*cos(2*pi*ScaleTable(18)*f0*t4);
    ti2f = mod4.*cos(2*pi*ScaleTable(19)*f0*t4);
    do3f = mod4.*cos(2*pi*ScaleTable(20)*f0*t4);
    blkf = zeros(1,i);
    % 1/8 notes
    do0e = mod8.*cos(2*pi*ScaleTable(21)*f0*t8);
    re0e = mod8.*cos(2*pi*ScaleTable(22)*f0*t8);
    mi0e = mod8.*cos(2*pi*ScaleTable(23)*f0*t8);
    fa0e = mod8.*cos(2*pi*ScaleTable(1)*f0*t8);
    so0e = mod8.*cos(2*pi*ScaleTable(2)*f0*t8);
    la0e = mod8.*cos(2*pi*ScaleTable(3)*f0*t8);
    ti0e = mod8.*cos(2*pi*ScaleTable(4)*f0*t8);
    do1e = mod8.*cos(2*pi*ScaleTable(5)*f0*t8);
    re1e = mod8.*cos(2*pi*ScaleTable(6)*f0*t8);
    mi1e = mod8.*cos(2*pi*ScaleTable(7)*f0*t8);
    fa1e = mod8.*cos(2*pi*ScaleTable(8)*f0*t8);
    so1e = mod8.*cos(2*pi*ScaleTable(9)*f0*t8);
    la1e = mod8.*cos(2*pi*ScaleTable(10)*f0*t8);
    tb1e = mod8.*cos(2*pi*ScaleTable(11)*f0*t8);
    ti1e = mod8.*cos(2*pi*ScaleTable(12)*f0*t8);
    do2e = mod8.*cos(2*pi*ScaleTable(13)*f0*t8);
    re2e = mod8.*cos(2*pi*ScaleTable(14)*f0*t8);
    mi2e = mod8.*cos(2*pi*ScaleTable(15)*f0*t8);
    fa2e = mod8.*cos(2*pi*ScaleTable(16)*f0*t8);
    so2e = mod8.*cos(2*pi*ScaleTable(17)*f0*t8);
    la2e = mod8.*cos(2*pi*ScaleTable(18)*f0*t8);
    ti2e = mod8.*cos(2*pi*ScaleTable(19)*f0*t8);
    do3e = mod8.*cos(2*pi*ScaleTable(20)*f0*t8);
    blke = zeros(1,j);
    % 1/16 notes
    do0s = mod16.*cos(2*pi*ScaleTable(21)*f0*t16);
    re0s = mod16.*cos(2*pi*ScaleTable(22)*f0*t16);
    mi0s = mod16.*cos(2*pi*ScaleTable(23)*f0*t16);
    fa0s = mod16.*cos(2*pi*ScaleTable(1)*f0*t16);
    so0s = mod16.*cos(2*pi*ScaleTable(2)*f0*t16);
    la0s = mod16.*cos(2*pi*ScaleTable(3)*f0*t16);
    ti0s = mod16.*cos(2*pi*ScaleTable(4)*f0*t16);
    do1s = mod16.*cos(2*pi*ScaleTable(5)*f0*t16);
    re1s = mod16.*cos(2*pi*ScaleTable(6)*f0*t16);
    mi1s = mod16.*cos(2*pi*ScaleTable(7)*f0*t16);
    fa1s = mod16.*cos(2*pi*ScaleTable(8)*f0*t16);
    so1s = mod16.*cos(2*pi*ScaleTable(9)*f0*t16);
    la1s = mod16.*cos(2*pi*ScaleTable(10)*f0*t16);
    tb1s = mod16.*cos(2*pi*ScaleTable(11)*f0*t16);
    ti1s = mod16.*cos(2*pi*ScaleTable(12)*f0*t16);
    do2s = mod16.*cos(2*pi*ScaleTable(13)*f0*t16);
    re2s = mod16.*cos(2*pi*ScaleTable(14)*f0*t16);
    mi2s = mod16.*cos(2*pi*ScaleTable(15)*f0*t16);
    fa2s = mod16.*cos(2*pi*ScaleTable(16)*f0*t16);
    so2s = mod16.*cos(2*pi*ScaleTable(17)*f0*t16);
    la2s = mod16.*cos(2*pi*ScaleTable(18)*f0*t16);
    ti2s = mod16.*cos(2*pi*ScaleTable(19)*f0*t16);
    do3s = mod16.*cos(2*pi*ScaleTable(20)*f0*t16);
    blks = zeros(1,k);
    % Melody by Schau_mal 
    part0 = [mi1f la0e la0e do1f mi1f ...
    re1e re1s mi1s re1e do1e re1e do1e la0f ...
    mi1f la0e la0e do1f mi1f ...
    so1e re1s mi1s re1e do1e re1e do1e ti0e so0e ...
    mi1f la0e la0e do1f mi1f ...
    re1e re1s mi1s re1e do1e re1e do1e la0e so0e ...
    mi1f la0e la0e do1f mi1f ...
    so1e mi1e blkf blkf blkf ...
    ];
    part1 = [la0f la0e so0e la0f la0e do1e ...
    do1f re1e do1e la0f la0f ...
    do1f do1e so0e do1e re1e mi1e so1e ...
    so1e mi1e re1f mi1f mi1f ...
    la1e la1e la1e so1e mi1e mi1f do1e ...
    la0e la0e la0e mi1e re1s mi1s re1e re1f ...
    mi1e mi1e so1e mi1e re1e mi1e re1e do1e ...
    la0f so0f la0f la0f ...
    ];
    part2 = [mi1e mi1e so1e mi1e mi1e so1e so1e la1e ... 
    do2e la1e so1f la1s do2s la1e la1f ...
    la0f la0e so0e la0f do1f ...
    re1e mi1s re1s do1e re1e mi1f mi1f ...
    la0e la1e la1e so1e re1e mi1s re1s do1e re1e ...
    mi1f mi1f blke blke blkf ...
    do1e la0e la0e do1e re1f so0e so0e ...
    mi1e so1e mi1e re1e do1f do1f ...
    la0e do1e re1e mi1e re1e do1e so0e mi0e ...
    la0f la0f blke blke blkf ...
    ];
    part3 = [la0f la0e so0e la0f do1f ...
    re1e mi1s re1s do1e re1e mi1f mi1f ...
    la0e la1e la1e so1e re1e mi1s re1s do1e re1e ...
    mi1f mi1f blke blke blkf ...
    do1e la0e la0e do1e re1f so0e so0e ...
    mi1e so1e mi1e re1e do1f do1e do1e ...
    la0e do1e re1e mi1e so1e mi1e mi1e so1e ...
    la1f la1f la1f la1f ...
    ];
    part4 = [la1e la1s la1s la1e la1e la1e la1s so1s mi1e re1e ...
    re1e re1s re1s mi1e mi1s so1s mi1e mi1s re1s do1e do1s la0s ...
    la0f la0e so0e la0f la0e do1e ...
    re1e mi1s re1s do1e re1e mi1f mi1f ...
    la1e so1e mi1e re1e so1e mi1e re1e do1e ...
    do1f do1f la0s do1s re1s mi1s re1s do1s la0s do1s
    ];
    part5 = [do2e do2s do2s la1e la1s la1s so1e so1s so1s mi1e mi1s mi1s ...
    re1e mi1s re1s do1e la0s so0s la0s so0s do1s re1s mi1s so1s la1s re2s ...
    do2f do2f blks blks blks blks do1e re1e ...
    mi1f mi1f mi1f so1e mi1e ...
    la1f la1f la1e do1e so1e mi1e ...
    re1f re1e re1s re1s re1e re1e do1e re1e ...
    mi1f mi1e mi1s mi1s mi1e re1s do1s ti0e do1s re1s ...
    mi1f mi1f mi1f so1e mi1e ...
    do2f la1f la1f la1e do1e ...
    re1f so1f so1f la1f ...
    ti1f ti1f ti1f ti1f ...
    ];
    part6 = [blkf blkf mi1e so1e mi1e so1e ...
    mi1f la0e la0s la0s do1f la0e mi1s la0s ...
    do1e do1s do1s re1e do1s re1s mi1f mi1f ...
    mi1f la0e la0s la0s so1f re1e re1s re1s ...
    mi1f mi1f mi1s re1s do1s la0s mi0s re0s mi0s so0s ...
    do1f la0e la0s la0s re1f so0e so0s so0s ...
    mi0f so0e so0s so0s do1f do1f ...
    la0f do1e do1s la0s mi1e mi1s mi1s re1e re1s mi1s ...
    ];
    % Combination, v1 is complete version, v2 is simple version.
    v1 = [part0 part1 part1 part2 part3 part4 part0 part1 part1 part2 part3 part5 part3 part6 part3];
    v2 = [part0 part1 part1 part2 part3 part5 part3 part6 part3];
    % Let's rock ^_^
    s = v1;
    s = s/max(s);
    sound(s,fs);
    % 画囧
    syms x;
    g=1/(x^2+2*x-3);
    ezplot(g,-10,10);
    % 2D 爱心
    [x,y]=meshgrid(-10:0.01:10);
    z=-(17*x.^2-16*y.*abs(x)+17.*y.^2);
    [c,h]=contourf(z,100);set(h,'linestyle','none')
    % 五星红旗
    function varargout=saxplaxliu(varargin)
    x=[0 0 40 40 0];
    y=[0 13 13 0 0];
    k=40/13;
    fill(x,y,'r')
    hold on
    plot(x,y,'r')
    axis([0 40 0 13])
    seta=pi/6;
    R=1.5;R2=0.55;x0=7;y0=9;seta=0;
    fliu(R,R2,x0,y0,seta,k)
    R=0.6;R2=0.23;x0=15;y0=11.6;seta=-pi/20;
    fliu(R,R2,x0,y0,seta,k)
    R=0.6;R2=0.23;x0=20;y0=10;seta=pi/20;
    fliu(R,R2,x0,y0,seta,k)
    R=0.6;R2=0.23;x0=19;y0=7;seta=pi/25;
    fliu(R,R2,x0,y0,seta,k)
    R=0.6;R2=0.23;x0=16;y0=5;seta=-pi/10;
    fliu(R,R2,x0,y0,seta,k)
    axis off 
    function fliu(R,R2,x0,y0,seta,k)
    x=zeros(1,10);
    y=x;
    for i=1:5
        x(2*(i-1)+1)=R*cos(pi/2+2*pi/5*(i-1)+seta);
        x(2*i)=R2*cos(pi/2+2*pi/5*(i-1)+pi/5+seta);
        y(2*(i-1)+1)=R*sin(pi/2+2*pi/5*(i-1)+seta);
        y(2*i)=R2*sin(pi/2+2*pi/5*(i-1)+pi/5+seta);
    end
    x(11)=x(1);
    y(11)=y(1);
    x=x*k+x0;
    y=y+y0;
    fill(x,y,[1 0.7 0])
    plot(x,y,'y')
    % 光盘
    t = (0:.02:2)*pi;
    r = 0:.02:1; %r = 0.3:.02:1; 
    pcolor(cos(t)'*r,sin(t)'*r,t'*(r==r))
    colormap(hsv(256)), shading interp, axis image off
    %ezsurf('r*cos(t)','r*sin(t)','t',[0 1 0 2*pi])
    %colormap(hsv(256)),shading interp,view(2), axis image off
    展开全文
  • MATLAB发布代码---生成文档pdf

    千次阅读 2019-03-12 22:23:12
    发布MATLAB®代码文件 (.m) 可创建包括您的代码、注释和输出的格式化文档。发布代码的常见原因是与其他人共享文档以用于教学或演示,或者生成您代码的可读外部文档。要在 MATLAB 编辑器中创建同时包含您的代码、格式...

    1、前记:

    发布 MATLAB® 代码文件 (.m) 可创建包括您的代码、注释和输出的格式化文档。发布代码的常见原因是与其他人共享文档以用于教学或演示,或者生成您代码的可读外部文档。要在 MATLAB 编辑器中创建同时包含您的代码、格式化内容和输出的交互式文档,请参阅在实时编辑器中创建实时脚本

    2、步骤----打开要发布的代码文件(m文件)-----点击发布----选择编辑发布选项。如下:

    点击输出文件,选择格式和修改地址,点击发布

    如:源代码为 Robotics System Toolbox中的机器人运动 (3)中的例子

    %% Waypoint tracking demonstration using Robotics System Toolbox
    % This demonstration performs inverse kinematics of a
    % robot manipulator to follow a desired set of waypoints.
    % Copyright 2017-2018 The MathWorks, Inc.
    %% Load and display robot
    clear
    clc
    robot = importrobot('irb_140.urdf');
    axis([-0.6 0.8 -0.6 0.65 0 1.2]);
    show(robot);
    axes.CameraPositionMode = 'auto';
    %% Create a set of desired wayPoints
    wayPoints = [0.5 0.1 0.6;0.5 0.4 0.5]; % Alternate set of wayPoints
    %wayPoints = [0.2 -0.2 0.02;0.15 0 0.28;0.15 0.05 0.2; 0.15 0.09 0.15;0.1 0.12 0.1; 0.04 0.1 0.2;0.25 0 0.15; 0.2 0.2 0.02];
    exampleHelperPlotWaypoints(wayPoints);
    %% Create a smooth curve from the waypoints to serve as trajectory
    trajectory = cscvn(wayPoints');%在点之间创建轨迹
    % Plot trajectory spline and waypoints
    hold on
    fnplt(trajectory,'r',2);
    
    %% Perform Inverse Kinematics for a point in space
    % Add end effector frame, offset from the grip link frame
    eeOffset = 0.01;
    eeBody = robotics.RigidBody('end_effector');
    setFixedTransform(eeBody.Joint,trvec2tform([eeOffset 0 0]));
    addBody(robot,eeBody,'link_6');
    ik = robotics.InverseKinematics('RigidBodyTree',robot);
    weights = [0.1 0.1 0 1 1 1];
    initialguess = robot.homeConfiguration;
    % Calculate the inverse kinematic solution using the "ik" solver 
    % Use desired weights for solution (First three are orientation, last three are translation)
    % Since it is a 4-DOF robot with only one revolute joint in Z we do not
    % put a weight on Z rotation; otherwise it limits the solution space
    numTotalPoints =40;
    % Evaluate trajectory to create a vector of end-effector positions
    eePositions = ppval(trajectory,linspace(0,trajectory.breaks(end),numTotalPoints));
    % Call inverse kinematics solver for every end-effector position using the
    % previous configuration as initial guess
    for idx = 1:size(eePositions,2)
        tform = trvec2tform(eePositions(:,idx)');
        configSoln(idx,:) = ik('end_effector',tform,weights,initialguess);
        initialguess = configSoln(idx,:);
    end
    %% Visualize robot configurations
    title('Robot waypoint tracking visualization')
    hold on
    axis([-0.6 0.8 -0.6 0.65 0 1.3]);
    for idx = 1:size(eePositions,2)
        show(robot,configSoln(idx,:), 'PreservePlot', false,'Frames','off');
        pause(0.1)
    end
    %% Plot joints values
    A = cat(1,configSoln.JointPosition);
    clf
    figure
    stem(A)%overview
    %% Joints
    joint1=A(1:40,1);
    joint2=A(41:80,1);
    joint3=A(81:120,1);
    joint4=A(121:160,1);
    joint5=A(161:200,1);
    joint6=A(201:240,1);
    figure
    stem(joint1,'LineStyle','none','MarkerFaceColor','r','MarkerEdgeColor','g')
    title('Joint关节的值变化')
    hold on
    stem(joint2,'LineStyle','none','MarkerFaceColor','g','MarkerEdgeColor','b')
    stem(joint3,'LineStyle','none','MarkerFaceColor','b','MarkerEdgeColor','y')
    stem(joint4,'LineStyle','none','MarkerFaceColor','y','MarkerEdgeColor','m')
    stem(joint5,'LineStyle','none','MarkerFaceColor','c','MarkerEdgeColor','w')
    stem(joint6,'LineStyle','none','MarkerFaceColor','m','MarkerEdgeColor','b')
    

    发布后生成的PDF文档效果为:

    3、后记:figure图框的利用---打印图窗、点击箭头修改图占框大小、插入图例修改data标签,以便给论文提取所需的图。

     

     

                                                                                                           ----------己亥年二月初六晚

    展开全文
  • 2018数学建模matlab代码

    2020-07-30 23:31:54
    2018数学建模matlab代码
  • 基于MATLAB的拼图游戏设计 内容摘要:MATLAB强大的运算和图形展示功能,使图像...本博文基于MATLAB编程语言,详细介绍了如何利用MATLAB及其图像处理函数进行经典拼图游戏设计,并通过具体方法步骤及相应代码逐...

                                                                               基于MATLAB的拼图游戏设计

    内容摘要:MATLAB强大的运算和图形展示功能,使图像处理变得更加的简单和直观。本博文基于MATLAB编程语言,详细介绍了如何利用MATLAB及其图像处理函数进行经典拼图游戏设计,并通过具体方法步骤及相应代码逐步实现游戏的完美运行。(有详细步骤及代码解释,适合新手以及进阶的朋友参考)

    关键词:拼图游戏;MATLAB;数字图像处理
    本文为博主原创,引用请注明出处http://blog.csdn.net/qq_32892383

     1.前言 

          Matlab是MathWork公司推出的一套高性能的数值计算和可视化软件。它是一个高度集成的系统,集科学计算、图像处理、声音处理于一体,具有极高的编程效率。数字图像处理是一种通过计算机采用一定的算法对图形图像进行处理的技术。数字图像处理技术已经在各个领域上都有了比较广泛的应用。MATLAB强大的运算和图形展示功能,使图像处理变得更加的简单和直观。本文介绍了如何利用MATLAB进行经典拼图游戏设计。拼图游戏是一款非常经典的小游戏,因为它比较简单有趣,可变性很高且耐玩,有利于开发智力,帮助提高动手解决问题的能力。 

          拼图游戏的设计对一个MATLAB语言设计者进行语言提高和进阶都是一个很好的锻炼机会,说起来这个程序是笔者当年大学时完全自己构思摸索的第一个长的完整程序,作为一名刚接触编程语言的菜鸟,在痛苦与激动中整整花了一个星期才完成。如今我已是一名研究生,转眼再看过去写的那些程序,可能诸多不足但那些编程的锻炼确实让我感获良多,面对如今众多的研究课题时,入门编程让我可以从容地用编程语言去释放自己的思想,不必在有好想法时因为编程问题而浇灭灵感的火花。临近年关,辞旧迎新之际,外面的世界熙来攘往,早已沉浸着春节的热闹与喜悦中,我仍要挑个安静的时间总结反思过去一年各方面的得与失。一个想法划过脑海想把前面做过的程序做个整理和改进,分享出来希望能够给刚接触编程的朋友们一点帮助和启发,对于我也是一个总结与提高,期待我们今后一起能够继续学习和进步。

    2.MATLAB的图像处理 

          MATLAB的基本数据单位是矩阵,它的指令表达式与数学,工程中常用的形式十分相似,故用MATLAB来解算问题要比用C、FORTRAN等语言完相同的事情简捷得多。MATLAB支持五种图像类型,即索引图像、灰度图像、二值图像、RGB图像和多帧图像阵列。MATLAB中,一幅图像包含一个数据矩阵,RGB图像分别用红,绿,蓝三个亮度值为一组,代表每个像素的颜色。图像数组为M*N*3,M,N表示图像像素的行列数。MATLAB图像处理工具箱是由一系列支持图像处理操作的函数组成,可以进行诸如几何操作、线性滤波和滤波器设计、图像变换、图像分析与图像增强、二值图像操作以及形态学处理等图像处理操作。

          这里拼图游戏中的图像处理主要是对图像数组的操作,涉及矩阵分割、重组等步骤。本文将在后面几节结合代码进行详细介绍。

    3.设计步骤

          到此为止,前面的内容稍作了解即可,接下来的主要设计思路无需细看但了解大概的流程却是有必要的,毕竟编写程序前还是得清楚到底要做什么的,简洁清晰的设计方案能起到提纲挈领的作用。

          拼图游戏的主要思想是先读入准备好的图片,将存储图像的数据矩阵平均分为9个小的矩阵块,并用一个矩阵元素为1,2,3,4,5,6,7,8,0的3*3的数组矩阵标记每一个小矩阵块。仿照人工随机打乱拼图的方法,将标记矩阵打乱,根据标记矩阵拼接相应的拼图块并显示整个图像,通过设置图形窗口鼠标点击事件的回调函数的方式获得鼠标点击位置的坐标值,判断点击位置并移动相应的拼图块,当拼图顺序完全正确时提示游戏完成。图3.1和图3.2是拼图游戏的程序流程图。

                                                    

                                             图3.1 总体程序流程图(左图)               图3.2 回调函数程序流程图(右图)

          上面流程图的方式可能有点学术,但确实不失为一种好的叙述整个程序设计思想的表示方法。解释一下吧,为了使整个程序整洁清晰,图1中“打乱拼图矩阵”以及”按照标记矩阵显示拼图“步骤都写成了自定义函数,分别为disrupt( )、dramap( ),其功能及具体细节会在后面章节展开。接着需要得到点击鼠标的位置坐标,这里利用figure的WindowButtonDownFcn属性自行定义一个回调函数。此时每次当你在图上按下鼠标的时候,就会转而执行回调函数,整个程序处于监听鼠标事件与调用一次回调函数的循环之中,回调函数的流程如图2中所示。在回调函数中,计算鼠标点击坐标后,根据坐标移动拼图标记矩阵中的元素,这一步由自定义的函数movejig( )完成。然后根据标记矩阵刷新拼图图像,即调用dramap( )函数。最后判断拼图的标记矩阵中元素是否排列正确,如果顺序完全正确则提示游戏完成并结束程序,而不正确时则结束本次的回调函数继续等待鼠标点击。

    3.1 开始程序设计

          首先需要准备一张彩色图片,图片的尺寸最好为正方形(否则不易于后面的处理,而且可能不好看),这里我选择的图片是一张经过裁剪的长宽为300*300的图片,如下文件'jigsawImage.jpeg'

                                                                                         jigsawImage.jpeg

            在matlab中新建一个m文件,这里我命名的文件名为'jigsaw.m',为了方便两个文件放在同一文件夹下,如下图所示。

                                                                                         图3.1.1 文件存放情况

            准备好这些我们就可以正式开始编写程序了,所有代码编写在jigsaw.m文件中,下面将逐个介绍其中的代码及设计细节。

    3.2 分割拼图

          这里我们设计的是一个九宫格的拼图游戏,因此在打乱拼图前需要先将图片平均切割为相等的九份。首先我们来看看MATLAB中图片的储存与表示,执行命令”image=imread('jigsawImage.jpeg');“读入jigsawImage图片(若图片与m文件不在同一位置需输入绝对路径,如image=imread('C:\Users\Administrator\Desktop\jigsaw puzzle\jigsawImage.jpeg');)在MATLAB中的存储情况如图3.2.1所示。

                                                                                       图3.2.1 原图存放情况

          可以看出MATLAB中图片的存储是以矩阵的形式进行,image是个300*300*3的矩阵,300、300分别是矩阵的横纵尺寸。平均分割image矩阵,则第一块小拼图的数据矩阵可以为x1=image(1:100,1:100,:);这行代码的意思是选取image矩阵中横坐标从1到100,纵坐标也从1到100的那部分矩阵数据。可通过下面的代码验证,帮助简单理解

    image=imread('jigsawImage.jpeg'); %读入图片
    figure %产生一个图形窗口
    imshow(image) %显示原图
    axis on %显示坐标轴
    figure
    x1=image(1:100,1:100,:);%分割一个拼图块
    imshow(x1);
    axis on

    在命令窗口执行以上代码,可以看到如下运行结果

                                          

                                                                             图3.2.2 分割演示结果图

          将整幅图像平均分割成9块,为了方便每一块用一个数字表示,从左到右,从上到下开始将9个小拼图块分别标记为1,2,3,4,5,6,7,8,0;其位置及坐标系如图3.2.3所示

                                                                                              图3.2.3 拼图标记
          
          从上图中可以看到每块拼图在原图中的坐标位置,其实也是矩阵的索引范围,因此同样可以通过上面的方式引用标号为2,3,4,5,6,7,8,0的拼图块,代码如下
    x2=image(1:100,101:200,:);%拼图块2矩阵数据
    x3=image(1:100,201:300,:);%拼图块3矩阵数据
    x4=image(101:200,1:100,:);%拼图块4矩阵数据
    x5=image(101:200,101:200,:);%拼图块5矩阵数据
    x6=image(101:200,201:300,:);%拼图块6矩阵数据
    x7=image(201:300,1:100,:);%拼图块7矩阵数据
    x8=image(201:300,101:200,:);%拼图块8矩阵数据
    x0=image(201:300,201:300,:);%拼图块0矩阵数据
    

    按照上面的思路,现在自定义一个从原图中分割拼图并按照相应拼图块的标记截取小拼图的函数choose( ),输入参数为image,index,其中image为原图的数据矩阵,index为要选择的拼图块的标记;输出为x,x是标记为index的小拼图块的数据矩阵。代码如下

    function x = choose(image,index)
    %% 根据索引选择对应位置上的拼图块
    if index > 0 %标记为1,2,3,4,5,6,7,8的拼图块
        % 计算出行数row以及列数column
        row=fix((index-1)/3);
        column=mod(index-1,3);
        % 分割出对应拼图块数据
        x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);
    else
        x=uint8(255*ones(100,100,3));%拼图块0矩阵数据
    end
          首先第3到第6行中当index为1,2,3,...,8时先计算出行数row以及列数column,行数可通过求除以3后的商确定,fix( )是MATLAB中的取整函数,而列数可通过求余数确定,mod( )是求余函数,返回index-1除以3的余数。为了便于按照上面的方法分割矩阵,这里的row、column相当于一个倍数,如x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);则将行列数乘分割间隔100(因为选择的图片大小是300*300的,分成3*3的拼图块所以索引间隔为100,若为其他尺寸的图片应为长宽分别除以3后的结果)即可根据行列数row,column引用相应位置上的小拼图块的数据矩阵了。例如index=4时,经过第5,6行代码计算出的row=1,column=0,代入第8行代码中,则实际x=image(1+1*100:100*2,1+0*100:100*1,:);这与前面代码中写出的”x4=image(101:200,1:100,:);%拼图块4矩阵数据“作用一致。
          当index=0时则执行第9行else下的代码部分,你可能会奇怪,为什么拼图块0不是从imge矩阵中分割而是放到else中了?这是因为0这个位置比较特殊,留作空白处,拼图游戏进行时当空白处附近某个拼图块被点击时,该拼图块就会移动到这个空白位置。这里ones( )函数产生一个100*100*3的全1矩阵,乘255则像素灰度值最亮,显示为全白,最后uint8( )统一数据类型。因此当index=0时,执行else中的代码,输出x为一块全白的拼图块。
     

    3.3 按标记序号矩阵显示拼图

          前面一节介绍了可以通过标记序号分割原图获得小拼图块数据矩阵的方法,一幅拼图可由9块小拼图块拼接而成,因此用一个9个元素的标记矩阵,每个位置上的元素值作为一个标记序号表示相应位置的拼图块,就可以通过这个标记矩阵表示整个的拼图了。          

          这样原图就可以用矩阵 表示,而任意打乱的拼图也可以通过改变矩阵相应位置上的元素值表示了。现在我们编写一个根据标记矩阵显示对应拼图的函数drawmap( ),输入参数为A,A为一幅拼图的标记矩阵,A大小为3*3。代码如下

    function drawmap(A)
    %% 将运算数字与对应拼图对应显示图片
    origin=imread('jigsawImage.jpeg');
    image=origin;
    
    % 对要显示的拼图进行赋值
    for row=1:3
        for col=1:3
        image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=choose(origin,A(row,col));
        end
    end
    
    imshow(image)%显示拼图

          第3行代码读入图片并将原图数据矩阵存储在origin中;第4行中image是要显示的拼图数据矩阵,先预定义与origin相同。接下来对image进行逐个赋值,image每一块数据的赋值通过调用前面编写的choose( )函数完成;第9行中”choose(image,A(row,col))“返回标记矩阵A中第row行第col列的元素表示的那一块拼图块的数据矩阵,而前面的一半image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)与3.2节中选取每个拼图块的作用类似,这里用于对行数row从1到3,列数col从1到3的拼图块矩阵上的元素逐个赋值。经过9次循环9处拼图块的数据赋值完成,最终显示图像image。可以通过下面的代码简单测试一下drawmap( )函数,设置一个标记矩阵Tag_A=[8 4 5;6 0 3;1 7 2],即Tag_A= ,按照该矩阵显示这幅拼图。

    function jigsaw()
    %% 主函数
    Tag_A=[8 4 5; 6 0 3; 1 7 2];
    drawmap(Tag_A);%按照标记矩阵显示拼图
    
    
    function x = choose(image,index)
    %% 根据索引选择对应位置上的拼图块
    if index>0 %标记为1,2,3,4,5,6,7,8的拼图块
        % 计算出行数row以及列数column
        row=fix((index-1)/3);
        column=mod(index-1,3);
        % 分割出对应拼图块数据
        x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);
    else
        x=uint8(255*ones(100,100,3));%拼图块0矩阵数据
    end
    
    
    function drawmap(A)
    %% 将运算数字与对应拼图对应显示图片
    origin=imread('jigsawImage.jpeg');
    image=origin;
    % 对要显示的拼图进行赋值
    for row=1:3
        for col=1:3
        image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=choose(origin,A(row,col));
        end
    end
    imshow(image)%显示拼图

          运行结果如下图所示,对比每个拼图块的标记可以看出函数能实现根据矩阵的值显示拼图了,距离成功又近了一步。

                                                                                         图3.3.1 测试结果

    3.4 移动拼图

          这部分我们要解决一个逻辑问题,那就是怎么移动拼图。例如,在图3.4.1的拼图中,如果鼠标在空白块的左侧一个拼图块内点击一次,此时左侧的那个拼图块应该往空白处移动,但要怎样才能实现这一过程?

                                                          

                                                       图3.4.1 移动拼图过程(左图)                 图3.4.2 拼图行列数(右图)

          为了实现这一过程,这里同样定义一个函数,实现在当前的拼图中根据鼠标所在的行列数移动拼图块,命名为movejig( ) 。输入参数:tag(当前拼图的标记矩阵)、row(鼠标点击位置的行数)、column(鼠标点击位置的列数);输出参数:tag(移动后得到的标记矩阵)。行列数的规定按照图3.4.2的坐标系确定,图3.4.3简单示出了movejig( )函数的大致运行方式。

                                                                                        图3.4.3 函数功能示意图

          这里默认已经知道了鼠标坐标并经过计算得出了鼠标点击处的行列数row,col,至于如何计算将在后面介绍。 movejig( )函数的具体代码如下

    function tag=movejig(tag,row,col)
     %% 4个if分4种情况对不同位置处的点坐标与矩阵行列式统一
        num = tag(row,col);%鼠标位置与号码牌一致
        if (row > 1)&&(tag(row-1,col)==0)%点击位置在第二或第三行,空白块在点击位置的上一行
            tag(row-1,col) = num;%交换两个位置上的值
            tag(row,col) = 0;
        end
        if (row < 3)&&(tag(row+1,col)==0)%点击位置在第一或第二行,空白块在点击位置的下一行
            tag(row+1,col) = num;
            tag(row,col) = 0;
        end
        if (col > 1)&&(tag(row,col-1)==0)%点击位置在第二或第三列,空白块在点击位置的左边一列
            tag(row,col-1) = num;
            tag(row,col) = 0;
        end
        if (col < 3)&&(tag(row,col+1)==0)%点击位置在第二或第三列,空白块在点击位置的右边一列
            tag(row,col+1) = num;
            tag(row,col) = 0;
        end
          第3行根据点击处的行列号可取出点击位置处拼图块的标记,存为num。第4行至第19行分四种情况考虑可能出现的点击情况,第4行if中的条件row>1说明点击位置在第2行或第3行,并且要求tag(row-1,col)==0即点击处的上一行位置上的标记是0(也就是表示空白拼图块),这两个条件同时满足就是表示鼠标点击的拼图块上面一个拼图块是空白块。条件满足后第5,6行就是将点击处的拼图块和上面的空白块的标记值互换,表示点击拼图块上移。同理,后面三种情况空白处分别出现在点击下方、左边、右边同样交换两个拼图块实现移动。其他情况如点击了某个拼图块而这个拼图块相邻位置上没有空白则不满足条件是不会进行任何操作的。
          其实,上面的四个if条件在拼图时是不会有同时满足的情况的,上述代码中的形式需要判断四次条件虽然没错但显得有点多余,在编程时写成嵌套的if...elseif...end形式则更加合理,这里不这么写是为了防止可能有初学的朋友容易混淆而出错,熟悉的朋友可以自行改写。

          movejig( )函数实现的是标记矩阵中相应元素的移动,结合前面编写的显示函数drawmap( )将得到的移动后的标记作为输入就可以显示移动后的拼图了。

    3.5 打乱拼图

          游戏开始时需要将一幅完整的图片打乱,那又要怎么实现呢?读到这里您可能就知道了,整个拼图游戏的实现主要是通过标记矩阵进行操作的,即改变标记矩阵,然后按标记矩阵将拼图显示出来。对此前面已多有铺垫,通过打乱标记矩阵的元素的方法打乱拼图自然也就水到渠成。

          一个简单的想法是,生成一个由0-8的数字随机排列构成的3*3的矩阵作为标记矩阵如下面的矩阵Tag1

          然而这样存在的bug是随机产生的矩阵其实大多通过移动拼图是不能完成正确排序的,这在数学上有相关理论研究可得出结论,不研究数学的笔者就不多说了。这里我的想法是模仿人手动打乱拼图的方式,不断随机移动拼图直至拼图顺序完全打乱。前面介绍了移动拼图的函数,这里随机产生点击的行列数然后调用移动拼图函数movejig( ),重复一定次数则可完成拼图打乱。定义一个打乱拼图函数Disrupt( ),返回一个仿手动打乱之后得到的标记矩阵,MATLAB代码如下
    function y = Disrupt()
    %% 随机打乱原拼图排列顺序
    y =[1,2,3;4,5,6;7,8,0];
    for i = 1:360
        row=randi([1,3]);%产生一个范围在1到3的整数
        col=randi([1,3]);
        y=movejig(y,row,col);%按随机产生的动作打乱拼图
    end
          代码第3行,默认y是一个顺序正确的3*3的矩阵,在第5行for循环中设置移动的次数为360次,每次都产生一个行数row和列数col,其值为1,2,3中随机的一个数,然后第8行调用movejig( )移动拼图。这就仿佛一个人不断在拼图上随机地点击很多次,由于点击拼图块,相应位置上的拼图块就会不断移动。这样做虽然每次盲目产生的row和col不一定都有效,但次数多了无疑会起到打乱拼图的作用。
          接下来就可以测试一下了,新建一个m文件,命名为jigsaw.m,在文件中输入如下代码
    function jigsaw()
    %% 主函数
    Tag_A= Disrupt()%将图像的排列顺序打乱
    drawmap(Tag_A);%按照标记矩阵显示拼图
    
    
    function tag=movejig(tag,row,col)
     %% 4个if分4种情况对不同位置处的点坐标与矩阵行列式统一
        num = tag(row,col);%鼠标位置与号码牌一致
        if (row > 1)&&(tag(row-1,col)==0)%点击位置在第二或第三行,空白块在点击位置的上一行
            tag(row-1,col) = num;%交换两个位置上的值
            tag(row,col) = 0;
        end
        if (row < 3)&&(tag(row+1,col)==0)%点击位置在第一或第二行,空白块在点击位置的下一行
            tag(row+1,col) = num;
            tag(row,col) = 0;
        end
        if (col > 1)&&(tag(row,col-1)==0)%点击位置在第二或第三列,空白块在点击位置的左边一列
            tag(row,col-1) = num;
            tag(row,col) = 0;
        end
        if (col < 3)&&(tag(row,col+1)==0)%点击位置在第二或第三列,空白块在点击位置的右边一列
            tag(row,col+1) = num;
            tag(row,col) = 0;
        end
       
    
    function y = Disrupt()
    %% 随机打乱原拼图排列顺序
    y =[1,2,3;4,5,6;7,8,0];
    
    for i = 1:360
        row=randi([1,3]);%产生一个范围在1到3的整数
        col=randi([1,3]);
        y=movejig(y,row,col);%按随机产生的动作打乱拼图
    end
    
    
    
    function x = choose(image,index)
    %% 根据索引选择对应位置上的拼图块
    if index>0 %标记为1,2,3,4,5,6,7,8的拼图块
        % 计算出行数row以及列数column
        row=fix((index-1)/3);
        column=mod(index-1,3);
        % 分割出对应拼图块数据
        x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);
    else
        x=uint8(255*ones(100,100,3));%拼图块0矩阵数据
    end
    
    
    function drawmap(A)
    %% 将运算数字与对应拼图对应显示图片
    origin=imread('jigsawImage.jpeg');
    image=origin;
    % 对要显示的拼图进行赋值
    for row=1:3
        for col=1:3
        image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=choose(origin,A(row,col));
        end
    end
    imshow(image)%显示拼图
        运行结果如图3.5.1所示

                                                     

                                                                                图3.5.1 打乱拼图测试

    3.6 拼图主函数

          主函数是完成拼图任务的核心,主函数的设计思路是首先将标记矩阵打乱,并按照标记矩阵中的排列显示拼图块,然后需要获得鼠标点击处的位置坐标以移动拼图,每次移动后判断拼图顺序是否已经正确,顺序正确后结束游戏。前面已经完成了标记矩阵的打乱和显示以及根据鼠标位置移动拼图的函数,那么现在的问题就剩下鼠标位置的获取了。

          MATLAB中获取鼠标坐标值有两种途径。第一种是利用ginput( )函数,该函数提供一个十字光标帮助更精确选择所需要的位置并返回坐标值,函数调用形式如[x y]=ginput(1),x,y分别为横纵坐标。这确实为一个简单实用的方法,开始时我就是采用的这种方式,在主函数中利用while循环重复调用ginput( )函数获取每次点击处的坐标值,结果证明是可行的,效果如下图3.6.1所示。

    图3.6.1 利用ginput( )的方式实现效果

          这样的类似方法网上提到很多,让我感觉不太好的一点是这个十字光标精确是精确,但是在这个拼图中显得有些多余,怎么删去这个光标寻找半天,未果。还有就是用while循环编写的代码每次关掉这个图形窗口都会甩出一个大大的类似下图那样的错误,这就让有点小小处女座的我不能忍了,转而编写了另外一个版本。

          第二种方法是利用figure的WindowButtonDownFcn属性定义一个坐标获取的回调函数。当在图上按下鼠标的时候,就会自动执行回调函数来获取坐标值。主函数命名为jigsaw( ),与文件名一致,其代码如下

    function jigsaw()
    %% 主函数
    Tag_A= Disrupt();%将标记矩阵的排列顺序打乱
    drawmap(Tag_A);%按照标记矩阵显示拼图
    
    global Tag;%Tag是标记矩阵,定义成全局变量,方便传递参数
    Tag=Tag_A;
    set(gcf,'windowButtonDownFcn',@ButtonDownFcn);%点击鼠标时调用ButtonDownFcn函数

          代码第3,4行调用前面的函数打乱和显示,不必多说;第6,7行意在将标记矩阵定义成全局变量并赋值为Tag_A,其目的在于在后面的回调函数中需要用到标记矩阵,这样方便传递参数,这里可以不必深究;第8行就是设置windowButtonDownFcn属性的回调函数,gcf表示当前图形窗口句柄,ButtonDownFcn是回调函数名,@ButtonDownFcn表示其函数句柄,整条代码就是设置当在当前图形窗口中点击鼠标时就会转而执行ButtonDownFcn函数。

    3.7 回调函数

          根据上一节的设置每次点击鼠标时就会执行一次回调函数,因此可以在回调函数中编写程序获取当前鼠标位置并据此移动一次拼图,然后判断拼图是否完成。定义回调函数ButtonDownFcn( ),输入参数src、event为系统约定变量,函数代码如下

    function ButtonDownFcn(src,event)
    %% 回调函数,鼠标点击事件发生时调用
    pt=get(gca,'CurrentPoint');%获取当前鼠标点击位置坐标
    xpos=pt(1,1);%鼠标点击处的横坐标实际值
    ypos=pt(1,2);%鼠标点击处的纵坐标实际值
       
    col = ceil(xpos/100);%将横坐标值转换为列数
    row = ceil(ypos/100);%将纵坐标值转换为行数
    
    global Tag; %全局变量声明
    
    if(col<=3&&col>0)&&(row<=3&&row>0)%鼠标点击位置在有效范围内    
        Tag=movejig(Tag,row,col);%按点击位置移动拼图
        
        drawmap(Tag)%显示拼图
        
        order = [1 2 3;4 5 6;7 8 0];%顺序矩阵
        zt = abs(Tag-order);%比较两个矩阵
        if sum(zt(:))==0 %顺序已经完全吻合
            image=imread('jigsawImage.jpeg');
            imshow(image) %游戏完成,补全拼图
            msgbox('You did a good job ,恭喜完成!!!') %提示完成信息
            pause(0.5);%延迟半秒
            close all %游戏结束,关闭所有图像窗口
        end
        
    else
        return
        
    end

          代码第3行利用get( )获取鼠标位置坐标,gca表示获取当前坐标系句柄即在当前坐标系中获取坐标值,CurrentPoint是当前点属性值,返回的pt为一行两列的数组,其元素分别为横纵坐标值。第4,5行是分别取出横纵坐标值,第7,8行代码求出行列数,因为图片的尺寸为300*300,分成3行3列,所以将鼠标坐标值除以100即可得出所在的行列数,如果选取的图片为其他尺寸应除以其他相应的数字。

          第10行声明全局变量Tag,在3.6节中定义过了,这里再度声明表示与前面定义的一致,Tag共享其数值,前面的标记矩阵这里就能使用了。

          第12行中,判断点击鼠标的位置是不是在拼图中,因为在图形窗口中点击时若点击位置不在图片上时,返回的坐标值会出现异常值,避免的方法是只有行列数在1到3内的点击才进行处理,不满足条件时跳至第27行返回,结束本次回调函数的运行。

          第13,15行按照点击的行列数移动拼图的标记矩阵,然后按照标记矩阵显示拼图。第17行定义一个顺序矩阵用于标记矩阵的比较,第18行将移动后的标记矩阵与顺序矩阵相减取绝对值,abs( )为取绝对值函数,可以知道如果两个矩阵完全一致则相减之后的结果每个位置上的元素都为0,反之不然。

          第19行中,if sum(zt(:))==0即如果zt中所有元素的和等于0,满足这个条件时表示游戏完成了,此时将拼图空白的那块补全,第20,21行读取原图然后显示,这一过程连续起来的瞬间就表现为拼图空白处被补全了。

          第22行弹出一个提示窗口,展示的信息为“You did a good job ,恭喜完成!!!”。第23行暂停0.5秒,第24行在暂停半秒之后关闭所有图形窗口,游戏结束。

    4.完整代码

          所有工作完成,完整的程序m文件以及图片文件已经上传大家可以点击链接下载基于MATLAB的拼图游戏,直接打开jigsaw.m文件即可运行程序。下面是完整的MATLAB代码,大家可以自行新建jigsaw.m文件,复制以下代码至文件中同样可以运行拼图程序。注意下载jigsawImage.jpeg图片文件,与jigsaw.m文件放在同一文件夹下。注意,如更换图片需要适当修改程序。

    %% 制作人:吴限
    % 2018年2月14日
    function jigsaw()
    %% 主函数
    Tag_A= Disrupt();%将标记矩阵的排列顺序打乱
    drawmap(Tag_A);%按照标记矩阵显示拼图
    
    global Tag;%Tag是标记矩阵,定义成全局变量,方便传递参数
    Tag=Tag_A;
    set(gcf,'windowButtonDownFcn',@ButtonDownFcn);%点击鼠标时调用ButtonDownFcn函数
    
    
    
    function ButtonDownFcn(src,event)
    %% 回调函数,鼠标点击事件发生时调用
    pt=get(gca,'CurrentPoint');%获取当前鼠标点击位置坐标
    xpos=pt(1,1);%鼠标点击处的横坐标实际值
    ypos=pt(1,2);%鼠标点击处的纵坐标实际值
       
    col = ceil(xpos/100);%将横坐标值转换为列数
    row = ceil(ypos/100);%将纵坐标值转换为行数
    
    global Tag; %全局变量声明
    
    if(col <= 3 && col >0)&&(row <= 3&&row > 0)%鼠标点击位置在有效范围内    
        Tag=movejig(Tag,row,col);%按点击位置移动拼图
        
        drawmap(Tag)%显示拼图
        
        order = [1 2 3;4 5 6;7 8 0];%顺序矩阵
        zt = abs(Tag-order);%比较两个矩阵
        if sum(zt(:))==0 %顺序已经完全吻合
            image=imread('jigsawImage.jpeg');
            imshow(image) %游戏完成,补全拼图
            msgbox('You did a good job ,恭喜完成!!!') %提示完成信息
            pause(0.5);%延迟半秒
            close all %游戏结束,关闭所有图像窗口
        end
        
    else
        return
        
    end
    
    
    
    
    function tag=movejig(tag,row,col)
     %% 4个if分4种情况对不同位置处的点坐标与矩阵行列式统一
        num = tag(row,col);%鼠标位置与号码牌一致
        if (row > 1)&&(tag(row-1,col)==0)%点击位置在第二或第三行,空白块在点击位置的上一行
            tag(row-1,col) = num;%交换两个位置上的值
            tag(row,col) = 0;
        end
        if (row < 3)&&(tag(row+1,col)==0)%点击位置在第一或第二行,空白块在点击位置的下一行
            tag(row+1,col) = num;
            tag(row,col) = 0;
        end
        if (col > 1)&&(tag(row,col-1)==0)%点击位置在第二或第三列,空白块在点击位置的左边一列
            tag(row,col-1) = num;
            tag(row,col) = 0;
        end
        if (col < 3)&&(tag(row,col+1)==0)%点击位置在第二或第三列,空白块在点击位置的右边一列
            tag(row,col+1) = num;
            tag(row,col) = 0;
        end
       
    
    
    function y = Disrupt()
    %% 随机打乱原拼图排列顺序
    y =[1,2,3;4,5,6;7,8,0];
    
    for i = 1:360
        row=randi([1,3]);%产生一个范围在1到3的整数
        col=randi([1,3]);
        y=movejig(y,row,col);%按随机产生的动作打乱拼图
    end
    
    
    
    function x = choose(image,index)
    %% 根据索引选择对应位置上的拼图块
    if index > 0 %标记为1,2,3,4,5,6,7,8的拼图块
        % 计算出行数row以及列数column
        row=fix((index-1)/3);
        column=mod(index-1,3);
        % 分割出对应拼图块数据
        x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);
    else
        x=uint8(255*ones(100,100,3));%拼图块0矩阵数据
    end
    
    function drawmap(A)
    %% 将运算数字与对应拼图对应显示图片
    origin=imread('jigsawImage.jpeg');
    image=origin;
    
    % 对要显示的拼图进行赋值
    for row=1:3
        for col=1:3
        image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)=choose(origin,A(row,col));
        end
    end
    
    imshow(image)%显示拼图

     

    5.反思与总结

     

          MATLAB大多用于数据处理以及工程计算,几乎很少有用MATLAB编写游戏的,这也符合实际情况因为编写游戏毕竟不是MATLAB的专长,其实MATLAB发展至今已经成为一个足够完善的编程语言许多java,c中的功能在MATLAB中同样也能实现。例如MATLAB具有高级图形处理功能,可以通过图形对象的属性完成许多复杂工作,前面鼠标位置的获取用的就是这一功能。

          整个拼图游戏的设计其实可以看成一个数学建模过程,代表拼图块的标记矩阵就是我们建立的模型,通过对这个模型矩阵元素排序问题的求解、分析最终完成这个拼图任务。更多数学建模的知识大家可以自行上网搜索。

          纵观整个拼图游戏的编写,在基本功能上可以改进与提高的地方如下

    一、增加自行挑选设置拼图所用图片的功能。

    二、增加拼图的难度,设计4*4或5*5甚至更复杂的拼图。

    三、利用MATLAB的GUI功能,为游戏设计一个好看的用户图形界面。

    四、设计一个一键完成拼图的算法,让程序以最优步数自行移动拼图完成拼图。实现上可采用原始的方法或者机器学习的算法。

    五、拼图块的形状与移动方式上也可不必局限这一种,稍作创新兴许一个新型的游戏就会被创造出来。

          关于上述的改进之处,有机会将在后面的博文中介绍。

     

    6. 结束语

          这就是利用MATLAB进行拼图游戏编写的全部内容了,虽然拼图游戏本身不足为奇,但利用MATLAB编写的完整程序不多,而且或多或少会有一点小bug,本博文介绍的方法在多次修改之下,其程序严谨没有错误。由于编者能力有限,代码即使经过了多次校对,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。

    【公众号获取】
    本人微信公众号已创建,扫描以下二维码并关注公众号“AI技术研究与分享”,后台回复“JP20180210”即可获取全部资源文件。

     

    展开全文
  • 1.一共包括30多种数学算法,其中有:层次分析法、插值与拟合、微分方程建模、神经网络模型、偏微分方程数值求解、目标规划、灰色系统理论及其...2.每个算法主要包括算法介绍、应用例子介绍、MATLAB代码实现。 3.PDF版本
  • matlab中双百分号%%的作用:代码分块运行

    万次阅读 多人点赞 2017-10-24 15:47:22
    在参考别人的matlab程序中,有时候会看到两个百分号一起...那是因为,%%在matlab代码中的作用是将代码分块,上下两个%%之间的部分作为一块,在运行代码的时候可以分块运行,查看每一块代码的运行情况。常用于调试程序。

    在参考别人的matlab程序中,有时候会看到两个百分号一起:%%,且当光标在这一部分时,颜色会不一样。比如:

    这里写图片描述

    因为%%在matlab代码中的作用是将代码分块,上下两个%%之间的部分作为一块,在运行代码的时候可以分块运行,查看每一块代码的运行情况。常用于调试程序。

    分块运行的方法有两种:

    第一种,将光标放置在要运行的那一块中,然后在工具栏中选择运行节,英文为Run Section

    这里写图片描述这里写图片描述

    第二种,将光标放置在要运行的那一块中,直接按CTRL+ENTER也可以实现分块运行

    使用案例:

    比如你想在本文第一张图中代码绘制的figure中加一个图例,可能你要重新运行整个代码,但分块运行你只要加上图例代码后,按下CTRL+ENTER

    这里写图片描述
    就实现了分块代码的运行了

    另外在有时候需要逐步向别人展示代码运行的结果,用%%分块以后拆开运行,也是很好的选择。或有两个方法进行比较,也可以写在一个文件中分块运行。
    但要注意前后变量的承接,变动关系等等。

    展开全文
  • matlab代码转换成C代码

    千次阅读 2018-11-29 22:47:15
    MATLAB Coder可以从MATLAB代码生成独立的、可读性强、可移植的C/C++代码。本文基于matlab2015a编制,但是也适用于matlab 2014~2016的版本。 1. 使用MATLAB Coder产生C代码的4个步骤: (1) 开发实现特定算法功能的...
  • 自己的Matlab代码整理

    千次阅读 2016-10-11 16:11:36
    自己的Matlab代码整理 生成矩阵: traindata=zeros(4500,4097);1 迭代目录下的所有bmp格式的图片 : filelist = dir(fullfile(DataPath,int2str(i),'*.bmp')); num_file = length(filelist); for i=1:numfile ...
  • Matlab线型、标记、颜色表示代码

    万次阅读 2018-01-25 14:00:43
    最近要用到Matlab画图,学到 plot 函数这里,觉得表示 线型、标记、颜色 的表示代码很容易忘,故在此记下来以便查阅。 Matlab共有5种不同的线型 线型代号 表示线型 - 实线 – 虚线 -. 点画线 ...
  • http://blog.csdn.net/chenbang110/article/details/7604975
  • Matlab里怎么注释掉一段(多行)代码?你可以这样做,先选好你需要注释的那几行,单击右键,选择COMMENT。就可以了。如果要取消就同样选择要取消注释的那几行、依上述同样的操作选择Uncomment.就行了。
  • 如何将Matlab代码带颜色无乱码粘贴到word或网页中  由于经常使用Matlab编程,并需要撰写报告,这就需要将代码附在后面。可是当代码中含有中文时,粘贴到微软的Ofiice的word里会出现乱码,在网上搜索了好长时间...
  • Latex 中插入 Matlab 代码

    万次阅读 多人点赞 2015-07-24 22:21:20
    功能效果主要有如下排版功能: 语法高亮 自动添加边框 自动添加行号 先上图,大家感受一下效果————————————————————开始...\lstset{language=Matlab}\begin{lstlisting} % Plot function f(x) = 2
  • 几种查看Matlab函数源代码的方法

    万次阅读 2014-03-03 14:49:28
    查看源码是学习写代码的一种好方法,这里介绍几种查看Matlab软件自带函数的方法: 1、type函数 在命令窗口输入“type+函数名”,则命令窗口会显示函数的源代码,例如type regress(其中regress是用来做线性回归的...
  • 算法例子 ... 原理 ... 1.定义 遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。 主要特点 ......
  • cmd.exe命令行方式执行matlab代码

    万次阅读 2012-09-05 09:26:13
    matlab代码的命令行运行方式 当你安装完matlab时,matlab会自动将matlab.exe的路径注册到系统的环境变量。如下图: [图1] 这个时候,打开cmd.exe(附件中的命令行)。首先可以验证一下,在cmd中输入matlab,...
  • matlab自动补全功能及代码对齐

    万次阅读 2018-01-11 11:16:55
    1、matlab代码编辑器的智能提示功能很简单,就是通过Tab键来实现。下面在代码串口输入下面的代码: aassd=0; 2、然后们现在想调用aassd,不用一次输完,直接在下面输入一个a,然后按Tab键,可以看到...
  • Matlab代码加密/封装处理

    千次阅读 2014-08-10 13:19:28
    有时候为了保护版权等等,我们不希望对方单位看到我们的代码,而Matlab在这方面也有其自己的加密方法——P文件,P文件是一种类似于安卓odex优化的预载入文件,能够提高Matlab的载入速度和运行速度,同时可以对代码...
1 2 3 4 5 ... 20
收藏数 133,295
精华内容 53,318
关键字:

matlab代码