1 | <?php |
||||||||
2 | |||||||||
3 | class sudoxu |
||||||||
4 | { |
||||||||
5 | |||||||||
6 | public $sudoku, |
||||||||
7 | $result, |
||||||||
8 | $number; |
||||||||
9 | private $limit, |
||||||||
10 | $sq, |
||||||||
11 | $chars, |
||||||||
12 | $stack = array('1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); |
||||||||
13 | |||||||||
14 | public function __construct() |
||||||||
15 | { |
||||||||
16 | ini_set('memory_limit', -1); |
||||||||
17 | set_time_limit(0); |
||||||||
18 | |||||||||
19 | ini_set('display_errors',1); |
||||||||
20 | error_reporting(E_ALL); |
||||||||
21 | |||||||||
22 | $this->number = 0; |
||||||||
23 | $this->limit = 16; |
||||||||
24 | $this->sq = (int)sqrt($this->limit); |
||||||||
25 | |||||||||
26 | self::logic(); |
||||||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||||||
27 | |||||||||
28 | return $this; |
||||||||
29 | |||||||||
30 | } |
||||||||
31 | |||||||||
32 | public function logic() |
||||||||
33 | { |
||||||||
34 | if(count($this->stack) < $this->limit) |
||||||||
35 | { |
||||||||
36 | echo 'error'; |
||||||||
37 | exit; |
||||||||
38 | } |
||||||||
39 | } |
||||||||
40 | |||||||||
41 | static function printr($write) |
||||||||
0 ignored issues
–
show
|
|||||||||
42 | { |
||||||||
43 | echo "<pre>"; |
||||||||
44 | print_r($write); |
||||||||
45 | echo "</pre>"; |
||||||||
46 | |||||||||
47 | } |
||||||||
48 | |||||||||
49 | public function set($number) |
||||||||
50 | { |
||||||||
51 | $this->limit = $number; |
||||||||
52 | $this->sq = (int)sqrt($this->limit); |
||||||||
53 | |||||||||
54 | return $this; |
||||||||
55 | |||||||||
56 | } |
||||||||
57 | |||||||||
58 | private function return_row($cell) |
||||||||
59 | { |
||||||||
60 | return floor($cell / $this->limit); |
||||||||
61 | |||||||||
62 | } |
||||||||
63 | |||||||||
64 | private function return_col($cell) |
||||||||
65 | { |
||||||||
66 | return $cell % $this->limit; |
||||||||
67 | |||||||||
68 | } |
||||||||
69 | |||||||||
70 | private function return_block($cell) |
||||||||
71 | { |
||||||||
72 | return floor(self::return_row($cell) / $this->sq) * $this->sq + floor(self::return_col($cell) / $this->sq); |
||||||||
0 ignored issues
–
show
The method
sudoxu::return_col() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The method
sudoxu::return_row() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
73 | |||||||||
74 | } |
||||||||
75 | |||||||||
76 | View Code Duplication | private function is_possible_row($number, $row) |
|||||||
77 | { |
||||||||
78 | $possible = true; |
||||||||
79 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
80 | { |
||||||||
81 | if (isset($this->sudoku[$row * $this->limit + $x]) && $this->sudoku[$row * $this->limit + $x] == $number) |
||||||||
82 | { |
||||||||
83 | $possible = false; |
||||||||
84 | } |
||||||||
85 | } |
||||||||
86 | |||||||||
87 | return $possible; |
||||||||
88 | } |
||||||||
89 | |||||||||
90 | View Code Duplication | private function is_possible_col($number, $col) |
|||||||
91 | { |
||||||||
92 | $possible = true; |
||||||||
93 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
94 | { |
||||||||
95 | if (isset($this->sudoku[$col + $this->limit * $x]) && $this->sudoku[$col + $this->limit * $x] == $number) |
||||||||
96 | { |
||||||||
97 | $possible = false; |
||||||||
98 | } |
||||||||
99 | } |
||||||||
100 | |||||||||
101 | return $possible; |
||||||||
102 | } |
||||||||
103 | |||||||||
104 | private function is_possible_block($number, $block) |
||||||||
105 | { |
||||||||
106 | $possible = true; |
||||||||
107 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
108 | { |
||||||||
109 | $index = floor($block / $this->sq) * $this->sq * $this->limit + $x % $this->sq + $this->limit * floor($x / $this->sq) + $this->sq * ($block % $this->sq); |
||||||||
110 | if (isset($this->sudoku[$index]) && $this->sudoku[$index] == $number) |
||||||||
111 | { |
||||||||
112 | $possible = false; |
||||||||
113 | } |
||||||||
114 | } |
||||||||
115 | |||||||||
116 | return $possible; |
||||||||
117 | } |
||||||||
118 | |||||||||
119 | private function is_possible_number($cell, $number) |
||||||||
120 | { |
||||||||
121 | $row = self::return_row($cell); |
||||||||
0 ignored issues
–
show
The method
sudoxu::return_row() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
122 | $col = self::return_col($cell); |
||||||||
0 ignored issues
–
show
The method
sudoxu::return_col() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
123 | $block = self::return_block($cell); |
||||||||
0 ignored issues
–
show
The method
sudoxu::return_block() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
124 | |||||||||
125 | return (self::is_possible_row($number, $row) && self::is_possible_col($number, $col) && self::is_possible_block($number, $block)); |
||||||||
0 ignored issues
–
show
The method
sudoxu::is_possible_col() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The method
sudoxu::is_possible_row() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The method
sudoxu::is_possible_block() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
126 | } |
||||||||
127 | |||||||||
128 | private function is_correct_row($row) |
||||||||
129 | { |
||||||||
130 | $row_temp = array(); |
||||||||
131 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
132 | { |
||||||||
133 | if(!isset($this->sudoku[$row * $this->limit + $x])) |
||||||||
134 | { |
||||||||
135 | $this->sudoku[$row * $this->limit + $x] = null; |
||||||||
136 | } |
||||||||
137 | $row_temp[$x] = $this->sudoku[$row * $this->limit + $x]; |
||||||||
138 | } |
||||||||
139 | |||||||||
140 | return count(array_diff($this->chars, $row_temp)) == 0; |
||||||||
141 | } |
||||||||
142 | |||||||||
143 | private function is_correct_col($col) |
||||||||
144 | { |
||||||||
145 | $col_temp = array(); |
||||||||
146 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
147 | { |
||||||||
148 | $col_temp[$x] = $this->sudoku[$col + $x * $this->limit]; |
||||||||
149 | } |
||||||||
150 | return count(array_diff($this->chars, $col_temp)) == 0; |
||||||||
151 | } |
||||||||
152 | |||||||||
153 | private function is_correct_block($block) |
||||||||
154 | { |
||||||||
155 | $block_temp = array(); |
||||||||
156 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
157 | { |
||||||||
158 | $lookingfor = floor($block / $this->sq) * ($this->sq * $this->limit) + ($x % $this->sq) + $this->limit * floor($x / $this->sq) + $this->sq * ($block % $this->sq); |
||||||||
159 | |||||||||
160 | if (!isset($this->sudoku[$lookingfor])) |
||||||||
161 | { |
||||||||
162 | $this->sudoku[$lookingfor] = null; |
||||||||
163 | } |
||||||||
164 | |||||||||
165 | $block_temp[$x] = $this->sudoku[$lookingfor]; |
||||||||
166 | } |
||||||||
167 | return count(array_diff($this->chars, $block_temp)) == 0; |
||||||||
168 | } |
||||||||
169 | |||||||||
170 | private function is_solved_sudoku() |
||||||||
171 | { |
||||||||
172 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
173 | { |
||||||||
174 | if (!self::is_correct_block($x) or !self::is_correct_row($x) or !self::is_correct_col($x)) |
||||||||
0 ignored issues
–
show
The method
sudoxu::is_correct_row() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The method
sudoxu::is_correct_block() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The method
sudoxu::is_correct_col() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
175 | { |
||||||||
176 | return false; |
||||||||
177 | break; |
||||||||
178 | } |
||||||||
179 | } |
||||||||
180 | return true; |
||||||||
181 | } |
||||||||
182 | |||||||||
183 | private function determine_possible_values($cell) |
||||||||
184 | { |
||||||||
185 | $possible = array(); |
||||||||
186 | for ($x = 0; $x < $this->limit; $x++) |
||||||||
187 | { |
||||||||
188 | if (self::is_possible_number($cell, $this->chars[$x])) |
||||||||
0 ignored issues
–
show
The method
sudoxu::is_possible_number() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
189 | { |
||||||||
190 | array_unshift($possible, $this->chars[$x]); |
||||||||
191 | } |
||||||||
192 | } |
||||||||
193 | |||||||||
194 | return $possible; |
||||||||
195 | } |
||||||||
196 | |||||||||
197 | private function determine_random_possible_value($possible, $cell) |
||||||||
198 | { |
||||||||
199 | return $possible[$cell][rand(0, count($possible[$cell]) - 1)]; |
||||||||
200 | } |
||||||||
201 | |||||||||
202 | private function scan_sudoku_for_unique() |
||||||||
203 | { |
||||||||
204 | $possible = false; |
||||||||
205 | for ($x = 0; $x < $this->limit * $this->limit; $x++) |
||||||||
206 | { |
||||||||
207 | if (!isset($this->sudoku[$x])) |
||||||||
208 | { |
||||||||
209 | $possible[$x] = self::determine_possible_values($x, $this->sudoku); |
||||||||
0 ignored issues
–
show
The method
sudoxu::determine_possible_values() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
210 | if (count($possible[$x]) == 0) |
||||||||
211 | { |
||||||||
212 | return (false); |
||||||||
213 | break; |
||||||||
214 | } |
||||||||
215 | } |
||||||||
216 | } |
||||||||
217 | |||||||||
218 | return $possible; |
||||||||
219 | } |
||||||||
220 | |||||||||
221 | private function remove_attempt($attempt_array, $number) |
||||||||
222 | { |
||||||||
223 | $new_array = array(); |
||||||||
224 | for ($x = 0; $x < count($attempt_array); $x++) |
||||||||
225 | { |
||||||||
226 | if ($attempt_array[$x] != $number) |
||||||||
227 | { |
||||||||
228 | array_unshift($new_array, $attempt_array[$x]); |
||||||||
229 | } |
||||||||
230 | } |
||||||||
231 | return $new_array; |
||||||||
232 | } |
||||||||
233 | |||||||||
234 | |||||||||
235 | private function next_random($possible) |
||||||||
236 | { |
||||||||
237 | $max = $this->limit; |
||||||||
238 | for ($x = 0; $x < $this->limit * $this->limit; $x++) |
||||||||
239 | { |
||||||||
240 | if (!isset($possible[$x])) |
||||||||
241 | { |
||||||||
242 | $possible[$x] = null; |
||||||||
243 | } |
||||||||
244 | |||||||||
245 | if ((count($possible[$x]) <= $max) && (count($possible[$x]) > 0)) |
||||||||
246 | { |
||||||||
247 | $max = count($possible[$x]); |
||||||||
248 | $min_choices = $x; |
||||||||
249 | } |
||||||||
250 | } |
||||||||
251 | return $min_choices; |
||||||||
252 | } |
||||||||
253 | |||||||||
254 | |||||||||
255 | private function build() |
||||||||
256 | { |
||||||||
257 | $this->sudoku = array(); |
||||||||
258 | $this->chars = array(); |
||||||||
259 | |||||||||
260 | for ($i = 0; $i < $this->limit; $i++) |
||||||||
261 | { |
||||||||
262 | $this->chars[] = $this->stack[$i]; |
||||||||
263 | } |
||||||||
264 | } |
||||||||
265 | |||||||||
266 | public function microtime() |
||||||||
267 | { |
||||||||
268 | return microtime(true); |
||||||||
269 | } |
||||||||
270 | |||||||||
271 | public function generate() |
||||||||
272 | { |
||||||||
273 | $start = self::microtime(); |
||||||||
0 ignored issues
–
show
The method
sudoxu::microtime() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
274 | self::build(); |
||||||||
0 ignored issues
–
show
The method
sudoxu::build() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
275 | |||||||||
276 | $x = 0; |
||||||||
277 | $saved = array(); |
||||||||
278 | $saved_sud = array(); |
||||||||
279 | while (!self::is_solved_sudoku()) |
||||||||
0 ignored issues
–
show
The method
sudoxu::is_solved_sudoku() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
280 | { |
||||||||
281 | $x++; |
||||||||
282 | $next_move = self::scan_sudoku_for_unique(); |
||||||||
0 ignored issues
–
show
The method
sudoxu::scan_sudoku_for_unique() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
283 | |||||||||
284 | if ($next_move == false) |
||||||||
285 | { |
||||||||
286 | $next_move = array_pop($saved); |
||||||||
287 | $this->sudoku = array_pop($saved_sud); |
||||||||
288 | } |
||||||||
289 | |||||||||
290 | $what_to_try = self::next_random($next_move); |
||||||||
0 ignored issues
–
show
The method
sudoxu::next_random() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
291 | $attempt = self::determine_random_possible_value($next_move, $what_to_try); |
||||||||
0 ignored issues
–
show
The method
sudoxu::determine_random_possible_value() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
292 | |||||||||
293 | |||||||||
294 | if (count($next_move[$what_to_try]) > 1) |
||||||||
295 | { |
||||||||
296 | $next_move[$what_to_try] = self::remove_attempt($next_move[$what_to_try], $attempt); |
||||||||
0 ignored issues
–
show
The method
sudoxu::remove_attempt() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
297 | array_push($saved, $next_move); |
||||||||
298 | array_push($saved_sud, $this->sudoku); |
||||||||
299 | } |
||||||||
300 | $this->sudoku[$what_to_try] = $attempt; |
||||||||
301 | } |
||||||||
302 | |||||||||
303 | $timing = self::microtime() - $start; |
||||||||
304 | $this->result = array( |
||||||||
305 | 'created_in' => round($timing,2), |
||||||||
306 | 'difficulty' => 'N/A' |
||||||||
307 | ); |
||||||||
308 | |||||||||
309 | self::draw(); |
||||||||
0 ignored issues
–
show
The method
sudoxu::draw() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||
310 | } |
||||||||
311 | |||||||||
312 | |||||||||
313 | public function draw() |
||||||||
314 | { |
||||||||
315 | |||||||||
316 | |||||||||
317 | echo "<table cellpadding='0' cellspacing='0' style='margin:0 auto;font:30px Arial;border:3px solid black'>"; |
||||||||
318 | |||||||||
319 | for ($u = 0; $u < $this->limit; $u++) |
||||||||
320 | { |
||||||||
321 | |||||||||
322 | |||||||||
323 | if (($u + 1) % $this->sq == '0') |
||||||||
324 | { |
||||||||
325 | $border = 3; |
||||||||
326 | } else { |
||||||||
327 | $border = 1; |
||||||||
328 | } |
||||||||
329 | |||||||||
330 | echo '<tr>'; |
||||||||
331 | |||||||||
332 | for ($v = 0; $v < $this->limit; $v++) |
||||||||
333 | { |
||||||||
334 | |||||||||
335 | |||||||||
336 | if (($v + 1) % $this->sq == '0') |
||||||||
337 | { |
||||||||
338 | $border2 = 3; |
||||||||
339 | } else { |
||||||||
340 | $border2 = 1; |
||||||||
341 | } |
||||||||
342 | |||||||||
343 | echo '<td |
||||||||
344 | data-row="'.$u.'" |
||||||||
345 | data-col="'.$v.'" |
||||||||
346 | style="border: 1px solid black;border-bottom:' . $border . 'px solid black;border-right:' . $border2 . 'px solid black;line-height: 50px; width: 50px; text-align: center; vertical-align: middle;">'; |
||||||||
347 | echo($this->sudoku[$v * $this->limit + $u]); |
||||||||
348 | echo '</td>'; |
||||||||
349 | |||||||||
350 | } |
||||||||
351 | |||||||||
352 | echo '</tr>'; |
||||||||
353 | |||||||||
354 | } |
||||||||
355 | |||||||||
356 | echo "</table>"; |
||||||||
357 | |||||||||
358 | echo $this->result['created_in'].' seconds'; |
||||||||
359 | |||||||||
360 | } |
||||||||
361 | |||||||||
362 | } |