No BSD License  

Highlights from
Sudoku! (v3.4)

image thumbnail
from Sudoku! (v3.4) by Alan Tan
Sudoku! is the ultimate GUI for Sudoku fans. No messy scribbles, simply click away to the solution.

sudoku_guicb(action,hObject)
function sudoku_guicb(action,hObject)
% Func : sudoku_makemap

global c1 c2 c3

c1 = [0 0 0 3 3 3 6 6 6];
c2 = [0.2 0.2 0.2 0 0 0 -0.2 -0.2 -0.2];
c3 = [-0.2 0 0.2 -0.2 0 0.2 -0.2 0 0.2];

switch action,
   
case 'button_load'
   cwd = cd;
   str = get(gcbo,'UserData');
   if ~isempty(str) & isdir(str), cd(str); end
   [file,pathname] = uigetfile('*.*','Load...');
   cd(cwd);
   if file > 0
      try
         maps = load(fullfile(pathname,file));
         if ~isstruct(maps), maps = struct('u01',maps); end
         
         set(hObject.hndl.text_map,'String',file);
         set(hObject.hndl.pm_map,'String',sort(fieldnames(maps)),'Value',1,'UserData',maps);
         set(gcbo,'UserData',pathname);
      end
   end
   
case 'button_make'
   maps = get(hObject.hndl.pm_map,'UserData');
   if isempty(maps), return, end
   str  = sort(fieldnames(maps));
   str  = str{get(hObject.hndl.pm_map,'Value')};
   map  = getfield(maps,str);
   
   clearmap(hObject.hndl.axes);
   try
      ud.map = map;
      ud.tee = gettee(ud.map);
      populatemap(hObject.hndl.axes,ud);
   catch, set(hObject.hndl.axes,'UserData',[]); end
   set(hObject.hndl.button_undo,'Enable','off','UserData',[]);
   
case 'button_run'
   ud = get(hObject.hndl.axes,'UserData');
   if isempty(ud), return, end
   
   feval(hObject.exe{get(hObject.hndl.pm_analysis,'Value')},'gui',ud.map,ud.tee);
   
case 'button_record'
   ud = get(hObject.hndl.axes,'UserData');
   if isempty(ud), return, end
   
   set(hObject.hndl.button_recall,'Enable','on');
   set(gcbo,'UserData',ud);
   
case 'button_recall'
   ud = get(hObject.hndl.button_record,'UserData');
   if isempty(ud), return, end
   
   clearmap(hObject.hndl.axes);
   populatemap(hObject.hndl.axes,ud);
   set(hObject.hndl.button_undo,'Enable','off','UserData',[]);
   
case 'button_undo'
   ud = get(gcbo,'UserData');
   if isempty(ud), return, end
   
   set(ud{end}.h3,'Visible','on');
   if ~isempty(ud{end}.h4), delete(ud{end}.h4); end
   
   set(hObject.hndl.axes,'UserData',ud{end});
   if length(ud) == 1, set(gcbo,'Enable','off','UserData',[]);
   else,               set(gcbo,'UserData',ud(1:end-1)); end
   
case 'button_save'
   ud = get(hObject.hndl.axes,'UserData');
   if isempty(ud), return, end
   
   cwd = cd;
   str = get(gcbo,'UserData');
   if ~isempty(str) & isdir(str), cd(str); end
   [file,pathname] = uiputfile('*.txt','Save...');
   cd(cwd);
   if file > 0
      fid = fopen([strrep(fullfile(pathname,file),'.txt',''),'.txt'],'w');
      for k1 = 1:9, 
         for k2 = 1:9, fprintf(fid,'%d ',ud.map(k1,k2)); end
         fprintf(fid,'\r\n');
      end
      fclose(fid);
      set(gcbo,'UserData',pathname);
   end
   
case 'menu_print'
   ud = get(hObject.hndl.axes,'UserData');
   if isempty(ud), return, end
   
   switch get(gcbo,'Label'),
   case '&Print with Hints',    h = sudoku_makemap(ud.map,ud.tee);
   case 'Print with&out Hints', h = sudoku_makemap(ud.map); end
   print(h);
   delete(h);
   
