MATLAB五子棋游戏(双人对战,可悔棋)

程序介绍:1、此游戏只可用于双人对战。

                 2、棋盘颜色、棋盘格数、棋子颜色等参数均可自由设置

                 3、鼠标点击非棋盘区域可悔棋。

一、游戏界面

MATLAB五子棋游戏(双人对战,可悔棋)_第1张图片

二、主程序及函数

1、主程序

%Author:LeiZhen
%Date:2018-03-12
%此程序只下五子棋,并判断胜负关系
clear all;
clc
%定义颜色
Color_QiPanBack=[135,206,255];
Color_ChessLine=[100,100,100];
%获胜连子数
Num_Victory=5;
Dpixel=33;
NumCell=14;%棋盘格的行或列数
Wid_edge=18;
[M_QiPan,xcol_ChessLine,yrow_ChessLine]=QiPan(NumCell,Dpixel,Wid_edge,Color_QiPanBack,Color_ChessLine);
imshow(M_QiPan);
set (gcf,'Position',[600,45,625,625]);
set (gca,'Position',[0,0,1,1]);
hold on,
%棋半径
radius_Chess=15;
M_LuoZi=zeros(NumCell+1,NumCell+1,2);
VictoryB=0;
VictoryW=0;
StateB=1;
StateW=2;
NumChess=0;
for i=1:(NumCell+1)^2
    [x_col_Chess, y_row_Chess]=ginput_pointer(1);
    %获得距离鼠标点击点最近的下棋点的坐标,并保证点击的下棋点在棋盘内
    if x_col_Chessmin(xcol_ChessLine)-Dpixel/2&&y_row_Chessmin(yrow_ChessLine)-Dpixel/2
        for x_i=xcol_ChessLine
            if abs(x_col_Chess-x_i)=1
            M_QiPan=Chess(M_QiPan,x_col_Chess_old,y_row_Chess_old,radius_Chess,3,Wid_edge,Dpixel,Color_QiPanBack,Color_ChessLine);
            imshow(M_QiPan);
            NumChess=NumChess-1;
            M_LuoZi(x_col_LuoZi_old,y_row_LuoZi_old,1)=0;
            M_LuoZi(x_col_LuoZi_old,y_row_LuoZi_old,2)=0;
        end
        continue;
    end
    %落子并防止重复在同一个下棋点落子
    x_col_LuoZi=(x_col_Chess-Wid_edge-1)/Dpixel+1;
    y_row_LuoZi=(y_row_Chess-Wid_edge-1)/Dpixel+1;
    if M_LuoZi(x_col_LuoZi,y_row_LuoZi,1)==0
        NumChess=NumChess+1;
        M_LuoZi(x_col_LuoZi,y_row_LuoZi,2)=NumChess;
        if mod(NumChess,2)==1
            M_QiPan=Chess(M_QiPan,x_col_Chess,y_row_Chess,radius_Chess,1,Wid_edge,Dpixel,Color_QiPanBack,Color_ChessLine);
            imshow(M_QiPan);
            M_LuoZi(x_col_LuoZi,y_row_LuoZi,1)=StateB; %落子为黑棋
            VictoryB=Victory_Judge(M_LuoZi,x_col_LuoZi,y_row_LuoZi,StateB);
        elseif mod(NumChess,2)==0
            M_QiPan=Chess(M_QiPan,x_col_Chess,y_row_Chess,radius_Chess,2,Wid_edge,Dpixel,Color_QiPanBack,Color_ChessLine);
            imshow(M_QiPan);
            M_LuoZi(x_col_LuoZi,y_row_LuoZi,1)=StateW; %落子为白棋
            VictoryW=Victory_Judge(M_LuoZi,x_col_LuoZi,y_row_LuoZi,StateW);
        end
    end
    %显示获胜信息
    if VictoryB==1
        %普通对话框
        h=dialog('name','对局结束','position',[500 350 250 100]);
        uicontrol('parent',h,'style','text','string','黑棋获胜!','position',[35 35 200 50],'fontsize',30);
        uicontrol('parent',h,'style','pushbutton','position',[150 5 80 30],'fontsize',20,'string','确定','callback','delete(gcbf)');
        break;
    elseif VictoryW==1
        %普通对话框
        h=dialog('name','对局结束','position',[500 350 250 100]);
        uicontrol('parent',h,'style','text','string','白棋获胜!','position',[35 35 200 50],'fontsize',30);
        uicontrol('parent',h,'style','pushbutton','position',[150 5 80 30],'fontsize',20,'string','确定','callback','delete(gcbf)');
        break;
    end
