Sudoku solving algorithm C++ -
i'm trying make sudoku solving program couple of days i'm stuck methods. found algorithm here don't understand it:
- start @ first empty cell, , put 1 in it.
- check entire board, , see if there conflicts
- if there coflicts on board, increase number in current cell 1 (so change 1 2, 2 3, etc)
- if board clean move, start @ step 1 again.
- if 9 possible numbers on given cell cause conflict in board, set cell empty, go previous cell, , start again step 3 (this 'backtracking' comes in).
here code. think wrong help_solve(...) function. can me identify problem, please?
#include <iostream> #include <iomanip> #include <time.h> #include <cstdlib> #include <windows.h> using namespace std; class sudoku { private: int board[9][9]; int change[9][9]; public: sudoku(); void print_board(); void add_first_cord(); void solve(); void help_solve(int i, int j); bool check_conflicts(int p, int i, int j); }; sudoku game; void setcolor(unsigned short color) //the function you'll use { //set colour handle hcon = getstdhandle(std_output_handle); setconsoletextattribute(hcon,color); } sudoku::sudoku() { for(int = 1; <= 9; i++) for(int j = 1; j <= 9; j++) board[i][j] = 0; } void sudoku::print_board() { for(int = 1; <= 9; i++) { for(int j = 1; j <= 9; j++) { if(change[i][j] == 1) { setcolor(12); cout << board[i][j] << " "; setcolor(7); } else cout << board[i][j] << " "; if(j%3 == 0) cout << "| "; } cout << endl; if(i%3 == 0) cout << "------+-------+---------" << endl; } } void sudoku::add_first_cord() { board[1][1] = 5; change[1][1] = 1; board[1][2] = 3; change[1][2] = 1; board[1][5] = 7; change[1][5] = 1; board[2][1] = 6; change[2][1] = 1; board[2][4] = 1; change[2][4] = 1; board[2][5] = 9; change[2][5] = 1; board[2][6] = 5; change[2][6] = 1; board[3][2] = 9; change[3][2] = 1; board[3][3] = 8; change[3][3] = 1; board[3][8] = 6; change[3][8] = 1; board[4][1] = 8; change[4][1] = 1; board[4][5] = 6; change[4][5] = 1; board[4][9] = 3; change[4][9] = 1; board[5][1] = 4; change[5][1] = 1; board[5][4] = 8; change[5][4] = 1; board[5][6] = 3; change[5][6] = 1; board[5][9] = 1; change[5][9] = 1; board[6][1] = 7; change[6][1] = 1; board[6][5] = 2; change[6][5] = 1; board[6][9] = 6; change[6][9] = 1; board[7][2] = 6; change[7][2] = 1; board[7][7] = 2; change[7][7] = 1; board[7][8] = 8; change[7][8] = 1; board[8][4] = 4; change[8][4] = 1; board[8][5] = 1; change[8][5] = 1; board[8][6] = 9; change[8][6] = 1; board[8][9] = 5; change[8][9] = 1; board[9][5] = 8; change[9][5] = 1; board[9][8] = 7; change[9][8] = 1; board[9][9] = 9; change[9][9] = 1; } bool sudoku::check_conflicts(int p, int i, int j) { for(int k = 1; k <= 9; k++) if(board[i][k] == p) return false; for(int q = 1; q <= 9; q++) if(board[q][j] == p) return false; /* *00 000 000 */ if((j == 1 || j == 4 || j == 7) && (i == 1 || == 4 || == 7)) { if(board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p || board[i+2][j] == p || board[i+1][j+1] == p || board[i+1][j+2] == p || board[i+2][j+1] == p || board[i+2][j+2] == p)return false; } /* 000 000 *00 */ if((j == 1 || j == 4 || j == 7) && (i == 3 || == 6 || == 9)) { if(board[i-1][j] == p || board[i-2][j] == p || board[i][j+1] == p || board[i][j+2] == p || board[i-1][j+1] == p || board[i-1][j+2] == p || board[i-2][j+1] == p || board[i-2][j+2] == p)return false; } /* 000 *00 000 */ if((j == 1 || j == 4 || j == 7) && (i == 2 || == 5 || == 8)) { if(board[i-1][j] == p || board[i+1][j] == p || board[i-1][j+1] == p || board[i][j+1] == p || board[i+1][j+1] == p || board[i+1][j+2] == p || board[i][j+2] == p || board[i+1][j+2] == p)return false; } /* 0*0 000 000 */ if((j == 2 || j == 5 || j == 8) && (i == 1 || == 5 || == 7)) { if(board[i-1][j] == p || board[i+1][j] == p || board[i-1][j+1] == p || board[i][j+1] == p || board[i+1][j+1] == p || board[i+1][j+2] == p || board[i][j+2] == p || board[i+1][j+2] == p)return false; } /* 000 0*0 000 */ if((j == 2 || j == 5 || j == 8) && (i == 2 || == 5 || == 8)) { if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j+1] == p || board[i][j+1] == p || board[i][j-1] == p || board[i+1][j+1] == p || board[i][j] == p || board[i+1][j-1] == p)return false; } /* 000 000 0*0 */ if((j == 2 || j == 5 || j == 8) && (i == 3 || == 6 || == 9)) { if(board[i][j-1] == p || board[i][j+1] == p || board[i-1][j] == p || board[i-1][j+1] == p || board[i-1][j-1] == p || board[i-2][j] == p || board[i-1][j+1] == p || board[i-2][j-1] == p) return false; } /* 00* 000 000 */ if((j == 3 || j == 6 || j == 9) && (i == 1 || == 4 || == 7)) { if(board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p || board[i+1][j-1] == p || board[i+1][j-2] == p || board[i+2][j] == p || board[i+2][j-1] == p || board[i+2][j-2] == p) return false; } /* 000 00* 000 */ if((j == 3 || j == 6 || j == 9) && (i == 2 || == 5 || == 8)) { if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j-2] == p || board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p || board[i+1][j-1] == p || board[i+1][j-2] == p) return false; } /* 000 000 00* */ if((j == 3 || j == 6 || j == 9) && (i == 3 || == 6 || == 9)) { if(board[i][j-1] == p || board[i][j-1] == p || board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j-2] == p || board[i-2][j] == p || board[i-2][j-1] == p || board[i-2][j-2] == p) return false; } return true; } void sudoku::help_solve(int i, int j) { if(j <= 0) { = i-1; j = 9; } if(change[i][j] == 1) return game.help_solve(i, j-1); for(int p = 1; p <= 9; p++) if(game.check_conflicts(p, i, j)) { board[i][j] = p; return; } return game.help_solve(i, j-1); } void sudoku::solve() { for(int = 1; <= 9; i++) { for(int j = 1; j <= 9; j++) { if(board[i][j] == 0 && change[i][j] == 0) { game.help_solve(i, j); } } } for(int = 1; <= 9; i++) for(int j = 1; j <= 9; j++) if(board[i][j] == 0) game.help_solve(i, j); } int main() { game.add_first_cord(); game.solve(); game.print_board(); system("pause"); return 0; }
edit: need use recursion right? maybe parameters give function wrong. don't know. in add_first_cord() declare starting values every sudoku has in beginning. here values use: http://bg.wikipedia.org/wiki/%d0%a4%d0%b0%d0%b9%d0%bb:sudoku-by-l2g-20050714.gif. expect see solved sudoku shown in wikipedia. solved values right others not. here in console
suggested approach
- implement generic graph search algorithm
- could use either idfs or a* graph search
- i prefer second
- do general directed graph
- node type
tnode
- node successor function
tnode => vector<tnode>
- node type
- could use either idfs or a* graph search
- define sudoku states
- a state 9x9 array number 1, 2, ..., or 9 or blank in each position
- define goal sudoku state
- all 81 cells filled in
- all 9 rows have numbers {1, 2, ..., 9} in them
- all 9 columns have numbers {1, 2, ..., 9} in them
- all 9 3x3 squares have numbers {1, 2, ..., 9} in them
- define valid sudoku state successor function
- a state
s
can have numbern
added @ rowi
, columnj
if:- cell
(i,j)
empty - there no other
n
in rowi
- there no other
n
in columnj
- there no other
n
in 3x3 square containing(i,j)
- cell
- the state successor function maps state
s
vector
of states satisfy these rules
- a state
- apply generic graph search algorithm (1) sudoku state graph (2-4)
- (optional) if choose use a* graph search, can define heuristic on sudoku state space potentially drastically increase performance
- how design heuristic whole problem, that's more of art science
current approach
your current approach mixes specification of graph searched , implementation of search algorithm. you're going have lot of difficulty if mix two. problem naturally separates 2 distinct pieces -- algorithm , graph -- can , should exploit in implementation. make simpler.
the other benefit if go separation able reuse graph search algorithm on huge number of problems - cool!
Comments
Post a Comment