case 'buttondownfcn'
   ud1 = get(hObject.hndl.axes,'UserData');
   ud2 = get(hObject.hndl.button_undo,'UserData');
   p   = ceil(get(gcbo,'Position')-0.5);
   m   = 10-p(2);
   n   = p(1);
   d   = str2num(get(gcbo,'String'));
   
   ud2{end+1} = ud1;
   switch get(gcbf,'SelectionType'),
   case 'normal'
      ud1.map(m,n) = d;
      ud1.h1(m,n)  = text(n,10-m,num2str(d),'FontSize',36,'HorizontalAlignment','center');
      h3           = ud1.h2(m,n,ud1.tee{m,n});
      h3           = h3(:);
      h4           = ud1.h1(m,n);
      ud1.tee{m,n} = [];
      for k = 1:9
         if ~isempty(ud1.tee{m,k}) & any(ud1.tee{m,k} == d)
            ud1.tee{m,k} = remove(ud1.tee{m,k},d);
            h3(end+1)    = ud1.h2(m,k,d);
         end
         if ~isempty(ud1.tee{k,n}) & any(ud1.tee{k,n} == d)
            ud1.tee{k,n} = remove(ud1.tee{k,n},d);
            h3(end+1)    = ud1.h2(k,n,d);
         end
      end
      for k1 = c1(m)+(1:3)
         for k2 = c1(n)+(1:3)
            if ~isempty(ud1.tee{k1,k2}) & any(ud1.tee{k1,k2} == d)
               ud1.tee{k1,k2} = remove(ud1.tee{k1,k2},d);
               h3(end+1)      = ud1.h2(k1,k2,d);
            end
         end
      end
   case 'alt'
      ud1.tee{m,n} = remove(ud1.tee{m,n},d);
      h3           = ud1.h2(m,n,d);
      h4           = [];
   end
   
   if ~(exist('h3') == 1), return, end
   set(h3,'Visible','off');
   
   ud2{end}.h3 = h3;
   ud2{end}.h4 = h4;
   if length(ud2) > 10, ud2 = ud2(2:end); end
   set(hObject.hndl.axes,'UserData',ud1);
   set(hObject.hndl.button_undo,'Enable','on','UserData',ud2);
   
case 'aboutme'
   
   msg = get(gcbo,'UserData');
   uidialog(msg);
   
end

% FUNCTIONS

function clearmap(h)

ud = get(h,'UserData');
if ~isempty(ud)
   delete(ud.h1(find(ud.h1 > 0)));
   delete(ud.h2(find(ud.h2 > 0)));
end

function tee = gettee(map)

global c1

tee = cell(9,9);

for k1 = 1:9
   u1 = map(k1,:);
   for k2 = 1:9
      if map(k1,k2) == 0
         u2 = map(:,k2);
         u3 = map(c1(k1)+(1:3),c1(k2)+(1:3));
         ut = [u1(:); u2; u3(:)];
         for k3 = 1:9, if ~any(ut == k3), tee{k1,k2}(end+1) = k3; end, end
      end
   end
end

function populatemap(h,ud)

global c2 c3

h1 = zeros(9,9);
h2 = zeros(9,9,9);

axes(h);
for k1 = 1:9
   for k2 = 1:9
      if ud.map(k1,k2) > 0
         h1(k1,k2) = text(k2,10-k1,num2str(ud.map(k1,k2)),'FontSize',36,'HorizontalAlignment','center');
      elseif ~isempty(ud.tee{k1,k2})
         for k3 = 1:9
            if any(ud.tee{k1,k2} == k3)
               h2(k1,k2,k3) = text(k2+c3(k3),10-k1+c2(k3),num2str(k3), ...
                  'FontSize',8,'HorizontalAlignment','center', ...
                  'ButtonDownFcn','sudoku_guicb(''buttondownfcn'',get(gcbf,''UserData''))');
            end
         end
      end
   end
end
ud.h1 = h1;
ud.h2 = h2;
set(h,'UserData',ud);

function v = remove(v,u)

v(find(v == u)) = [];

function uidialog(msg)

u = {'Version','Date','Author','URL'};

h0 = dialog('Name',msg.title, ...
   'Units','points', ...
   'Position',[200 200 msg.box(1) msg.box(2)+98]);
for k = 1:4
   uicontrol('Parent',h0, ...
      'Units','points', ...
      'BackgroundColor',[236 233 216]/255, ...
      'HorizontalAlignment','right', ...
      'Position',[20 msg.box(2)+78-12*k 40 12], ...
      'String',[u{k},' >'], ...
      'Style','text');
   uicontrol('Parent',h0, ...
      'Units','points', ...
      'BackgroundColor',[236 233 216]/255, ...
      'HorizontalAlignment','left', ...
      'Position',[62 msg.box(2)+78-12*k msg.box(1) 12], ...
      'String',msg.header{k}, ...
      'Style','text');
end

if ~isempty(msg.body)
   uicontrol('Parent',h0, ...
      'Units','points', ...
      'BackgroundColor',[236 233 216]/255, ...
      'HorizontalAlignment','right', ...
      'Position',[20 msg.box(2)+8 40 12], ...
      'String','Features >', ...
      'Style','text');
   uicontrol('Parent',h0, ...
      'Units','points', ...
      'BackgroundColor',[236 233 216]/255, ...
      'HorizontalAlignment','left', ...
      'Position',[62 20 msg.box], ...
      'String',msg.body, ...
      'Style','text');
end

Contact us at files@mathworks.com