end

2、画棋盘函数

%Author:LeiZhen
%Date:2018-03-12
function [M_QiPan, xcol_ChessLine,yrow_ChessLine]=QiPan(NumCell, Dpixel, Wid_edge,Color_QiPanBack,Color_ChessLine)
%此程序为画五子棋盘的程序
%NumCell为棋盘格数
%Dpixel为相邻棋盘线间的像素间隔
%Wid_edge为棋盘边缘的像素宽度
%Color_QiPanBack为棋盘背景颜色
%Color_ChessLine为棋盘线的颜色
%M_QiPan为棋盘矩阵
%xcol_ChessLine为棋盘列线
%yrow_ChessLine为棋盘行线
NumSum=1+Dpixel*NumCell+Wid_edge*2;
xcol_ChessLine=Wid_edge+1:Dpixel:NumSum-Wid_edge;%列
yrow_ChessLine=Wid_edge+1:Dpixel:NumSum-Wid_edge;%行
M_QiPan=uint8(ones(NumSum,NumSum,3));
M_QiPan(:,:,1)=M_QiPan(:,:,1)*Color_QiPanBack(1);
M_QiPan(:,:,2)=M_QiPan(:,:,2)*Color_QiPanBack(2);
M_QiPan(:,:,3)=M_QiPan(:,:,3)*Color_QiPanBack(3);
%画棋盘线
for i=xcol_ChessLine
    M_QiPan(i,Wid_edge+1:NumSum-Wid_edge,:)=ones(NumSum-2*Wid_edge,1)*Color_ChessLine;
end
for j=yrow_ChessLine
    M_QiPan(Wid_edge+1:NumSum-Wid_edge,j,:)=ones(NumSum-2*Wid_edge,1)*Color_ChessLine;
end
%画9个小圆点
radius_Dot=5;
P1=Wid_edge+1+Dpixel*3:Dpixel*(NumCell/2-3):Wid_edge+1+Dpixel*(NumCell-3);
for ti=P1
    for tj=P1
        for Num=ti-radius_Dot:ti+radius_Dot;
            for j=tj-radius_Dot:tj+radius_Dot;
                if (Num-ti)^2+(j-tj)^2

3、下棋或悔棋函数

%Author:LeiZhen
%Date:2018-03-12
function M_QiPan=Chess(M_QiPan,x_col_Chess,y_row_Chess,radius_Chess,BorW,Wid_edge,Dpixel,Color_QiPanBack,Color_ChessLine)
%此程序下棋或者悔棋
%M_QiPan为棋盘矩阵
%xcol_ChessLine为棋盘列线
%yrow_ChessLine为棋盘行线
%radius_Chess为棋的像素半径
%BorW为下棋选择,1黑棋,2白棋,3悔棋
%Wid_edge为棋盘矩阵中的棋盘边缘的像素宽度
%Dpixel为棋盘矩阵中的相邻棋盘线间的像素间隔
%Color_QiPanBack为棋盘背景颜色
%Color_ChessLine为棋盘线的颜色
Color_BChess=[54,54,54];
Color_WChess=[255,240,245];
[Wid,Hei,Deep]=size(M_QiPan);
for i=x_col_Chess-radius_Chess:x_col_Chess+radius_Chess
    for j=y_row_Chess-radius_Chess:y_row_Chess+radius_Chess
        if (i-x_col_Chess)^2+(j-y_row_Chess)^2<=radius_Chess^2
            if BorW==1%黑棋
                M_QiPan(j,i,:)=Color_BChess;
            elseif BorW==2%白棋
                M_QiPan(j,i,:)=Color_WChess;
            elseif BorW==3%悔棋
                M_QiPan(j,i,:)=Color_QiPanBack;
                %对于不是棋盘边缘的棋子
                if i==x_col_Chess||j==y_row_Chess
                    M_QiPan(j,i,:)=Color_ChessLine;
                end
                %悔棋点是否为小圆点
                if ((i-x_col_Chess)^2+(j-y_row_Chess)^2<5^2)&&...
                    (x_col_Chess==Wid_edge+1+Dpixel*3||x_col_Chess==floor(Wid/2)+1||x_col_Chess==Wid-Wid_edge-Dpixel*3)&&...
                    (y_row_Chess==Wid_edge+1+Dpixel*3||y_row_Chess==floor(Wid/2)+1||y_row_Chess==Wid-Wid_edge-Dpixel*3)            
                    M_QiPan(j,i,:)=Color_ChessLine;
                end
                %对于棋盘边缘的棋子
                if x_col_Chess==Wid_edge+1&&ix_col_Chess
                    M_QiPan(j,i,:)=Color_QiPanBack;
                end
                if y_row_Chess==Wid_edge+1&&jy_row_Chess
                    M_QiPan(j,i,:)=Color_QiPanBack;
                end
            end
        end
    end
