function openMineSweeper(dim,nMines,fig)
% openMineSweeper - Matthieu Aussal - Copyright 2015 - Licence CC BY-NC-SA 4.0
% CMAP - Ecole Polytechnique, Route de Saclay, 91128 Palaiseau CEDEX France
% For any informations, please contact  : matthieu.aussal@polytechnique.edu
% "run openMineSweeper([10,10],10,1)", play with left and right mouse buttons
global Buttons Mines Results
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Results  = zeros(dim);                                 % Random mine matrix
perm = randperm(dim(1)*dim(2));     
Results(perm(1:min(nMines,dim(1)*dim(2)))) = -1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Mines = zeros(dim+2);                                % Expanded mine matrix
indL  = 2:dim(1)+1;   indC = 2:dim(2)+1; 
Mines(indL,indC) = Results;
for i = -1:1
    for j = -1:1
        if ~(i == 0 && j == 0)
            Mines(indL,indC) = Mines(indL,indC) + ...
                (Mines(indL+i,indC+j) == -1) .* (Mines(indL,indC) > -1);
        end
    end
end
Mines = Mines(indL,indC);  Results(:) = 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fig = figure(fig); scr = get(0,'ScreenSize');    % Graphical User Interface
set(fig,'Name','openMineSweeper 2015','WindowButtonDownFcn',{@rightClic}, ...
    'Position',[scr(3)/2-10*dim(1) scr(4)/2-10*dim(2) 20*dim(1) 20*dim(2)], ...
    'NumberTitle','off','ToolBar','none','MenuBar','none','Color','w');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Buttons = cell(dim(1),dim(2));                        % Interactive buttons
for i = 1:dim(1)
    for j = 1:dim(2)
        Buttons{i,j} = uicontrol(fig,'Style','pushbutton','Callback',{@leftClic,i,j}, ...
            'Position', [(i-1)*20+1 (j-1)*20+1 20 20],'BackgroundColor','w');
    end
end
end
%=============================== LEFT CLIC ===============================%
function leftClic(~,~,i,j)
global Buttons Mines Results
Results(i,j) = 1;
if Mines(i,j) == -1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Game over
    gameOver()
elseif Mines(i,j) == 0  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% No mine near
    set(Buttons{i,j},'Style','text','Value',1);
    for ii = max(i-1,1):min(i+1,size(Results,1))
        for jj = max(j-1,1):min(j+1,size(Results,2))
            if ~Results(ii,jj)
                leftClic([],[],ii,jj)
            end
        end
    end
else %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Mine(s) near
    set(Buttons{i,j},'Style','text','Value',1,'String',num2str(Mines(i,j)), ...
        'BackgroundColor', [1-Mines(i,j)/8 1  1])
end
if ~sum((Results(:)<=0) - (Mines(:)==-1)) %%%%%%%%%%%%%%%%%%%%%%%%% Victory
    Results(Results(:)==0) = -1; gameOver()
end
end
%============================== RIGHT CLIC ===============================%
function rightClic(~,~)
global Buttons Mines Results
if strcmp(get(gcf,'SelectionType'),'alt')
    pos = get(gcf,'CurrentPoint'); i = ceil(pos(1)/20); j = ceil(pos(2)/20);    
    if Results(i,j) <= 0 
        if Results(i,j) == 0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Selected
            Results(i,j) = -1; 
            set(Buttons{i,j},'BackgroundColor','g');
        else %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Unselected
            Results(i,j) = 0;
            set(Buttons{i,j},'BackgroundColor','w');
        end
    end
    if ~sum((Results(:)==-1) - (Mines(:)==-1)) %%%%%%%%%%%%%%%%%%%% Victory
        gameOver()
    end
end
end
%=============================== GAME OVER ===============================%
function gameOver()
global Buttons Mines Results
for i=1:size(Buttons,1) 
    for j=1:size(Buttons,2)        
        if Mines(i,j) == -1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Find a mine
            set(Buttons{i,j},'Style','text','String','x')            
            if Results(i,j) == Mines(i,j) %%%%%%%%%%%%%%%%%%%% Good Results
                set(Buttons{i,j},'BackgroundColor','g')   
            else                          %%%%%%%%%%%%%%%%%%%%% Bad Results
                set(Buttons{i,j},'BackgroundColor','r')
            end           
        elseif Mines(i,j) == 0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Find nothing 
            set(Buttons{i,j},'Style','text','Value',1,'String','');
        else %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Find mine is near
            set(Buttons{i,j},'Style','text','String', num2str(Mines(i,j)), ...
        	'BackgroundColor', [1-Mines(i,j)/8 1  1])
        end
    end
end
end