-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsudoku_board.c
225 lines (203 loc) · 6.95 KB
/
sudoku_board.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include "sudoku_board.h"
#include <stdio.h>
#include "2d_array_utils.h"
#include <math.h>
#include <stdlib.h>
int const BOARD_NULL_VALUE = 0;
/* all functions in this file get 0<=x,y<=row*col-1 */
/* if is_fix == 1 value from fixed_board if ==0 from current_board*/
int get_value(int x, int y, Board* board, int is_fix){
if(is_fix==0){
return (board->cur_board)[x][y];
}
return (board->fixed_board)[x][y];
}
/* return 1 if value was found in row*/
int value_in_row(int row, int value, Board* board, int is_fix){
int i;
int size = (board->num_of_rows)*(board->num_of_columns);
for (i=0; i<size; i++){
if(get_value(row,i,board,is_fix) == value)
return 1;
}
return 0;
}
/* return 1 if value was found in column*/
int value_in_col(int col, int value, Board* board,int is_fix){
int i;
int size = (board->num_of_rows)*(board->num_of_columns);
for (i=0; i<size; i++){
if(get_value(i,col,board,is_fix) == value)
return 1;
}
return 0;
}
/* return 1 if value was found in square*/
int value_in_square(int row, int col, int value, Board* board,int is_fix){
int i,j;
int top_left_corner_row = floor(row/board->num_of_rows)*board->num_of_rows;
int top_left_corner_col = floor(col/board->num_of_columns)*board->num_of_columns;
for(i= top_left_corner_row; i<top_left_corner_row+board->num_of_rows; i++){
for(j= top_left_corner_col; j<top_left_corner_col+board->num_of_columns; j++){
if(get_value(i,j,board,is_fix) == value)
return 1;
}
}
return 0;
}
/* return 1 if value is legal in <x,y>*/
int is_legal(int x, int y, int value, Board* board, int is_fix){
if((value_in_row(x,value,board,is_fix) || value_in_col(y,value,board,is_fix) || value_in_square(x,y,value,board,is_fix) ))
return 0;
return 1;
}
/* set legal value to <x,y>*/
int set_value(int x, int y, int value, Board* board,int is_fix){
if(is_legal(x,y,value,board,is_fix)==0){
return 0;}
if(board->cur_board[x][y] == BOARD_NULL_VALUE)
board->count_filled++;
board->cur_board[x][y] = value;
return 1;
}
/* set BOARD_NULL_VALUE TO <x,y>*/
int erase_value(int x, int y, Board* board) {
if (board->cur_board[x][y] != BOARD_NULL_VALUE) {
board->count_filled--;
}
board->cur_board[x][y] = BOARD_NULL_VALUE;
return 1;
}
/* set value to <x,y> without legal check*/
void set_value_without_check(int x, int y, int value, Board* board){
if(board->cur_board[x][y] == BOARD_NULL_VALUE)
board->count_filled++;
board->cur_board[x][y] = value;
}
/* allocate boards with size, initialize board parameters*/
int create_empty_board(Board* board, int rows, int columns) {
int size = rows * columns;
board->num_of_columns = columns;
board->num_of_rows = rows;
board->cur_board = create_2d_array(size);
board->fixed_board = create_2d_array(size);
board->solved_board = create_2d_array(size);
board->count_filled = 0;
board->mode = INIT;
board->mark_errors = 1;
return 1;
}
/* copy from_board to to_board parameters and values*/
void copy_board(Board* from_board,Board* to_board){
int size = from_board->num_of_columns * from_board->num_of_rows;
/* allocated same sizes before call this func!*/
to_board->mode = from_board->mode;
to_board->count_filled = from_board->count_filled;
/*to_board->mark_errors = from_board->mark_errors; parameter for all game!*/
copy_board_values(to_board->cur_board,from_board->cur_board,size);
copy_board_values(to_board->fixed_board,from_board->fixed_board,size);
copy_board_values(to_board->solved_board,from_board->solved_board,size);
}
/* free memo of 2d_arrays and board*/
void free_board(Board* board){
if(board != NULL && board->cur_board != NULL){ /*alloceted all boards! create_empty_board was called*/
int size = (board->num_of_rows)*(board->num_of_columns);
free_2d_array(board->solved_board,size);
free_2d_array(board->fixed_board,size);
free_2d_array(board->cur_board,size);
}
free(board);
}
/* check is cell <row,col> is erroneous*/
int is_erroneous_cell(Board* board,int row, int col){
int successed;
int value;
if(board->cur_board[row][col] != BOARD_NULL_VALUE){
value = get_value(row,col,board,0);
erase_value(row,col,board);
successed = set_value(row,col,value,board,0);
if(successed == 0){
set_value_without_check(row,col,value,board);
return 1;
}
}
return 0;
}
/* check if board has erroneous_cell*/
int is_erroneous_board(Board* board){
int i, j;
int size = (board->num_of_rows)*(board->num_of_columns);
for (i=0; i<size; i++){
for (j=0; j<size; j++){
if(is_erroneous_cell(board,i,j))
return 1;
}
}
return 0;
}
/* check if board has size*size filled cells*/
int is_filled(Board* board){
int size = (board->num_of_rows)*(board->num_of_columns);
if(board->count_filled == size*size){
return 1;
}
return 0;
}
/* print the differences between before and after boards*/
void print_diff(Board* before, Board* after){
int i, j, before_val, after_val;
int size = (before->num_of_rows)*(before->num_of_columns);
/* mode cant be changed without mew board and clean moves. therefore, same sizes
mark_errors isn't in moves list.
if(before->mark_errors != after->mark_errors){
printf("mark_errors parameter changed from %d to %d.\n",before->mark_errors,after->mark_errors);
}*/
for (i=0; i<size; i++){
for (j=0; j<size; j++){
before_val = get_value(i,j,before,0);
after_val = get_value(i,j,after,0);
if(before_val != after_val){
if(before_val == BOARD_NULL_VALUE){
before_val = 0;
}
if(after_val == BOARD_NULL_VALUE){
after_val = 0;
}
printf("cell (%d,%d) changed from %d to %d.\n",j+1,i+1,before_val,after_val);
}
}
}
}
/* return 0 if no legal value or more then one legal value to cell <row,col>
or the value if he's the only one.*/
int single_possible_value(int row, int col, Board* board){
/* notice the change to 0 */
int i,value = 0;
int count = 0;
int size = board->num_of_columns * board->num_of_rows;
for(i = 1; i<=size; i++){
if(is_legal(row,col,i,board,0)){
count++;
value = i;
}
if(count>1)
return -1;
}
if(count != 1){
return 0;
}
return value;
}
/* check if the board is winner. if it's filled and don't have errors*/
int is_winner(Board* board){
if(is_filled(board)){
if(is_erroneous_board(board)==0){
return 1;
}
else{
printf("solution is erroneous.\n");
return 0;
}
}
return 0;
}