end
end

4、胜负判断函数

%Author:LeiZhen
%Date:2018-03-12
function Victory_flag=Victory_Judge(M_LuoZi,x_col_LuoZi,y_row_LuoZi,State)
%对一方是否获胜的判断函数
%M_LuoZi为下棋点的矩阵
%x_col_LuoZi为下棋列数
%y_row_LuoZi下棋行数
%State为M_LuoZi矩阵某点的下棋状态,黑棋(1)或白棋(2)或无棋(0),以及每步棋的序号
%NumCell为棋盘格数
%Victory_flag为胜利标志
NumCell=length(M_LuoZi)-1;
Victory_flag=0;
for i=1:NumCell-3
    if M_LuoZi(i,y_row_LuoZi,1)==State&&M_LuoZi(i+1,y_row_LuoZi,1)==State&&M_LuoZi(i+2,y_row_LuoZi,1)==State&&M_LuoZi(i+3,y_row_LuoZi,1)==State&&M_LuoZi(i+4,y_row_LuoZi,1)==State
        Victory_flag=1;
        break;
    end
    if M_LuoZi(x_col_LuoZi,i,1)==State&&M_LuoZi(x_col_LuoZi,i+1,1)==State&&M_LuoZi(x_col_LuoZi,i+2,1)==State&&M_LuoZi(x_col_LuoZi,i+3,1)==State&&M_LuoZi(x_col_LuoZi,i+4,1)==State
        Victory_flag=1;
        break;
    end
    if abs(x_col_LuoZi-y_row_LuoZi)+i<=NumCell-3
        if x_col_LuoZi>=y_row_LuoZi
            if M_LuoZi(abs(x_col_LuoZi-y_row_LuoZi)+i,i,1)==State&&M_LuoZi(abs(x_col_LuoZi-y_row_LuoZi)+i+1,i+1,1)==State&&M_LuoZi(abs(x_col_LuoZi-y_row_LuoZi)+i+2,i+2,1)==State&&M_LuoZi(abs(x_col_LuoZi-y_row_LuoZi)+i+3,i+3,1)==State&&M_LuoZi(abs(x_col_LuoZi-y_row_LuoZi)+i+4,i+4,1)==State
                Victory_flag=1;
                break;
            end
        elseif x_col_LuoZi=5
        if M_LuoZi(y_row_LuoZi+x_col_LuoZi-i,i,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-i-1,i+1,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-i-2,i+2,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-i-3,i+3,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-i-4,i+4,1)==State
            Victory_flag=1;
            break;
        end
    elseif y_row_LuoZi+x_col_LuoZi>NumCell+2&&y_row_LuoZi+x_col_LuoZi+i<=NumCell*2-1
        offset=NumCell+2;
        if M_LuoZi(y_row_LuoZi+x_col_LuoZi-offset+i,offset-i,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-offset+i+1,offset-i-1,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-offset+i+2,offset-i-2,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-offset+i+3,offset-i-3,1)==State&&M_LuoZi(y_row_LuoZi+x_col_LuoZi-offset+i+4,offset-i-4,1)==State
            Victory_flag=1;
            break;
        end
    end
end
end

5、光标函数(由库函数改动而来)

