MATLAB實現(xiàn)五子棋游戲(雙人對戰(zhàn)、可悔棋)
本文實例為大家分享了MATLAB實現(xiàn)五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
程序介紹:
1、此游戲只可用于雙人對戰(zhàn)。
2、棋盤顏色、棋盤格數(shù)、棋子顏色等參數(shù)均可自由設(shè)置
3、鼠標點擊非棋盤區(qū)域可悔棋。
一、游戲界面

二、主程序及函數(shù)
1、主程序
%Author:LeiZhen
%Date:2018-03-12
%此程序只下五子棋,并判斷勝負關(guān)系
clear all;
clc
%定義顏色
Color_QiPanBack=[135,206,255];
Color_ChessLine=[100,100,100];
%獲勝連子數(shù)
Num_Victory=5;
Dpixel=33;
NumCell=14;%棋盤格的行或列數(shù)
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);
%獲得距離鼠標點擊點最近的下棋點的坐標,并保證點擊的下棋點在棋盤內(nèi)
if x_col_Chess<max(xcol_ChessLine)+Dpixel/2&&x_col_Chess>min(xcol_ChessLine)-Dpixel/2&&y_row_Chess<max(yrow_ChessLine)+Dpixel/2&&y_row_Chess>min(yrow_ChessLine)-Dpixel/2
for x_i=xcol_ChessLine
if abs(x_col_Chess-x_i)<Dpixel/2;
x_col_Chess=x_i;
end
end
for y_i=yrow_ChessLine
if abs(y_row_Chess-y_i)<Dpixel/2;
y_row_Chess=y_i;
end
end
%點擊悔棋區(qū)(棋盤外的區(qū)域)悔棋
else
[x_col_LuoZi_old,y_row_LuoZi_old]=find(M_LuoZi(:,:,2)==max(max(M_LuoZi(:,:,2))));
x_col_Chess_old=(x_col_LuoZi_old-1)*Dpixel+Wid_edge+1;
y_row_Chess_old=(y_row_LuoZi_old-1)*Dpixel+Wid_edge+1;
if NumChess>=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
%落子并防止重復(fù)在同一個下棋點落子
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','對局結(jié)束','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','對局結(jié)束','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、畫棋盤函數(shù)
%Author:LeiZhen
%Date:2018-03-12
function [M_QiPan, xcol_ChessLine,yrow_ChessLine]=QiPan(NumCell, Dpixel, Wid_edge,Color_QiPanBack,Color_ChessLine)
%此程序為畫五子棋盤的程序
%NumCell為棋盤格數(shù)
%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<radius_Dot^2
M_QiPan(Num,j,:)=Color_ChessLine;
end
end
end
end
end
end
3、下棋或悔棋函數(shù)
%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&&i<x_col_Chess
M_QiPan(j,i,:)=Color_QiPanBack;
elseif x_col_Chess==Wid-Wid_edge&&i>x_col_Chess
M_QiPan(j,i,:)=Color_QiPanBack;
end
if y_row_Chess==Wid_edge+1&&j<y_row_Chess
M_QiPan(j,i,:)=Color_QiPanBack;
elseif y_row_Chess==Wid-Wid_edge&&j>y_row_Chess
M_QiPan(j,i,:)=Color_QiPanBack;
end
end
end
end
end
end
4、勝負判斷函數(shù)
%Author:LeiZhen
%Date:2018-03-12
function Victory_flag=Victory_Judge(M_LuoZi,x_col_LuoZi,y_row_LuoZi,State)
%對一方是否獲勝的判斷函數(shù)
%M_LuoZi為下棋點的矩陣
%x_col_LuoZi為下棋列數(shù)
%y_row_LuoZi下棋行數(shù)
%State為M_LuoZi矩陣某點的下棋狀態(tài),黑棋(1)或白棋(2)或無棋(0),以及每步棋的序號
%NumCell為棋盤格數(shù)
%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<y_row_LuoZi
if M_LuoZi(i,abs(x_col_LuoZi-y_row_LuoZi)+i,1)==State&&M_LuoZi(i+1,abs(x_col_LuoZi-y_row_LuoZi)+i+1,1)==State&&M_LuoZi(i+2,abs(x_col_LuoZi-y_row_LuoZi)+i+2,1)==State&&M_LuoZi(i+3,abs(x_col_LuoZi-y_row_LuoZi)+i+3,1)==State&&M_LuoZi(i+4,abs(x_col_LuoZi-y_row_LuoZi)+i+4,1)==State
Victory_flag=1;
break;
end
end
end
if y_row_LuoZi+x_col_LuoZi<=NumCell+2&&y_row_LuoZi+x_col_LuoZi-i>=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、光標函數(shù)(由庫函數(shù)改動而來)
%此函數(shù)為庫函數(shù)的修改,僅將十字光標改為箭頭光標,改動位置為第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<CTCH>
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 <Return> 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<AGROW>
y = [y;pt(1,2)]; %#ok<AGROW>
b = [b;button]; %#ok<AGROW>
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<NASGU>
% 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<CTCH>
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
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
OpenMP?Parallel?Construct的實現(xiàn)原理詳解
在本篇文章當中我們將主要分析?OpenMP?當中的?parallel?construct?具體時如何實現(xiàn)的,以及這個?construct?調(diào)用了哪些運行時庫函數(shù),并且詳細分析這期間的參數(shù)傳遞,需要的可以參考一下2023-01-01
M1 Macbook vscode C++ debug調(diào)試實現(xiàn)
本文主要介紹了M1 Macbook vscode C++ debug調(diào)試,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
C語言詳細分析講解關(guān)鍵字enum與sizeof及typedef的用法
在?C?語言中經(jīng)常會見到?enum、sizeof、typedef,那么我們今天就來講解下它們?nèi)齻€,enum是C語言中的一種自定義類型,它是一種枚舉類型,sizeof是編譯器的內(nèi)置指示符,用于計算類型或變量所占內(nèi)存打小,typedef用于給一個已經(jīng)存在的數(shù)據(jù)類型重命名,本質(zhì)上不能產(chǎn)生新的類型2022-04-04

