% You should be able to run this as % % CS121_sudoku(sudoku_file) % % The board_file should just be a 9x9 matrix of numbers. % It should look like the one we provide. % % Example Run: CS121_sudoku('board.txt'); % % Feel free to delete all example code. % % We referenced http://www.mathworks.com/matlabcentral/fileexchange/7676 % when setting this assignment up. function sudoku_solver(sudoku_file) global fignr; fignr = figure; cla; draw_grid(); %% for loading from a plain text file as in start = load(sudoku_file); current = start; draw_board(start, current); %% if loading from an excel spreadsheet use % start = xlsread(sudoku_file); % current = start; % draw_board_xls(start, current); %% This just pauses the board after it has been initially drawn waitforbuttonpress %% Example code: that marks squares with numbers that make the board invalid % This does not try to check which squares are correctly labeled and is % just used as an example to show you what functions you have available. for i = 1:9 for j = 1:9 ss_r = ceil(i / 3); % because matlab indexes starting from 1 ss_c = ceil(j / 3); if start(i, j) == 0 && (current(i, j) ~= 0) && ... % matlab uses ~ to signify not ~(is_subsquare_valid(ss_r, ss_c, current) ... && is_row_valid(i, current) ... && is_col_valid(j, current)) draw_number(current(i, j), i, j, 'r'); end end end %% Example code that checks if a board is solved if(checksolved(current)) disp('this board is a solved board'); end %% Sudoku Solver % if you are using this as your sudoku model then % % YOUR CODE SHOULD GO HERE % % Also you may add as many functions as you'd like. You'll probably need % to add a couple for readability and for however you decompose the % problem return %% Helper Functions % Provided for your convenience. You shouldn't need to % change any code below here. But feel free to read it and change it as % see fit. Just be sure to document what you are doing. % This function checks to see if the current board configuration is solved function isvalid = checksolved(current) isvalid = true; for i = 1:3 for j = 1:3 r = 3*(i-1) + j; c = r; if( ~is_subsquare_solved(i, j, current) || ... ~is_row_solved(r, current) || ... ~is_col_solved(c, current) ) isvalid = false; return end end end return % checks if the 3x3 subsquare in position % r,c (labeled by subsquare) is a valid subsquare % meaning that there are no conflicts within the square function isvalid = is_subsquare_valid(r, c, current) rr = 3*r; cc = 3*c; subsquare = current(rr-2:rr, cc-2:cc); subsquare = subsquare(:); subsquare = subsquare(subsquare ~= 0); isvalid = isequal(size(unique(subsquare)), size(subsquare)); return function isvalid = is_row_valid(row, current) r = current(row, :); r = r(r ~= 0); isvalid = isequal(size(unique(r)), size(r)); return function isvalid = is_col_valid(col, current) isvalid = is_row_valid(col, current'); return % check to see if a particular subproblem is solved function issolved = is_subsquare_solved(r, c, current) rr = 3*r; cc = 3*c; subsquare = current(rr-2:rr, cc-2:cc); issolved = ~any(subsquare(:) == 0) ... && is_subsquare_valid(r, c, current); return function issolved = is_row_solved(r, current) issolved = ~any(current(r, :) == 0) ... && is_row_valid(r, current); return function issolved = is_col_solved(c, current) issolved = is_row_solved(c, current'); return % This function writes the desired number in the sudoku square, as given by % the desired row and column. Also draws it in the specified color. % If there was a previous number in that position then that object is removed % from the board so the new number can be cleanly placed function draw_number(num, row, col, color) [sx, sy, w, h] = position(row, col); pos = [sx + w/2, sy + h/2, 0]; % erase current text at this position % need to find a better way to do this, such as get the element at the % current position tt = get(get(gcf,'Children'), 'Children'); for i = 1:size(tt, 1) if strcmp(get(tt(i), 'Type'), 'text') == 0 continue; end numpos = get(tt(i), 'Position'); if(numpos == pos) delete(tt(i)); break; end end text(pos(1), pos(2), num2str(num), 'fontsize', 20, 'color', color); return % For a given position (rows and cols start from the top left corner i.e. % row 1 is the top row and col 3 would be the third column from the left) % on the sudoku board, this function will return the lower left corner % graphing coordinate position as sx,sy and the width and the height % of the rectangle as w, h % % rows correspond to y values, and columns correspond to x values on the % graph function [sx,sy,w,h]=position(row,col) dx=1/9; dy=1/9; w=dx; h=dy; sx=(col-1)*dx; sy=(9-row)*dy; return % This function draws the grid for the sudoku board and should only ever % have to be called once. function draw_grid() hold on xlabel(''); ylabel(''); set(gca,'xtick',[]); set(gca,'ytick',[]); set(gca,'pos',[0.01 0.01 0.98 0.98]); for i = 1:10 spos = (i-1)/9; width = 1; if( mod(i, 3) == 1 ), width = 3; end line( [spos, spos], [0 1], 'color', 'k', 'linewidth', width); line( [0, 1], [spos spos], 'color', 'k', 'linewidth', width); end return % This function draws the numbers from start and current onto the board. % -The start matrix should represent the initial starting configuration. % (starting board configuration numbers are drawn in black) % -the current matrix should represent the current board configuration. % (current board configuration numbers are drawn in green) function draw_board(start, current) for i=1:9 for j=1:9 nr=start(i,j); if nr>0 draw_number(nr, i, j, 'k'); elseif current(i, j) ~= 0 draw_number(current(i, j), i, j, 'g'); end end end return function draw_board_xls(start, current) ns = isnan(start); nc = isnan(current); for i=1:9 for j=1:9 if ~ns(i, j) draw_number(nr, i, j, 'k'); elseif ~nc(i, j) draw_number(current(i, j), i, j, 'g'); end end end return