function demin3(mode, Param1)
% demin3.m (Version 3.0)
% Just type 'demin3' to launch the game with a fixed number of mines.
% Extended modes : demin3(mode, Param1)
% mode =
% 'start' - Will launch the game as before
% 'cheat' - Cheat mode, Mines are disabled
% Param1 [1 x 3] vector (optional - require 1st parameter if used)
% Param1(1) = Nb of Lines
% Param1(2) = Nb of Columns
% Param1(3) = Nb of Mines
% Example:
% demin3('cheat', [5, 5, 3]) set the game options to
% cheating mode (mines are disabled)
% 5 Lines , 5 Columns and 3 Mines
% Have fun !
%
% F. Andrianasy, Vendredi 7 Mars 1997, 13:09 (demin3.m)
% Laboratoire PARC, Universite Paris 6, Paris, France
% (fidi@robo.jussieu.fr)
global SeeMinesFlag
global CheatFlag
global ParamFlag
global NbLin
global NbCol
global NbMines
global SafeCases
global Remain
global Tab1
global Tab2
global hfig
global hbTab
global hETab
global BadMoveFlag
global TermineFlag
global LeftMouseFlag
global RightMouseFlag
global EnableFlag
global BackCol
global ETabFore
global ETabBack
global bTabFore
global bTabBack
global LastLoc
% ------------------------------------
% Boot
% ------------------------------------
if nargin == 0,
mode = 'start';
ParamFlag = 0;
end;
if nargin > 0,
if strcmp(mode, 'SeeMines')
SeeMinesFlag = 1;
mode = 'start';
else
SeeMinesFlag = 0;
end;
% ------------------------------------
% You're cheating !
% ------------------------------------
if strcmp(mode, 'cheat')
CheatFlag = 1;
mode = 'start';
else
CheatFlag = 0;
end;
end;
if nargin > 1,
if exist('Param1') == 1,
NbLin = Param1(1);
NbCol = Param1(2);
NbMines = Param1(3);
ParamFlag = 1;
else
ParamFlag = 0;
end;
end;
% ------------------------------------
% Initialisations
% ------------------------------------
if strcmp(mode, 'start')
%disp(mode);
clc;
% ------------------------------------
% LES DEUX TABLEAUX Tab1 et Tab2
% ------------------------------------
% Dimensions: nb de cases
% ------------------------------------
if ParamFlag == 0,
NbLin = 8;
NbCol = 10;
end;
% ------------------------------------
% Le nombre de mines
% ------------------------------------
if ParamFlag == 0,
NbMines = ceil((NbLin * NbCol)/6);
end;
% ------------------------------------
% Le nombre de cases non minees
% ------------------------------------
SafeCases = ((NbLin * NbCol) - NbMines);
% ------------------------------------
% Les emplacements des mines (aleatoires)
% ------------------------------------
Tab1 = zeros(NbLin, NbCol);
for k = 1: NbMines
col = floor(rand * (NbCol)) + 1;
lin = floor(rand * (NbLin)) + 1;
% ------------------------------------
% Il faut eviter de mettre
% deux mines au meme endroit
% ------------------------------------
while Tab1(lin, col) == -1,
col = floor(rand * (NbCol)) + 1;
lin = floor(rand * (NbLin)) + 1;
end;
Tab1(lin, col) = -1;
% ------------------------------------
% On remplit les 8 cases voisins
% avec le nombre de mines adjacents
% ------------------------------------
% ------------------------------------
% Haut + Gauche
% ------------------------------------
j = lin-1; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Haut + Centre
% ------------------------------------
j = lin-1; i = col;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Haut + Droite
% ------------------------------------
j = lin-1; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Milieu + Gauche
% ------------------------------------
j = lin; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Milieu + Droit
% ------------------------------------
j = lin; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Gauche
% ------------------------------------
j = lin+1; i = col-1;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Centre
% ------------------------------------
j = lin+1; i = col;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Droit
% ------------------------------------
j = lin+1; i = col+1;
if (j<=NbLin) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
end; % for k...
%Tab1
% ------------------------------------
% Fin des initialisations de Tab1
% ------------------------------------
% ------------------------------------
% On cree un second tableau
% avec des caracteres ascii
% pour:
% l'affichage
% le suivi des operations
% ------------------------------------
Tab2 = ones(NbLin, NbCol) * '-';
% ------------------------------------
% FENETRE GRAPHIQUE
% ------------------------------------
% ------------------------------------
% Dimensions de chaque bouton
% ------------------------------------
LargBtn = 20;
HautBtn = 20;
% ------------------------------------
% Dimensions de la fenetre
% ------------------------------------
BackCol = [.71 .71 .71];
% BackCol = 'k';
LargFig = LargBtn * NbCol;
HautFig = (HautBtn * NbLin) + 1.5*HautBtn;
DimFig = [189 265 LargFig HautFig];
hfig = figure('Position', DimFig);
figName = sprintf('Demineur [%d*/%d]', NbMines, NbLin*NbCol);
set(hfig, 'Resize', 'off');
set(hfig, 'NumberTitle', 'off', ...
'Name', figName, ...
'MenuBar', 'none', ...
'Color', BackCol); % Jaune = [1 1 0.4]
set(hfig, 'ButtonDownFcn', 'get(gcf, ''SelectionType'')');
% ------------------------------------
% Matrice de zones d'Editions
% ------------------------------------
ETabFore = 'c';
ETabBack = [.0 .0 .5];
%%% ETabFore = 'k';
%%% ETabBack = [.6 .6 .6];
hETab = 0 * Tab1;
for j = 1:NbLin
for i = 1:NbCol
c = Tab2(j, i);
DimTxt = [ (i-1)*LargBtn (j-1)*HautBtn LargBtn-1 HautBtn-1 ];
hETab(j, i) = uicontrol( 'Style', 'Text', ...
'Units', 'pixels', ...
'Pos', DimTxt, ...
'String', sprintf('%c', c), ...
'BackgroundColor', ETabBack, ...
'Fore', ETabFore);
% -------------------------------------------
% La couleur depend du nb de mines
% -------------------------------------------
v = Tab1(j, i);
if (v == 1),
set(hETab(j, i), 'Fore', [0 .85 .85 ]);
elseif (v == 2),
set(hETab(j, i), 'Fore', [1 .7 1]);
elseif (v > 2 & v <= 4),
set(hETab(j, i), 'Fore', 'y');
elseif (v > 4 & v <= 6),
set(hETab(j, i), 'Fore', 'r');
elseif (v > 6 & v <= 8),
set(hETab(j, i), 'Fore', 'g');
end;
end;
end;
% ------------------------------------
% Dessin des boutons
% ------------------------------------
% callstr = 'get( get( get(0, ''CurrentFigure''), ''CurrentObject''), ''Userdata'')';
callstr = 'demin3(''demine'')';
hbTab = 0 * Tab1;
for j = 1:NbLin
for i = 1:NbCol
DimBtn = [ (i-1)*LargBtn (j-1)*HautBtn LargBtn HautBtn ];
hbTab(j, i) = uicontrol( 'Style', 'PushButton', ...
'Units', 'pixels', ...
'Pos', DimBtn, ...
'Callback', callstr, ...
'String', '', ...
'Interruptible', 'off', ...
'UserData', [j, i] );
end;
end;
bTabFore = get(hbTab(1, 1), 'Fore');
bTabBack = get(hbTab(1, 1), 'Back');
% ------------------------------------
% Cheat mode
% ------------------------------------
mines = find(Tab1 == -1);
for k = 1: length(mines),
if SeeMinesFlag,
set(hbTab(mines(k)), 'String', '*');
end;
if CheatFlag,
set(hbTab(mines(k)), 'Callback', '');
end;
end;
% ------------------------------------
% Bouton BYE !
% ------------------------------------
DimBye = [LargFig/2 HautFig-1.3*HautBtn (LargFig/2)-4 HautBtn];
hbBYE = uicontrol( 'Style', 'PushButton', ...
'Units', 'pixels', ...
'Pos', DimBye, ...
'Callback', 'demin3(''fini'')', ...
'String', 'Bye !');
% ------------------------------------
% Bouton CLEAR
% ------------------------------------
DimClr = [2 HautFig-1.3*HautBtn (LargFig/2)-4 HautBtn];
hbBYE = uicontrol( 'Style', 'PushButton', ...
'Units', 'pixels', ...
'Pos', DimClr, ...
'Callback', 'demin3(''clear'')', ...
'String', 'Clear');
% ------------------------------------
% Apres chaque click de la souris
% ------------------------------------
elseif strcmp(mode, 'demine')
% disp(['Mode: ', mode]);
% ------------------------------------
% Le handle du bouton courant
% ------------------------------------
hbCurrent = get( get(0, 'CurrentFigure'), 'CurrentObject');
% ------------------------------------
% Coordonnees de ce bouton
% (stockees dans lui-meme ('UserData') )
% ------------------------------------
A = get(hbCurrent , 'Userdata');
BadMoveFlag = 0;
TermineFlag = 0;
LeftMouseFlag = 0;
RightMouseFlag = 0;
EnableFlag = 0;
% ------------------------------------
%
% ------------------------------------
l = 'l'; L = l; % Explosion d'une case
r = 'r'; R = r; % Marquage d'une case
% ------------------------------------
% Coordonnees lignes et colonnes
% ------------------------------------
lin = A(1); %
col = A(2); %
Op = l; % Force a Left
% ------------------------------------
% Flags
% ------------------------------------
if upper(Op) == 'L',
RightMouseFlag = 0;
LeftMouseFlag = 1;
end;
% ------------------------------------
% Deminable ou pas ...
% ------------------------------------
if Tab2(lin, col) == '-',
EnableFlag = 1;
end;
% ------------------------------------
% Bad move !!!!
% ------------------------------------
if Tab1(lin, col) == -1 & LeftMouseFlag & EnableFlag,
Mines = find(Tab1 == -1);
Tab2(Mines) = ones(size(Mines)) * '*' ;
LastLoc = [lin, col];
BadMoveFlag = 1;
%%% break;
end;
% ------------------------------------
% GOOD MOVE
% ------------------------------------
if Tab1(lin, col) == 0 & LeftMouseFlag & EnableFlag,
% ------------------------------------
% Traitement des '0' dans Tab2
% ------------------------------------
while 1,
Tab2(lin, col) = '.' ;
% ------------------------------------
% On copie le contenu des cases autour
% de la case poitee dans Tab1
% Conditions:
% Tab1(j, i) > - 1
% Tab2(j, i) == '-', "vierge"
% ------------------------------------
% Haut + Gauche
j = lin-1; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Haut + Centre
j = lin-1; i = col;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Haut + Droite
j = lin-1; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Milieu + Gauche
j = lin; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Milieu + Droit
j = lin; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Bas + Gauche
j = lin+1; i = col-1;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Bas + Centre
j = lin+1; i = col;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Bas + Droit
j = lin+1; i = col+1;
if (j<=NbLin) & (i<=NbCol),
if (Tab1(j, i) > - 1) & (Tab2(j, i) == '-')
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end;
end;
% Fin --------------------------------
% Copies des contenus des cases voisins
% de la case poitee dans Tab1
% ------------------------------------
% ------------------------------------
% Traitement des cases == 0 de Tab2
% Quelles cases sont activees et a zero ?
% ------------------------------------
ZeroMine = find(Tab2 == '0');
if length(ZeroMine) == 0,
break;
else
% ------------------------------------
% Calul des lignes et colonnes
% a cause de "find" qui linearise
% ------------------------------------
lin = rem(ZeroMine(1), NbLin);
if lin == 0,
lin = NbLin;
end;
col = ceil(ZeroMine(1) / NbLin);
end; % if length(ZeroMine) == 0
end; % while
% Fin --------------------------------
% Traitement des '0' dans Tab2
% ------------------------------------
end; % if Tab1(lin, col) == 0
% Fin --------------------------------
% GOOD MOVE
% ------------------------------------
% ------------------------------------
% Pres d'une mine !!!!!!
% ------------------------------------
if Tab1(lin, col) > 0 & LeftMouseFlag & EnableFlag,
% ------------------------------------
% On recopie la case
% ------------------------------------
j = lin; i = col;
Tab2(j, i) = sprintf('%d', Tab1(j, i));
end; % if Tab1(lin, col) > 0
% ------------------------------------
% Detection de la reussite
% Cette partie fonctionne seulement
% quand on peut "marquer" les mines
% ------------------------------------
LocMines = find(Tab1 < 0); % Position des mines
LocFlags = find(Tab2 == 'F'); % Positions des vos flags
SameLen = length(LocMines) == length(LocFlags) ; % Nb de flags identiques ?
SameVal = [];
if SameLen,
SameVal = LocMines == LocFlags ; % Memes positions ?
end;
if (SameVal), % Si oui
TermineFlag = 1; % alors sortir tout de suite
return; % avec le flag TermineFlag mis a 1
else
SameVal = 0; % Sinon, re-init. pour la securite
end;
% ------------------------------------
% 2e Detection de la reussite
% Toutes les cases ont ete deblayees
% Compte le nombre de cases deblayees
% ------------------------------------
Cleaned = find( (Tab2 >= '1' & Tab2 <= '8') | (Tab2 == '.'));
CleanedLen = length(Cleaned);
Remain = SafeCases - CleanedLen;
if Remain == 0,
TermineFlag = 1; % alors sortir tout de suite
%%% disp('OK!')
else
TermineFlag = 0;
end;
% ------------------------------------
% En vue d'un autre cycle
% ------------------------------------
RightMouseFlag = 0;
LeftMouseFlag = 0;
EnableFlag = 0;
% ------------------------------------
% Va afficher le contenu de Tab2
% ------------------------------------
demin3('affiche');
% ------------------------------------
% Affichage
% ------------------------------------
elseif strcmp(mode, 'affiche')
% disp(['Mode: ', mode]);
% ------------------------------------
% Titre de la figure
% ------------------------------------
figName = sprintf('Demineur [%d*/%d]', NbMines, Remain);
set(hfig, 'Name', figName);
if BadMoveFlag
% ------------------------------------
% You loose !
% ------------------------------------
set(hfig, 'Name', 'Ooops, You loose !!!');
set(hfig, 'Color', BackCol + .15);
for j = 1:size(Tab2, 1),
for i = 1:size(Tab2, 2),
c = Tab2(j, i);
% ------------------------------------
% Change la couleur des mines
% ------------------------------------
if (c == '*')
set(hETab(j, i), 'String', sprintf('%c', Tab2(j, i)));
%%% set(hETab(j, i), 'Fore', 'w', 'Back', ETabBack);
%%% set(hETab(j, i), 'Fore', 'k', 'Back', [.7 .7 .7]);
set(hETab(j, i), 'Fore', 'w', 'Back', [.7 .7 .7]);
set(hbTab(j, i), 'Visible', 'off');
end;
% ------------------------------------
% INVALIDE TOUS LES BOUTONS
% ------------------------------------
set(hbTab(j, i), 'Callback', '');
end;
end;
% ------------------------------------
% La mine qui a sautee !
% ------------------------------------
set(hETab(LastLoc(1), LastLoc(2)), 'Back', [.5 0 0], 'Fore', 'y');
else
% ------------------------------------
% Regular move
% ------------------------------------
pointTab2 = find(Tab2 == '.'); pointTab2Len = length(pointTab2);
for i = 1:pointTab2Len,
set(hbTab(pointTab2(i)), 'Visible', 'off');
set(hETab(pointTab2(i)), 'String', '');
end
nmbrTab2 = find(Tab2 >= '0' & Tab2 <= '8'); nmbrTab2Len = length(nmbrTab2);
for i = 1:nmbrTab2Len,
set(hbTab(nmbrTab2(i)), 'Visible', 'off');
set(hETab(nmbrTab2(i)), 'String', sprintf('%c', Tab2(nmbrTab2(i))) );
end
% ------------------------------------
% You win !
% ------------------------------------
if TermineFlag
%%% disp('You win !!!')
%%% break;
set(hfig, 'Name', 'You win !!!');
%%% pause(1);
%%% set(hfig, 'Name', ' YOU WIN !!!');
%%% pause(1);
end;
end;
drawnow;
% ------------------------------------
% Traitement du bouton 'Clear'
% ------------------------------------
elseif strcmp(mode, 'clear')
% ------------------------------------
% Titre de la figure
% ------------------------------------
figName = sprintf('Demineur [%d*/%d]', NbMines, NbLin*NbCol);
set(hfig, 'Name', figName);
set(hfig, 'Color', BackCol);
% ------------------------------------
% RE-INITIALISATION DE Tab1 et Tab2
% Devrait etre dans un sous-prog.
% ------------------------------------
% Tab1 = zeros(NbLin, NbCol);
Tab1 = 0 * Tab1;
for k = 1: NbMines
col = floor(rand * (NbCol)) + 1;
lin = floor(rand * (NbLin)) + 1;
% ------------------------------------
% Il faut eviter de mettre
% deux mines au meme endroit
% ------------------------------------
while Tab1(lin, col) == -1,
col = floor(rand * (NbCol)) + 1;
lin = floor(rand * (NbLin)) + 1;
end;
Tab1(lin, col) = -1;
% ------------------------------------
% On remplit les 8 cases voisins
% avec le nombre de mines adjacents
% ------------------------------------
% ------------------------------------
% Haut + Gauche
% ------------------------------------
j = lin-1; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Haut + Centre
% ------------------------------------
j = lin-1; i = col;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Haut + Droite
% ------------------------------------
j = lin-1; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Milieu + Gauche
% ------------------------------------
j = lin; i = col-1;
if (j>0) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Milieu + Droit
% ------------------------------------
j = lin; i = col+1;
if (j>0) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Gauche
% ------------------------------------
j = lin+1; i = col-1;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Centre
% ------------------------------------
j = lin+1; i = col;
if (j<=NbLin) & (i>0),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
% ------------------------------------
% Bas + Droit
% ------------------------------------
j = lin+1; i = col+1;
if (j<=NbLin) & (i<=NbCol),
if (Tab1(j, i) > - 1)
Tab1(j, i) = Tab1(j, i) + 1;
end;
end;
end; % for k...
%Tab1
% ------------------------------------
% Fin des initialisations de Tab1
% ------------------------------------
% ------------------------------------
% On cree un second tableau
% avec des caracteres ascii
% pour:
% l'affichage
% le suivi des operations
% ------------------------------------
Tab2 = ones(NbLin, NbCol) * '-';
% ------------------------------------
% RAZ Flags
% ------------------------------------
BadMoveFlag = 0;
TermineFlag = 0;
LeftMouseFlag = 0;
RightMouseFlag = 0;
EnableFlag = 0;
% ------------------------------------
% Re-Set Callbacks
% ------------------------------------
for j = 1:size(Tab2, 1),
for i = 1:size(Tab2, 2),
set(hETab(j, i), 'Fore', ETabFore, 'Back', ETabBack);
% -------------------------------------------
% Couleur des chiffres depend du nb de mines
% -------------------------------------------
v = Tab1(j, i);
if (v == 1),
set(hETab(j, i), 'Fore', [0 .85 .85 ]);
elseif (v == 2),
set(hETab(j, i), 'Fore', [1 .7 1]);
elseif (v > 2 & v <= 4),
set(hETab(j, i), 'Fore', 'y');
elseif (v > 4 & v <= 6),
set(hETab(j, i), 'Fore', 'r');
elseif (v > 6 & v <= 8),
set(hETab(j, i), 'Fore', 'g');
end;
% ------------------------------------
% RE-VALIDE TOUS LES BOUTONS
% ------------------------------------
set(hbTab(j, i), 'Fore', bTabFore, 'Back', bTabBack);
set(hbTab(j, i), 'Callback', 'demin3(''demine'')');
% ------------------------------------
% Cheat mode
% ------------------------------------
set(hbTab(j, i), 'String', '');
if SeeMinesFlag,
mines = find(Tab1 == -1);
for k = 1: length(mines),
set(hbTab(mines(k)), 'String', '*');
end;
end;
set(hbTab(j, i), 'Visible', 'on');
end;
end;
% Fin --------------------------------
% Re-Set Callbacks
% ------------------------------------
% drawnow;
% ------------------------------------
% Traitement du bouton 'Bye'
% ------------------------------------
elseif strcmp(mode, 'fini')
% disp(mode);
close(hfig);
clc;
disp(' ')
disp('----------------------------------------------------- ')
disp(' Thanks for playing with Demin3.m ');
disp(' by ');
disp(' Fidimahery ANDRIANASY ');
disp(' (fidi@robo.jussieu.fr) ')
disp('----------------------------------------------------- ')
drawnow;
return;
end; % suite de if ... elseif
end % ...of function demin3.m