function xpbombs(arg1,arg2,arg3)
%XPBOMBS Play the minesweeper game.
% There are 13 bombs hidden in the mine field. Try to flag them
% and uncover all of the other spaces without getting blown up.
% In each non-bomb square is printed the number of adjacent
% squares which contain bombs.
%
% Use the FLAG button to toggle in and out of flag mode. When
% in flag mode, clicking on any covered square places a flag on it.
% Clicking on any flag removes it.
%
% At any time during the game, the number of remaining unflagged
% bombs is shown in the upper left.
%
% NEW stops the game and creates a new minefield.
%
% CLOSE closes the game window.
% Mark W. Reichelt 4-30-93
% Modified by N. Gulley, 10-10-96
% Copyright 1984-2005 The MathWorks, Inc.
% $Revision: 5.9.4.7 $ $Date: 2011/09/03 22:39:31 $
persistent h minefield cntmines rows cols t nummines remaining
persistent HEIGHT WIDTH BWIDTH BHEIGHT textHndl
persistent flagHndl bomb hidden flag hb nhb hflag
if nargin < 1,
arg1 = 'start';
end;
if strcmp(arg1,'start') ;
rows = 8; %16;
cols = 8; %30;
nummines = 13; %99;
BWIDTH = 35;
SWIDTH = 0;
BHEIGHT = 35;
SHEIGHT = 0;
WIDTH = BWIDTH + SWIDTH;
HEIGHT = BHEIGHT + SHEIGHT;
bomb = [
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 2 2 2 2 2 1 1 2 1 1 1 1
1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1
1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1
1 1 1 2 2 2 1 1 2 2 2 2 2 2 1 1 1 1
1 1 1 2 2 2 1 1 2 2 2 2 2 2 1 1 1 1
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1
1 1 1 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1
1 1 1 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1
1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1
1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1
1 1 1 2 1 1 2 2 2 2 2 1 1 2 1 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
];
hidden = bomb + 2*(bomb == 1); % change red background to gray
flag = [
3 3 3 3 3 3 2 3 3 3 3 3
3 3 3 3 3 1 2 3 3 3 3 3
3 3 3 1 1 1 2 3 3 3 3 3
3 1 1 1 1 1 2 3 3 3 3 3
3 3 3 1 1 1 2 3 3 3 3 3
3 3 3 3 3 1 2 3 3 3 3 3
3 3 3 3 3 3 2 3 3 3 3 3
3 3 3 3 3 3 2 3 3 3 3 3
3 3 3 3 3 3 2 3 3 3 3 3
3 3 3 3 3 2 2 2 3 3 3 3
3 3 3 3 2 2 2 2 2 3 3 3
3 3 3 2 2 2 2 2 2 2 3 3
];
xoff = 45;
pos = get(0,'DefaultFigurePosition');
figure('Name','XPBombs','NumberTitle','off',...
'Resize','off',...
'Visible','off',...
'Color',192/255*[1 1 1], ...
'WindowButtonDownFcn','xpbombs(''windowbuttondownfcn'')',...
'WindowButtonUpFcn','xpbombs(''windowbuttonupfcn'')');
colormap([1 0 0;0 0 0;.65 .65 .65;1 1 1]); % red, black, gray, white
a = axes('Units','pixels',...
'PlotBoxAspectRatio',[1 1 1],...
'Position',[WIDTH+xoff,HEIGHT,cols*WIDTH-SWIDTH,rows*HEIGHT-SHEIGHT],...
'Color','none',...
'Box','on', ...
'XLim',[0 cols*WIDTH-SWIDTH],...
'YLim',[0 rows*HEIGHT-SHEIGHT], ...
'XColor','k','YColor','k',...
'YDir','reverse', ...
'Tag','mainaxes', ...
'Xtick',[],'Ytick',[]);
hold on; % so we can do small images later
h = zeros(rows,cols); % button handles
t = zeros(rows,cols); % text handles
hflag = zeros(rows,cols); % flag image handles
for m = 1:rows
for n = 1:cols
h(m,n) = uicontrol('Style','Pushbutton',...
'Units','pixels',...
'Position',[n*WIDTH+xoff,m*HEIGHT,BWIDTH,BHEIGHT],...
'UserData',[m,n]); % stuff m,n into UserData
end
end
nhb = 0; % number of handles to bomb images
for m = 1:rows
line('XData',[0,cols*WIDTH],'YData',[m*HEIGHT m*HEIGHT],...
'Color','k','LineWidth',1);
end
for n = 1:cols
line('XData',[n*WIDTH,n*WIDTH],'YData',[0,rows*HEIGHT],...
'Color','k','LineWidth',1);
end
textHndl = uicontrol('Style','text',...
'BackgroundColor',192/255*[1 1 1], ...
'Units','pixels',...
'FontSize',24, ...
'FontWeight','bold', ...
'Position', [WIDTH+xoff (rows+2)*HEIGHT 2*WIDTH WIDTH],...
'String',num2str(nummines));
%====================================
% Information for all buttons
yInitPos=0.90;
top=0.95;
left=0.80;
bottom=0.05;
btnWid=0.15;
btnHt=0.10;
% Spacing between the button and the next command's label
spacing=0.04;
%====================================
% The CONSOLE frame
frmBorder=0.02;
yPos=0.05-frmBorder;
frmPos=[left-frmBorder yPos btnWid+2*frmBorder 0.9+2*frmBorder];
uicontrol( ...
'Style','frame', ...
'Units','normalized', ...
'Position',frmPos, ...
'BackgroundColor',[0.50 0.50 0.50]);
%====================================
% The FLAG button
btnNumber=1;
yPos=top-(btnNumber-1)*(btnHt+spacing);
labelStr=getString(message('MATLAB:demos:shared:LabelFlag'));
callbackStr='';
% Generic button information
btnPos=[left yPos-btnHt btnWid btnHt];
flagHndl=uicontrol( ...
'Style','checkbox', ...
'Units','normalized', ...
'Position',btnPos, ...
'String',labelStr, ...
'Callback',callbackStr, ...
'BackgroundColor',[0.50 0.50 0.50]);
%====================================
% The NEW button
btnNumber=2;
yPos=top-(btnNumber-1)*(btnHt+spacing);
labelStr=getString(message('MATLAB:demos:shared:LabelNew'));
callbackStr='xpbombs(''newgame'')';
% Generic button information
btnPos=[left yPos-btnHt btnWid btnHt];
uicontrol( ...
'Style','pushbutton', ...
'Units','normalized', ...
'Position',btnPos, ...
'String',labelStr, ...
'Callback',callbackStr);
%====================================
% The INFO button
labelStr=getString(message('MATLAB:demos:shared:LabelInfo'));
callbackStr='xpbombs(''info'')';
infoHndl=uicontrol( ...
'Style','pushbutton', ...
'Units','normalized', ...
'Position',[left bottom+btnHt+spacing btnWid btnHt], ...
'String',labelStr, ...
'Callback',callbackStr);
%====================================
% The CLOSE button
labelStr=getString(message('MATLAB:demos:shared:LabelClose'));
callbackStr='close(gcf)';
closeHndl=uicontrol( ...
'Style','pushbutton', ...
'Units','normalized', ...
'Position',[left bottom btnWid btnHt], ...
'String',labelStr, ...
'Callback',callbackStr);
set(gcf, ...
'Visible','on', ...
'Color',192/255*[1 1 1]); % only after all is built
xpbombs('newgame');
elseif strcmp(arg1,'newgame'),
axes(findobj(gcf,'Tag','mainaxes'));
remaining = nummines;
set(textHndl,'String',num2str(remaining));
minefield = rand(rows,cols);
[temp,index] = sort(minefield(:));
minefield = (minefield <= minefield(index(nummines)));
% disp(flipud(minefield)) % for cheating
% look east, left, down, up to count adjacent mines
east = (2:cols); west = (1:cols-1); north = (1:rows-1); south = (2:rows);
cntmines = zeros(rows,cols);
cntmines(:,west) = cntmines(:,west) + minefield(:,east);
cntmines(:,east) = cntmines(:,east) + minefield(:,west);
cntmines(north,:) = cntmines(north,:) + minefield(south,:);
cntmines(south,:) = cntmines(south,:) + minefield(north,:);
cntmines(north,west) = cntmines(north,west) + minefield(south,east);
cntmines(north,east) = cntmines(north,east) + minefield(south,west);
cntmines(south,west) = cntmines(south,west) + minefield(north,east);
cntmines(south,east) = cntmines(south,east) + minefield(north,west);
for i = 1:nhb % delete any bomb images
delete(hb(i))
end
nhb = 0;
for m = 1:rows
for n = 1:cols
set(h(m,n),'Visible','on','Callback','xpbombs(''buttondown'')');
if t(m,n) ~= 0 % delete any text
delete(t(m,n));
t(m,n) = 0;
end
if hflag(m,n) ~= 0 % delete any flag images
delete(hflag(m,n));
hflag(m,n) = 0;
end
end
end
set(flagHndl,'Value',0); % default is not to be in flag mode
set(gcf,'Color',192/255*[1 1 1]);
elseif strcmp(arg1,'buttondown')
axes(findobj(gcf,'Tag','mainaxes'));
userdata = get(gco,'UserData');
m = userdata(1);
n = userdata(2);
if get(flagHndl,'Value') == 1 % if in flag mode
hflag(m,n) = image([(n-1)*WIDTH+4,(n-1)*WIDTH+2+BWIDTH-5],...
[(rows-m)*HEIGHT+4,(rows-m)*HEIGHT+2+BHEIGHT-5],flag);
set(h(m,n),'Visible','off'); % turn off button
remaining = remaining - 1;
set(textHndl,'String',num2str(remaining));
drawnow
else
if minefield(m,n) % if a bomb
nhb = 1;
hb(nhb) = image([(n-1)*WIDTH+2,(n-1)*WIDTH+2+BWIDTH-2],...
[(rows-m)*HEIGHT+2,(rows-m)*HEIGHT+2+BHEIGHT-2],bomb);
set(h(m,n),'Visible','off'); % turn off button
set(gcf,'Color','r'); % flash "boom"
drawnow;
set(gcf,'Color','k');
drawnow;
for i = 1:rows % uncover all bombs
for j = 1:cols
set(h(i,j),'CallBack',''); % disable all button presses after boom
if minefield(i,j) && (i ~= m || j ~= n)
nhb = nhb + 1;
hb(nhb) = image([(j-1)*WIDTH+2,(j-1)*WIDTH+2+BWIDTH-2],...
[(rows-i)*HEIGHT+2,(rows-i)*HEIGHT+2+BHEIGHT-2],...
hidden);
set(h(i,j),'Visible','off');
end
end
end
else
xpbombs('uncover',m,n);
end;
end
elseif strcmp(arg1,'windowbuttondownfcn')
axes(findobj(gcf,'Tag','mainaxes'));
if get(flagHndl,'Value') == 1
pt = get(gca,'CurrentPoint');
m = rows - (floor(pt(1,2) / HEIGHT) + 1) + 1;
n = floor(pt(1,1) / WIDTH) + 1;
if 1 <= m && m <= rows && 1 <= n && n <= cols
if hflag(m,n) ~= 0
set(h(m,n),'Visible','on');
delete(hflag(m,n));
hflag(m,n) = 0;
remaining = remaining + 1;
set(textHndl,'String',num2str(remaining));
end
end
drawnow;
end
elseif strcmp(arg1,'uncover')
axes(findobj(gcf,'Tag','mainaxes'));
m = arg2;
n = arg3;
if strcmp(get(h(m,n),'Visible'),'on')
set(h(m,n),'Visible','off');
c = cntmines(m,n);
if c > 0
t(m,n) = text('Units','pixels',...
'Position',[(n-0.5)*WIDTH,(m-0.5)*HEIGHT],...
'FontSize',18,...
'HorizontalAlignment','center');
if c == 1
set(t(m,n),'String',num2str(c),'Color','r');
elseif c == 2
set(t(m,n),'String',num2str(c),'Color','b');
elseif c == 3
set(t(m,n),'String',num2str(c),'Color','g');
elseif c == 4
set(t(m,n),'String',num2str(c),'Color','y');
elseif c == 5
set(t(m,n),'String',num2str(c),'Color','c');
elseif c == 6
set(t(m,n),'String',num2str(c),'Color','m');
elseif c == 7
set(t(m,n),'String',num2str(c),...
'Color',[1,.6471,0]); % orange
elseif c == 8
set(t(m,n),'String',num2str(c),...
'Color',[.8588,.5098,.8588]); % violet
end
else % if a zero, open all squares around it
if m > 1
if n > 1, xpbombs('uncover',m-1,n-1), end;
xpbombs('uncover',m-1,n);
if n < cols, xpbombs('uncover',m-1,n+1), end;
end
if n > 1, xpbombs('uncover',m,n-1), end;
if n < cols, xpbombs('uncover',m,n+1), end;
if m < rows
if n > 1, xpbombs('uncover',m+1,n-1), end;
xpbombs('uncover',m+1,n);
if n < cols, xpbombs('uncover',m+1,n+1), end;
end
end
end
elseif strcmp(arg1,'info')
helpwin(mfilename);
end % if strcmp(arg1,'start')