function openSnake(dim,n,lvl)
% openSnake - Matthieu Aussal - Copyright 2018 - 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 openSnake([30,30],10,10)", play with keyboard arrows 

% Initialize key value (-> right)
global key
key = 29;

% Object indices
indSnake = [dim(1)/2 * ones(n,1)  dim(2)/2 + (-n+1:0)'];
indApple = ceil((dim-1).*rand(1,2));

% Sense of displacement (carthesian)
sens = [0 1];

% Initialize pixel matrix 
M = zeros(dim(1),dim(2));
M(sub2ind(dim,indSnake(:,1),indSnake(:,2))) = 1.0;
M(sub2ind(dim,indApple(:,1),indApple(:,2))) = 0.5;

% Graphical representation
figure(1); clf
axes('position',[0 0 1 1])
H = pcolor(1-M);
colormap gray; axis equal off; shading flat
set(gcf,'KeyPressFcn',{@direction});
pause(5)

% Infinite loop
while 1
    % Keyboard
    if (key == 28 && ~sens(2))
        sens = [0 -1];
    elseif (key == 29 && ~sens(2))
        sens = [0 1];
    elseif (key == 30 && ~sens(1))
        sens = [1 0];
    elseif (key == 31 && ~sens(1))
        sens = [-1 0];
    end
        
    % Eat apple or not (snake growth and level up)
    if (norm(indSnake(end,:) - indApple) == 0)
        indSnake(end+1,:) = indSnake(end,:) + sens; 
        while intersect(indApple,indSnake,'rows')
            indApple = ceil((dim-1).*rand(1,2));
        end   
        lvl = lvl + 1;
    else
        indSnake = circshift(indSnake,-1);
        indSnake(end,:) = indSnake(end-1,:) + sens;
    end
    
    % Game over
    if sum(indSnake(end,:) >= dim) || sum(indSnake(end,:) <= 0) || ...
        size(unique(indSnake,'rows'),1) < size(indSnake,1)
        disp(['SCORE IS ',num2str(length(indSnake)),'. GAME OVER !']);
        break
    end
        
    % Update pixel matrix
    M = zeros(dim(1),dim(2));
    M(sub2ind(dim,indSnake(:,1),indSnake(:,2))) = 1.0;
    M(sub2ind(dim,indApple(:,1),indApple(:,2))) = 0.5;

    % Update graphical representation
    set(H,'CData',1-M)
    drawnow
    
    % Pause time
    pause(1/lvl)      
end
end

function direction(~,~)
global key
key = double(get(gcf,'Currentcharacter'));
end