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