image thumbnail
from Sudoku GUI by Johnny Brannbacka
Graphical user interface for creating and solving sudoku puzzles

sudoku(varargin)
function sudoku(varargin)

% sudoku
%
% Sudoku GUI for Matlab
%
% Created 2006 by Johnny Brannbacka
% <jbrannba@gmail.com>
%

if nargin==0,
    h_main=openfig(mfilename,'new');
    centerfig(h_main);
    handles=guihandles(h_main);
    guidata(h_main,handles);
    initialize(handles);
else
    if nargin>1,
        feval(varargin{1},varargin{2:end})
    else
        feval(varargin{1})
    end
end

%--------------------------------------------------------------------------
function initialize(handles)

set(handles.sudoku,'buttondownfcn','sudoku(''highlight'',guidata(gcbo),0)','keypressfcn','sudoku(''keypress'',guidata(gcbo))');
axes(handles.axes1);
cla
set(handles.axes1,'nextplot','add');

h_text=[];
h_field=[];
for i=1:9,
    for j=1:9,
        ix=sub2ind([9 9],i,j);
        
        h_field(ix)=fill([-1 0 0 -1]+i,[-1 -1 0 0]+j,'w','buttondownfcn',['sudoku(''highlight'',guidata(gcbo),' num2str(ix) ')']);
        h_text(ix)=text(i-0.5,j-0.5,'','fontunits','normalized','fontsize',0.07,'horizontalalignment','center','buttondownfcn',['sudoku(''highlight'',guidata(gcbo),' num2str(ix) ')']);
    end
end

setappdata(handles.sudoku,'h_text',h_text);
setappdata(handles.sudoku,'h_field',h_field);

for i=0:3:9,
    h=plot([0 9],[i i],'k-');
    set(h,'linewidth',2.5);
    h=plot([i i],[0 9],'k-');
    set(h,'linewidth',2.5);
end

hlbox=plot([0 1 1 0 0],[0 0 1 1 0],'r-');
set(hlbox,'linewidth',3,'visible','off');

axis([-0.03 9.03 -0.03 9.03]);
axis equal
axis off

s=zeros(9);
setappdata(handles.sudoku,'s',s);
setappdata(handles.sudoku,'s0',s);
setappdata(handles.sudoku,'ss',s);
setappdata(handles.sudoku,'hlbox',hlbox)
setappdata(handles.sudoku,'selected',0)
setappdata(handles.sudoku,'t0',clock);
setappdata(handles.sudoku,'cheated',0);

%--------------------------------------------------------------------------
function create_sudoku(handles)

t=timer('timerfcn','waitbar(mod(etime(clock,t0)/60,1),hwb)','period',1 ...
    ,'startfcn','hwb=waitbar(0,''Please wait...'',''windowstyle'',''modal'');t0=clock;' ...
    ,'stopfcn','delete(hwb)','executionmode','fixedrate');
start(t);
n=get(handles.create_slider,'value');

[s,ss]=sudoku_construct(n);

h_text=getappdata(handles.sudoku,'h_text');
for i=1:9,
    for j=1:9,
        ix=sub2ind([9 9],i,j);
        
        if s(ix)==0,
            str='';
        else
            str=num2str(s(ix));
        end
        set(h_text(ix),'string',str,'color','black');
    end
end
stop(t);
delete(t);

setappdata(handles.sudoku,'s',s);
setappdata(handles.sudoku,'s0',s);
setappdata(handles.sudoku,'ss',ss);
setappdata(handles.sudoku,'t0',clock);
setappdata(handles.sudoku,'cheated',0);
%--------------------------------------------------------------------------
function highlight(handles,ix);


hlbox=getappdata(handles.sudoku,'hlbox');

if ix>0,
    [i,j]=ind2sub([9 9],ix);
    set(hlbox,'xdata',i+[-1 0 0 -1 -1],'ydata',j+[-1 -1 0 0 -1],'visible','on');
else
    set(hlbox,'visible','off');
end

setappdata(handles.sudoku,'hlbox',hlbox)
setappdata(handles.sudoku,'selected',ix)

%--------------------------------------------------------------------------
function keypress(handles);

ix=getappdata(handles.sudoku,'selected');
s0=getappdata(handles.sudoku,'s0');
s=getappdata(handles.sudoku,'s');
key=get(handles.sudoku,'currentcharacter');

if ix>0 && ismember(double(key),[28:31]),
    [i,j]=ind2sub([9 9],ix);
    if double(key)==28,
        i=i-1;
    elseif double(key)==29,
        i=i+1;
    elseif double(key)==30,
        j=j-1;
    else
        j=j+1;
    end
    if i>=1 && i<=9 && j>=1 && j<=9,
        ix=sub2ind([9 9],i,j);
        highlight(handles,ix);
    end
    return
end

ix0=find(s0==0);
if ~ismember(ix,ix0),
    return
end

h_text=getappdata(handles.sudoku,'h_text');
h_field=getappdata(handles.sudoku,'h_field');


if ismember(double(key),[8 32 48 127]),
    s(ix)=0;
    set(h_text(ix),'string','');
    setappdata(handles.sudoku,'s',s);
