image thumbnail

GUI for Hybrid Sudoku Solver

by

 

A simple GUI to solve Sudoku puzzles. Uses both logical and bruteforce methods.

Sudoku_GUI2
%%%%%%%%%%Programmed by: Chi-Hang Kwan%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%Creation Date: November 10, 2012%%%%%%%%%%%%%%%%%%%%
function Sudoku_GUI2
clear all
close all

WinWidth = 400; %window width
WinHeight = 500; %window height

%create the GUI window
window = figure('unit','pixels','numbertitle','off','menubar','none','resize','off',...
        'position',[0 0 WinWidth WinHeight],'name','Sudoku Solver ver. 1.1','visible','on');
movegui(window,'center')

%Calculations for cell entry positions
MarSide = 50;
MarTop = 50;
dC = (WinWidth - MarSide -10)/9;
CornerY = WinHeight-MarTop-dC;
CornerX = MarSide/2;

%Creating all 81 input boxes      
for ii=1:9
    for jj=1:9
        XPos = CornerX + (jj-1)*dC + floor((jj-1)/3)*5;
        YPos = CornerY - (ii-1)*dC - floor((ii-1)/3)*5;
        tb.x(ii,jj) = uicontrol( 'Style','edit','unit','pixels','backgroundcolor','w',...
            'string',[],'position', [XPos YPos dC dC],'KeyPressFcn', {@callback_entry,window,ii,jj},...
            'fontsize',13, 'visible', 'on', 'fontWeight', 'normal','enable', 'on');
    end
end

%The title textbox
tb.title = uicontrol('Style', 'text', 'unit', 'pixels', 'string', 'Hybrid Sudoku Solver',...
        'Position',[0 WinHeight-45  WinWidth 30], 'Horizontalalignment', 'center',...
        'FontSize',16, 'backgroundcolor', 0.8*[1 1 1], 'foregroundcolor', [0 0 1],...
        'FontName', 'constantia', 'FontWeight', 'normal');

%The solve button
tb.solve = uicontrol('Style','pushbutton','unit','pixels','string','Solve',...
        'position',[WinWidth-MarSide/2-100 55 100 30],'fontsize',10,...
        'backgroundcolor',0.9*[1 1 1],'foregroundcolor',0.8*[0 1 0],...
        'visible','on','callback',{@callback_update,window} );

%The clear button
tb.clear = uicontrol('Style','pushbutton','unit','pixels','string','Clear',...
        'position',[WinWidth-MarSide/2-100 15 100 30],'fontsize',10,...
        'backgroundcolor',0.9*[1 1 1],'foregroundcolor',0.8*[1 0 0],...
        'visible','on', 'callback',{@callback_clear,window});
    
%Status Notification
message = sprintf('Status:\nPress [Solve] to calculate solution.');
tb.status = uicontrol('Style', 'text', 'unit', 'pixels', 'string', message,...
        'Position',[MarSide/2 35  250 50], 'Horizontalalignment', 'left',...
        'FontSize',10, 'backgroundcolor', 0.8*[1 1 1]);

set(window,'UserData', tb); %save the completed tb structure back into the window handle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%The Input Function%%%%%%%%%%%%%%%%%%%%%%%%%%
function callback_entry(src,event, hAxes,ii,jj)
tb = get(hAxes,'UserData');
set(tb.x(ii,jj), 'FontWeight', 'bold'); % to differentiate between entered and calculated entries

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%The Solving Function%%%%%%%%%%%%%%%%%%%%%%%%%%
function callback_update(src, event, hAxes)

tb = get(hAxes,'UserData');

A=zeros(1,81);
for k=1:81
    if isempty(get(tb.x(k), 'string'))
            A(k) = 0;
    else
            A(k) = str2double(get(tb.x(k), 'string'));
    end
end
A=reshape(A,9,9);

%Check for Invalid Entries%
for ii=1:9
    for jj=1:9
        if isnan(A(ii,jj)) || A(ii,jj)>9 || A(ii,jj)<0 || rem(A(ii,jj),1)~=0
            message = sprintf('Status:\nError! The cell entries must be integers between 0 and 9.');
            set(tb.status, 'string', message);
            return
        end
    end
end

%Check for Conflicts*
for ii=1:9
    for jj=1:9
    if A(ii,jj)~=0
        if NoConflict(A,ii,jj)==0
            message = sprintf('Status:\nError! Conflicting cell entries.');
            set(tb.status, 'string', message);
            return
        end
    end
    end
end


message = sprintf('Status:\nCalculating solution, please wait...');
set(tb.status, 'string', message);
pause(0.5)


%%%%%%%Here we call the SudokuSolver function*%%%%%%%%%%%%%%%%%%%%%%
%You may use your own solver if desired
%The input array A uses 0's to represent empty spots
tic
  B = SudokuSolver(A');  %The transpose solution is usually faster!
  B = B';
t=toc;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

message = sprintf('Status:\nSolved! Solution time: %.3f sec.',t);
set(tb.status, 'string', message);

%Update cells
for k=1:81
      if A(k)==0
          set(tb.x(k), 'fontweight', 'normal');
          set(tb.x(k),'string', num2str(B(k))); 
      end
end



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%The Clearing Function%%%%%%%%%%%%%%%%%%%%%%%%%%
function callback_clear(src, event, hAxes)
tb = get(hAxes,'UserData');

for k=1:81
        set(tb.x(k),'string', []);
end

message = sprintf('Status:\nPress [Solve] to calculate solution.');
set(tb.status, 'string', message);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%Conflict Checking Function%%%%%%%%%%%%%%%%%%
function bool = NoConflict(C,Row,Col)

for ii=1:9
    if ii~=Row
    if C(ii,Col)==C(Row,Col)
        bool=0;
        return
    end
    end
end

for jj=1:9
    if jj~=Col
    if C(Row,jj)==C(Row,Col)
        bool=0;
        return
    end
    end
end

RemR = rem((Row-1),3);
RemC = rem((Col-1),3);

RowL = Row - RemR;
ColL = Col - RemC;

for ii=RowL:RowL+2
    for jj=ColL:ColL+2
       if (ii~=Row) ||(jj~=Col)
       if C(ii,jj)==C(Row,Col)
            bool=0;
            return
       end
       end
    end
end

bool=1;



Contact us