%此函数为库函数的修改,仅将十字光标改为箭头光标,改动位置为第88行
function [out1,out2,out3] = ginput_pointer(arg1)
%GINPUT Graphical input from mouse.
%   [X,Y] = GINPUT(N) gets N points from the current axes and returns
%   the X- and Y-coordinates in length N vectors X and Y.  The cursor
%   can be positioned using a mouse.  Data points are entered by pressing
%   a mouse button or any key on the keyboard except carriage return,
%   which terminates the input before N points are entered.
%
%   [X,Y] = GINPUT gathers an unlimited number of points until the
%   return key is pressed.
%
%   [X,Y,BUTTON] = GINPUT(N) returns a third result, BUTTON, that
%   contains a vector of integers specifying which mouse button was
%   used (1,2,3 from left) or ASCII numbers if a key on the keyboard
%   was used.
%
%   Examples:
%       [x,y] = ginput;
%
%       [x,y] = ginput(5);
%
%       [x, y, button] = ginput(1);
%
%   See also GTEXT, WAITFORBUTTONPRESS.

%   Copyright 1984-2011 The MathWorks, Inc.
%   $Revision: 5.32.4.18 $  $Date: 2011/05/17 02:35:09 $

out1 = []; out2 = []; out3 = []; y = [];
c = computer;
if ~strcmp(c(1:2),'PC')
    tp = get(0,'TerminalProtocol');
else
    tp = 'micro';
end

if ~strcmp(tp,'none') && ~strcmp(tp,'x') && ~strcmp(tp,'micro'),
    if nargout == 1,
        if nargin == 1,
            out1 = trmginput(arg1);
        else
            out1 = trmginput;
        end
    elseif nargout == 2 || nargout == 0,
        if nargin == 1,
            [out1,out2] = trmginput(arg1);
        else
            [out1,out2] = trmginput;
        end
        if  nargout == 0
            out1 = [ out1 out2 ];
        end
    elseif nargout == 3,
        if nargin == 1,
            [out1,out2,out3] = trmginput(arg1);
        else
            [out1,out2,out3] = trmginput;
        end
    end
else
    
    fig = gcf;
    figure(gcf);
    
    if nargin == 0
        how_many = -1;
        b = [];
    else
        how_many = arg1;
        b = [];
        if  ischar(how_many) ...
                || size(how_many,1) ~= 1 || size(how_many,2) ~= 1 ...
                || ~(fix(how_many) == how_many) ...
                || how_many < 0
            error(message('MATLAB:ginput:NeedPositiveInt'))
        end
        if how_many == 0
            % If input argument is equal to zero points,
            % give a warning and return empty for the outputs.
            
            warning (message('MATLAB:ginput:InputArgumentZero'));
        end
    end
    
    % Setup the figure to disable interactive modes and activate pointers. 
    initialState = setupFcn(fig);
    set(gcf, 'pointer', 'arrow');
    
    % onCleanup object to restore everything to original state in event of
    % completion, closing of figure errors or ctrl+c. 
    c = onCleanup(@() restoreFcn(initialState));
       
    
    % We need to pump the event queue on unix
    % before calling WAITFORBUTTONPRESS
    drawnow
    char = 0;
    
    while how_many ~= 0
        % Use no-side effect WAITFORBUTTONPRESS
        waserr = 0;
        try
            keydown = wfbp;
        catch %#ok
            waserr = 1;
        end
        if(waserr == 1)
            if(ishghandle(fig))
                cleanup(c);
                error(message('MATLAB:ginput:Interrupted'));
            else
                cleanup(c);
                error(message('MATLAB:ginput:FigureDeletionPause'));
            end
        end
        % g467403 - ginput failed to discern clicks/keypresses on the figure it was
        % registered to operate on and any other open figures whose handle
        % visibility were set to off
        figchildren = allchild(0);
        if ~isempty(figchildren)
            ptr_fig = figchildren(1);
        else
            error(message('MATLAB:ginput:FigureUnavailable'));
        end
        %         old code -> ptr_fig = get(0,'CurrentFigure'); Fails when the
        %         clicked figure has handlevisibility set to callback
        if(ptr_fig == fig)
            if keydown
                char = get(fig, 'CurrentCharacter');
                button = abs(get(fig, 'CurrentCharacter'));
            else
                button = get(fig, 'SelectionType');
                if strcmp(button,'open')
                    button = 1;
                elseif strcmp(button,'normal')
                    button = 1;
                elseif strcmp(button,'extend')
                    button = 2;
                elseif strcmp(button,'alt')
                    button = 3;
                else
                    error(message('MATLAB:ginput:InvalidSelection'))
                end
            end
            axes_handle = gca;
            drawnow;
            pt = get(axes_handle, 'CurrentPoint');
            
            how_many = how_many - 1;
            
            if(char == 13) % & how_many ~= 0)
                % if the return key was pressed, char will == 13,
                % and that's our signal to break out of here whether
                % or not we have collected all the requested data
                % points.
                % If this was an early breakout, don't include
                % the  key info in the return arrays.
                % We will no longer count it if it's the last input.
                break;
            end
            
            out1 = [out1;pt(1,1)]; %#ok
            y = [y;pt(1,2)]; %#ok
            b = [b;button]; %#ok
        end
    end
    
    % Cleanup and Restore 
    cleanup(c);
    
    if nargout > 1
        out2 = y;
        if nargout > 2
            out3 = b;
        end
    else
        out1 = [out1 y];
    end
    
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function key = wfbp
%WFBP   Replacement for WAITFORBUTTONPRESS that has no side effects.