elseif ismember(double(key),[49:57]),
    st=s;
    st(ix)=str2num(key);
    [i,j]=ind2sub([9 9],ix);
    [rok,ind]=rulesok(st,i,j);
    set(h_text(ix),'string',key,'color',0.5*[1 1 1]);
    if rok,
        s(ix)=str2num(key);
        setappdata(handles.sudoku,'s',s);
        if ~any(s(:)==0),
            t0=getappdata(handles.sudoku,'t0');
            dt=etime(clock,t0);
            t_h=floor(dt/(60*60));
            t_m=floor((dt-t_h*(60*60))/60);
            t_s=round(dt-t_h*(60*60)-t_m*60);
            t_str=[];
            if t_h>0,
                t_str=[num2str(t_h) ' h '];
            end
            if t_m>0,
                t_str=[t_str num2str(t_m) ' min '];
            end
            t_str=[t_str num2str(t_s) ' s '];
            cheated=getappdata(handles.sudoku,'cheated');
            if cheated,
                t_str=[t_str ', BUT YOU CHEATED!!'];
            end 
            h=msgbox(['You have solved the sudoku puzzle in ' t_str],'Congratulations!','modal');
            uiwait(h);
        end
    else
        set(h_field(ind),'facecolor',[1 0.8 0.8]);
        drawnow;
        pause(1);
        set(h_field(ind),'facecolor','white');
        set(h_text(ix),'string','');
    end
end
    
    
%--------------------------------------------------------------------------
function [rok,ind]=rulesok(s,i,j)

ix=sub2ind(size(s),i,j);
ix1=sub2ind(size(s),i*ones(1,9),1:9);
ix1=ix1(find(ix1~=ix));
ix2=sub2ind(size(s),1:9,j*ones(1,9));
ix2=ix2(find(ix2~=ix));

if i<=3,
    xv=1:3;
elseif i<=6,
    xv=4:6;
else
    xv=7:9;
end

if j<=3,
    yv=1:3;
elseif j<=6,
    yv=4:6;
else
    yv=7:9;
end

[x,y]=meshgrid(xv,yv);

ix3=sub2ind(size(s),x(:)',y(:)');
ix3=ix3(find(ix3~=ix));

rok = ~(any(s(ix)==s(ix1)) | any(s(ix)==s(ix2)) | any(s(ix)==s(ix3)));

if nargout==2,
    ind=[];
    i=find(ismember(s(ix1),s(ix)));
    ind=[ind ix1(i)];
    i=find(ismember(s(ix2),s(ix)));
    ind=[ind ix2(i)];
    i=find(ismember(s(ix3),s(ix)));
    ind=[ind ix3(i)];
end

%--------------------------------------------------------------------------
function hint(handles);

s=getappdata(handles.sudoku,'s');
h_field=getappdata(handles.sudoku,'h_field');

s1=sudokusolve(s,0,1);

ix=find(s1-s);
set(h_field(ix),'facecolor',[0.8 1 0.8]);
waitforbuttonpress
set(h_field(ix),'facecolor','white');
setappdata(handles.sudoku,'cheated',1);

%--------------------------------------------------------------------------
function solve_number(handles);

s=getappdata(handles.sudoku,'s');
h_field=getappdata(handles.sudoku,'h_field');
h_text=getappdata(handles.sudoku,'h_text');

s1=sudokusolve(s,0,1);

ix=find(s1-s);
ix=ix(randperm(length(ix)));

s(ix(1))=s1(ix(1));
set(h_text(ix(1)),'string',num2str(s1(ix(1))),'color',0.5*[1 1 1])
setappdata(handles.sudoku,'s',s);
set(h_field(ix(1)),'facecolor',[0.8 1 0.8]);
waitforbuttonpress
set(h_field(ix(1)),'facecolor','white');
setappdata(handles.sudoku,'cheated',1);

%--------------------------------------------------------------------------
function solve_step(handles);

s=getappdata(handles.sudoku,'s');
h_field=getappdata(handles.sudoku,'h_field');
h_text=getappdata(handles.sudoku,'h_text');

s1=sudokusolve(s,0,1);

ix=find(s1-s);

s(ix)=s1(ix);
for i=1:length(ix),
    set(h_text(ix(i)),'string',num2str(s1(ix(i))),'color',0.5*[1 1 1]);
end
setappdata(handles.sudoku,'s',s);
set(h_field(ix),'facecolor',[0.8 1 0.8]);
waitforbuttonpress
set(h_field(ix),'facecolor','white');
setappdata(handles.sudoku,'cheated',1);

%--------------------------------------------------------------------------
function solve_all(handles);

s=getappdata(handles.sudoku,'s');
h_field=getappdata(handles.sudoku,'h_field');
h_text=getappdata(handles.sudoku,'h_text');

s1=sudokusolve(s);

ix=find(s1-s);

s(ix)=s1(ix);
for i=1:length(ix),
    set(h_text(ix(i)),'string',num2str(s1(ix(i))),'color',0.5*[1 1 1]);
end
setappdata(handles.sudoku,'s',s);
set(h_field(ix),'facecolor',[0.8 1 0.8]);
waitforbuttonpress
set(h_field(ix),'facecolor','white');
setappdata(handles.sudoku,'cheated',1);

%--------------------------------------------------------------------------
function delete_incorrect(handles);

s=getappdata(handles.sudoku,'s');
ss=getappdata(handles.sudoku,'ss');
h_field=getappdata(handles.sudoku,'h_field');
h_text=getappdata(handles.sudoku,'h_text');

ix=find((s-ss)~=0 & s~=0);

s(ix)=0;

for i=1:length(ix),
    set(h_text(ix(i)),'string','','color',0.5*[1 1 1]);
end
setappdata(handles.sudoku,'s',s);
set(h_field(ix),'facecolor',[0.8 1 0.8]);
waitforbuttonpress
set(h_field(ix),'facecolor','white');
setappdata(handles.sudoku,'cheated',1);

Contact us at files@mathworks.com