fig = gcf;
current_char = []; %#ok

% Now wait for that buttonpress, and check for error conditions
waserr = 0;
try
    h=findall(fig,'Type','uimenu','Accelerator','C');   % Disabling ^C for edit menu so the only ^C is for
    set(h,'Accelerator','');                            % interrupting the function.
    keydown = waitforbuttonpress;
    current_char = double(get(fig,'CurrentCharacter')); % Capturing the character.
    if~isempty(current_char) && (keydown == 1)          % If the character was generated by the
        if(current_char == 3)                           % current keypress AND is ^C, set 'waserr'to 1
            waserr = 1;                                 % so that it errors out.
        end
    end
    
    set(h,'Accelerator','C');                           % Set back the accelerator for edit menu.
catch %#ok
    waserr = 1;
end
drawnow;
if(waserr == 1)
    set(h,'Accelerator','C');                          % Set back the accelerator if it errored out.
    error(message('MATLAB:ginput:Interrupted'));
end

if nargout>0, key = keydown; end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end

function initialState = setupFcn(fig)

% Store Figure Handle. 
initialState.figureHandle = fig; 

% Suspend figure functions
initialState.uisuspendState = uisuspend(fig);

% Disable Plottools Buttons
initialState.toolbar = findobj(allchild(fig),'flat','Type','uitoolbar');
if ~isempty(initialState.toolbar)
    initialState.ptButtons = [uigettool(initialState.toolbar,'Plottools.PlottoolsOff'), ...
        uigettool(initialState.toolbar,'Plottools.PlottoolsOn')];
    initialState.ptState = get (initialState.ptButtons,'Enable');
    set (initialState.ptButtons,'Enable','off');
end

% Setup FullCrosshair Pointer without warning. 
oldwarnstate = warning('off', 'MATLAB:hg:Figure:Pointer');
set(fig,'Pointer','fullcrosshair');
warning(oldwarnstate);

% Adding this to enable automatic updating of currentpoint on the figure 
set(fig,'WindowButtonMotionFcn',@(o,e) dummy());

% Get the initial Figure Units
initialState.fig_units = get(fig,'Units');
end

function restoreFcn(initialState)
if ishghandle(initialState.figureHandle)
    % Figure Units
    set(initialState.figureHandle,'Units',initialState.fig_units);
    set(initialState.figureHandle,'WindowButtonMotionFcn','');
    
    % Plottools Icons
    if ~isempty(initialState.toolbar) && ~isempty(initialState.ptButtons)
        set (initialState.ptButtons(1),'Enable',initialState.ptState{1});
        set (initialState.ptButtons(2),'Enable',initialState.ptState{2});
    end
    
    % UISUSPEND
    uirestore(initialState.uisuspendState);
end
end

function dummy()
% do nothing, this is there to update the GINPUT WindowButtonMotionFcn. 
end

function cleanup(c)
if isvalid(c)
    delete(c);
end
end



你可能感兴趣的:(MATLAB编程)