Compare commits
	
		
			10 Commits
		
	
	
		
			231612cce4
			...
			1bb8bdc6b0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1bb8bdc6b0 | |||
| 227fa8a257 | |||
| 06231936fb | |||
| f6c80ebcfa | |||
| dccf9b3616 | |||
| 8e279b4800 | |||
| ba7db7a04e | |||
| 3555c49ad4 | |||
| 775398f456 | |||
| 98c245fb9e | 
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | # Sudoku in Löve | ||||||
|  | 
 | ||||||
|  | ## Shortcuts | ||||||
|  | 
 | ||||||
|  | - l: go right | ||||||
|  | - k: go up | ||||||
|  | - j: go down | ||||||
|  | - h: go left | ||||||
|  | - tab: toggle editing bit / small numbers | ||||||
|  | - s: show search space | ||||||
|  | - a: insert certain numbers | ||||||
|  | - u: undo | ||||||
|  | - f: save current state to "lastBoard.txt" | ||||||
|  | - c: solve the puzzle | ||||||
|  | - -: zoom out | ||||||
|  | - =: zoom in | ||||||
| @ -7,3 +7,13 @@ | |||||||
| 7 0 0 0 0 0 0 3 0 | 7 0 0 0 0 0 0 3 0 | ||||||
| 0 0 1 2 3 0 8 6 0 | 0 0 1 2 3 0 8 6 0 | ||||||
| 0 0 0 0 0 0 2 0 1 | 0 0 0 0 0 0 2 0 1 | ||||||
|  | 
 | ||||||
|  | 2 3 4 7 6 5 1 9 8 | ||||||
|  | 1 8 7 9 4 2 6 5 3 | ||||||
|  | 9 5 6 3 8 1 7 2 4 | ||||||
|  | 4 7 8 5 2 3 9 1 6 | ||||||
|  | 6 2 5 1 9 8 3 4 7 | ||||||
|  | 3 1 9 4 7 6 5 8 2 | ||||||
|  | 7 6 2 8 1 9 4 3 5 | ||||||
|  | 5 4 1 2 3 7 8 6 9 | ||||||
|  | 8 9 3 6 5 4 2 7 1 | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								boards/041.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								boards/041.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | 0 0 4 3 0 0 2 0 9 | ||||||
|  | 0 0 5 0 0 9 0 0 1 | ||||||
|  | 0 7 0 0 6 0 0 4 3 | ||||||
|  | 0 0 6 0 0 2 0 8 7 | ||||||
|  | 1 9 0 0 0 7 4 0 0 | ||||||
|  | 0 5 0 0 8 3 0 0 0 | ||||||
|  | 6 0 0 0 0 0 1 0 5 | ||||||
|  | 0 0 3 5 0 8 6 9 0 | ||||||
|  | 0 4 2 9 1 0 3 0 0 | ||||||
							
								
								
									
										19
									
								
								boards/042.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/042.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 9 2 6 0 0 0 0 0 1 | ||||||
|  | 0 5 0 0 0 0 0 2 0 | ||||||
|  | 0 0 0 4 9 0 0 0 7 | ||||||
|  | 0 6 0 0 4 0 0 1 0 | ||||||
|  | 2 0 0 0 0 7 0 0 0 | ||||||
|  | 0 4 5 0 3 0 7 0 0 | ||||||
|  | 0 0 0 0 0 4 0 0 9 | ||||||
|  | 0 9 3 0 0 0 5 0 0 | ||||||
|  | 0 0 0 0 0 0 8 0 6 | ||||||
|  | 
 | ||||||
|  | 9 2 6 3 7 5 4 8 1 | ||||||
|  | 7 5 4 1 6 8 9 2 3 | ||||||
|  | 8 3 1 4 9 2 6 5 7 | ||||||
|  | 3 6 7 8 4 9 2 1 5 | ||||||
|  | 2 8 9 5 1 7 3 6 4 | ||||||
|  | 1 4 5 2 3 6 7 9 8 | ||||||
|  | 5 7 8 6 2 4 1 3 9 | ||||||
|  | 6 9 3 7 8 1 5 4 2 | ||||||
|  | 4 1 2 9 5 3 8 7 6 | ||||||
							
								
								
									
										19
									
								
								boards/043.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/043.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 0 0 0 7 0 0 0 6 | ||||||
|  | 0 6 0 4 0 9 0 8 7 | ||||||
|  | 0 1 0 8 0 0 0 0 9 | ||||||
|  | 0 0 0 0 0 0 4 0 0 | ||||||
|  | 0 0 0 1 0 4 6 0 0 | ||||||
|  | 0 0 4 0 5 0 0 0 0 | ||||||
|  | 3 8 0 5 0 0 0 0 0 | ||||||
|  | 0 0 0 0 0 2 0 7 0 | ||||||
|  | 9 0 6 0 0 0 5 0 2 | ||||||
|  | 
 | ||||||
|  | 4 9 8 2 7 1 3 5 6 | ||||||
|  | 2 6 5 4 3 9 1 8 7 | ||||||
|  | 7 1 3 8 6 5 2 4 9 | ||||||
|  | 6 5 9 7 8 3 4 2 1 | ||||||
|  | 8 3 7 1 2 4 6 9 5 | ||||||
|  | 1 2 4 9 5 6 7 3 8 | ||||||
|  | 3 8 2 5 1 7 9 6 4 | ||||||
|  | 5 4 1 6 9 2 8 7 3 | ||||||
|  | 9 7 6 3 4 8 5 1 2 | ||||||
							
								
								
									
										19
									
								
								boards/044.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/044.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 5 8 4 0 2 3 0 7 0 | ||||||
|  | 0 0 0 8 0 0 0 0 4 | ||||||
|  | 0 0 0 0 0 4 0 0 8 | ||||||
|  | 3 0 6 7 0 0 0 4 0 | ||||||
|  | 4 0 0 0 3 0 0 0 9 | ||||||
|  | 0 1 0 0 0 9 3 0 5 | ||||||
|  | 2 0 0 5 0 0 0 0 0 | ||||||
|  | 6 0 0 0 0 2 0 0 0 | ||||||
|  | 0 4 0 9 7 0 6 2 3 | ||||||
|  | 
 | ||||||
|  | 5 8 4 1 2 3 9 7 6 | ||||||
|  | 1 6 3 8 9 7 2 5 4 | ||||||
|  | 9 2 7 6 5 4 1 3 8 | ||||||
|  | 3 9 6 7 1 5 8 4 2 | ||||||
|  | 4 5 8 2 3 6 7 1 9 | ||||||
|  | 7 1 2 4 8 9 3 6 5 | ||||||
|  | 2 3 1 5 6 8 4 9 7 | ||||||
|  | 6 7 9 3 4 2 5 8 1 | ||||||
|  | 8 4 5 9 7 1 6 2 3 | ||||||
							
								
								
									
										19
									
								
								boards/045.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/045.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 6 0 0 0 0 9 5 8 | ||||||
|  | 0 0 0 0 0 0 0 0 7 | ||||||
|  | 0 0 0 3 0 0 2 0 0 | ||||||
|  | 0 0 0 0 0 5 3 0 0 | ||||||
|  | 7 0 0 0 0 6 0 0 0 | ||||||
|  | 8 0 4 0 1 0 6 0 0 | ||||||
|  | 1 0 0 0 0 0 0 0 3 | ||||||
|  | 5 9 0 0 7 0 0 0 6 | ||||||
|  | 0 2 0 0 0 0 4 0 0 | ||||||
|  | 
 | ||||||
|  | 3 6 2 1 4 7 9 5 8 | ||||||
|  | 4 8 5 6 9 2 1 3 7 | ||||||
|  | 9 7 1 3 5 8 2 6 4 | ||||||
|  | 2 1 6 7 8 5 3 4 9 | ||||||
|  | 7 3 9 4 2 6 5 8 1 | ||||||
|  | 8 5 4 9 1 3 6 7 2 | ||||||
|  | 1 4 8 5 6 9 7 2 3 | ||||||
|  | 5 9 3 2 7 4 8 1 6 | ||||||
|  | 6 2 7 8 3 1 4 9 5 | ||||||
							
								
								
									
										19
									
								
								boards/046.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/046.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 8 9 0 0 0 2 0 4 0 | ||||||
|  | 5 0 0 0 0 0 0 0 3 | ||||||
|  | 0 0 0 0 0 1 0 5 0 | ||||||
|  | 0 0 5 6 0 0 0 9 0 | ||||||
|  | 0 0 2 0 0 0 5 0 0 | ||||||
|  | 0 4 0 0 0 0 0 0 8 | ||||||
|  | 0 0 1 0 4 0 2 0 9 | ||||||
|  | 7 0 0 8 0 0 0 0 6 | ||||||
|  | 0 0 0 3 0 0 0 0 0 | ||||||
|  | 
 | ||||||
|  | 8 9 7 5 3 2 6 4 1 | ||||||
|  | 5 1 6 4 7 8 9 2 3 | ||||||
|  | 2 3 4 9 6 1 8 5 7 | ||||||
|  | 1 7 5 6 8 4 3 9 2 | ||||||
|  | 6 8 2 1 9 3 5 7 4 | ||||||
|  | 9 4 3 2 5 7 1 6 8 | ||||||
|  | 3 5 1 7 4 6 2 8 9 | ||||||
|  | 7 2 9 8 1 5 4 3 6 | ||||||
|  | 4 6 8 3 2 9 7 1 5 | ||||||
							
								
								
									
										19
									
								
								boards/047.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/047.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 0 0 0 0 1 8 0 7 | ||||||
|  | 4 0 0 0 0 5 0 2 0 | ||||||
|  | 0 0 0 0 2 0 0 5 9 | ||||||
|  | 0 3 0 0 0 0 2 1 4 | ||||||
|  | 1 0 0 4 3 7 0 0 6 | ||||||
|  | 6 4 5 0 0 0 0 8 0 | ||||||
|  | 5 2 0 0 6 0 0 0 0 | ||||||
|  | 0 1 0 7 0 0 0 0 2 | ||||||
|  | 7 0 6 2 0 0 0 0 0 | ||||||
|  | 
 | ||||||
|  | 2 5 3 6 9 1 8 4 7 | ||||||
|  | 4 6 9 8 7 5 3 2 1 | ||||||
|  | 8 7 1 3 2 4 6 5 9 | ||||||
|  | 9 3 7 5 8 6 2 1 4 | ||||||
|  | 1 8 2 4 3 7 5 9 6 | ||||||
|  | 6 4 5 9 1 2 7 8 3 | ||||||
|  | 5 2 4 1 6 3 9 7 8 | ||||||
|  | 3 1 8 7 5 9 4 6 2 | ||||||
|  | 7 9 6 2 4 8 1 3 5 | ||||||
							
								
								
									
										19
									
								
								boards/048.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/048.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 8 0 0 6 1 0 0 0 0 | ||||||
|  | 0 2 7 0 0 0 4 0 6 | ||||||
|  | 0 1 6 0 7 0 8 0 0 | ||||||
|  | 0 3 0 0 6 5 2 0 0 | ||||||
|  | 0 0 0 0 9 0 0 0 0 | ||||||
|  | 0 0 4 8 2 0 0 5 0 | ||||||
|  | 0 0 1 0 8 0 6 4 0 | ||||||
|  | 4 0 9 0 0 0 7 8 0 | ||||||
|  | 0 0 0 0 4 6 0 0 9 | ||||||
|  | 
 | ||||||
|  | 8 4 3 6 1 2 9 7 5 | ||||||
|  | 9 2 7 5 3 8 4 1 6 | ||||||
|  | 5 1 6 4 7 9 8 2 3 | ||||||
|  | 1 3 8 7 6 5 2 9 4 | ||||||
|  | 2 7 5 3 9 4 1 6 8 | ||||||
|  | 6 9 4 8 2 1 3 5 7 | ||||||
|  | 3 5 1 9 8 7 6 4 2 | ||||||
|  | 4 6 9 2 5 3 7 8 1 | ||||||
|  | 7 8 2 1 4 6 5 3 9 | ||||||
							
								
								
									
										19
									
								
								boards/049.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/049.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 1 0 6 0 0 0 7 3 | ||||||
|  | 9 0 0 0 0 0 0 0 4 | ||||||
|  | 0 4 0 2 0 0 0 0 0 | ||||||
|  | 0 7 0 0 0 8 4 0 0 | ||||||
|  | 0 0 4 0 0 0 6 0 0 | ||||||
|  | 3 0 0 0 0 0 0 1 0 | ||||||
|  | 7 0 6 0 1 0 2 0 0 | ||||||
|  | 8 0 0 0 0 3 0 0 5 | ||||||
|  | 0 0 0 0 0 9 0 0 0 | ||||||
|  | 
 | ||||||
|  | 2 1 8 6 9 4 5 7 3 | ||||||
|  | 9 6 7 3 5 1 8 2 4 | ||||||
|  | 5 4 3 2 8 7 1 9 6 | ||||||
|  | 6 7 9 1 3 8 4 5 2 | ||||||
|  | 1 5 4 9 7 2 6 3 8 | ||||||
|  | 3 8 2 5 4 6 9 1 7 | ||||||
|  | 7 3 6 8 1 5 2 4 9 | ||||||
|  | 8 9 1 4 2 3 7 6 5 | ||||||
|  | 4 2 5 7 6 9 3 8 1 | ||||||
							
								
								
									
										19
									
								
								boards/050.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/050.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 4 0 0 7 2 1 0 8 | ||||||
|  | 0 0 0 3 0 6 5 4 0 | ||||||
|  | 0 0 0 0 0 4 0 0 3 | ||||||
|  | 0 0 0 0 8 0 0 5 6 | ||||||
|  | 0 0 7 0 9 0 4 0 0 | ||||||
|  | 4 8 0 0 2 0 0 0 0 | ||||||
|  | 7 0 0 5 0 0 0 0 0 | ||||||
|  | 0 6 4 2 0 9 0 0 0 | ||||||
|  | 8 0 5 7 6 0 0 2 0 | ||||||
|  | 
 | ||||||
|  | 5 4 3 9 7 2 1 6 8 | ||||||
|  | 9 7 8 3 1 6 5 4 2 | ||||||
|  | 6 2 1 8 5 4 7 9 3 | ||||||
|  | 3 1 9 4 8 7 2 5 6 | ||||||
|  | 2 5 7 6 9 3 4 8 1 | ||||||
|  | 4 8 6 1 2 5 9 3 7 | ||||||
|  | 7 3 2 5 4 8 6 1 9 | ||||||
|  | 1 6 4 2 3 9 8 7 5 | ||||||
|  | 8 9 5 7 6 1 3 2 4 | ||||||
							
								
								
									
										19
									
								
								boards/051.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/051.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 3 4 0 0 0 0 7 6 0 | ||||||
|  | 2 0 0 0 0 0 0 0 0 | ||||||
|  | 5 0 1 7 0 6 0 0 8 | ||||||
|  | 0 0 0 2 6 0 0 0 0 | ||||||
|  | 0 0 0 0 0 9 0 4 0 | ||||||
|  | 0 0 7 0 0 0 0 0 0 | ||||||
|  | 0 0 0 0 0 8 0 0 0 | ||||||
|  | 6 0 0 0 0 0 0 5 1 | ||||||
|  | 0 0 0 0 4 3 9 2 0 | ||||||
|  | 
 | ||||||
|  | 3 4 8 5 9 1 7 6 2 | ||||||
|  | 2 7 6 8 3 4 1 9 5 | ||||||
|  | 5 9 1 7 2 6 4 3 8 | ||||||
|  | 4 1 3 2 6 7 5 8 9 | ||||||
|  | 8 5 2 3 1 9 6 4 7 | ||||||
|  | 9 6 7 4 8 5 2 1 3 | ||||||
|  | 1 2 9 6 5 8 3 7 4 | ||||||
|  | 6 3 4 9 7 2 8 5 1 | ||||||
|  | 7 8 5 1 4 3 9 2 6 | ||||||
							
								
								
									
										19
									
								
								boards/052.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/052.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 6 0 0 0 0 5 9 3 | ||||||
|  | 0 0 0 0 0 0 0 0 4 | ||||||
|  | 0 0 0 7 0 0 2 0 0 | ||||||
|  | 0 0 0 0 0 9 7 0 0 | ||||||
|  | 4 0 0 0 0 6 0 0 0 | ||||||
|  | 3 0 8 0 1 0 6 0 0 | ||||||
|  | 1 0 0 0 0 0 0 0 7 | ||||||
|  | 9 5 0 0 4 0 0 0 6 | ||||||
|  | 0 2 0 0 0 0 8 0 0 | ||||||
|  | 
 | ||||||
|  | 7 6 2 1 8 4 5 9 3 | ||||||
|  | 8 3 9 6 5 2 1 7 4 | ||||||
|  | 5 4 1 7 9 3 2 6 8 | ||||||
|  | 2 1 6 4 3 9 7 8 5 | ||||||
|  | 4 7 5 8 2 6 9 3 1 | ||||||
|  | 3 9 8 5 1 7 6 4 2 | ||||||
|  | 1 8 3 9 6 5 4 2 7 | ||||||
|  | 9 5 7 2 4 8 3 1 6 | ||||||
|  | 6 2 4 3 7 1 8 5 9 | ||||||
							
								
								
									
										19
									
								
								boards/053.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/053.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 0 0 0 5 8 0 0 4 | ||||||
|  | 8 0 7 0 0 0 1 3 0 | ||||||
|  | 0 0 4 0 1 0 8 5 0 | ||||||
|  | 0 0 3 2 8 0 0 9 0 | ||||||
|  | 0 0 0 0 6 0 0 0 0 | ||||||
|  | 0 2 0 0 3 4 7 0 0 | ||||||
|  | 0 7 8 0 4 0 5 0 0 | ||||||
|  | 0 4 1 0 0 0 6 0 7 | ||||||
|  | 6 0 0 8 7 0 0 0 0 | ||||||
|  | 
 | ||||||
|  | 2 1 6 3 5 8 9 7 4 | ||||||
|  | 8 5 7 4 9 2 1 3 6 | ||||||
|  | 9 3 4 6 1 7 8 5 2 | ||||||
|  | 7 6 3 2 8 1 4 9 5 | ||||||
|  | 4 8 5 7 6 9 2 1 3 | ||||||
|  | 1 2 9 5 3 4 7 6 8 | ||||||
|  | 3 7 8 1 4 6 5 2 9 | ||||||
|  | 5 4 1 9 2 3 6 8 7 | ||||||
|  | 6 9 2 8 7 5 3 4 1 | ||||||
							
								
								
									
										19
									
								
								boards/054.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/054.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 3 6 0 7 8 0 0 1 | ||||||
|  | 7 0 0 5 0 0 0 0 4 | ||||||
|  | 0 0 0 0 0 3 0 0 7 | ||||||
|  | 9 0 1 0 0 2 0 4 0 | ||||||
|  | 2 0 0 0 8 0 0 0 6 | ||||||
|  | 0 6 0 9 0 0 7 0 8 | ||||||
|  | 3 0 0 8 0 0 0 0 0 | ||||||
|  | 6 0 0 0 0 7 0 0 2 | ||||||
|  | 8 0 0 1 9 0 4 7 0 | ||||||
|  | 
 | ||||||
|  | 4 3 6 2 7 8 9 5 1 | ||||||
|  | 7 2 8 5 1 9 6 3 4 | ||||||
|  | 1 9 5 6 4 3 2 8 7 | ||||||
|  | 9 8 1 7 6 2 3 4 5 | ||||||
|  | 2 7 3 4 8 5 1 9 6 | ||||||
|  | 5 6 4 9 3 1 7 2 8 | ||||||
|  | 3 1 7 8 2 4 5 6 9 | ||||||
|  | 6 4 9 3 5 7 8 1 2 | ||||||
|  | 8 5 2 1 9 6 4 7 3 | ||||||
							
								
								
									
										19
									
								
								boards/055.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/055.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 0 8 0 0 0 2 4 5 0 | ||||||
|  | 9 0 3 4 0 0 0 0 0 | ||||||
|  | 0 0 0 0 3 0 1 0 0 | ||||||
|  | 1 0 6 0 0 0 0 0 0 | ||||||
|  | 0 0 0 0 0 0 9 0 0 | ||||||
|  | 0 0 0 5 0 0 0 2 8 | ||||||
|  | 0 0 0 3 1 0 6 0 0 | ||||||
|  | 4 0 0 0 0 9 0 0 0 | ||||||
|  | 2 3 0 0 0 0 0 7 0 | ||||||
|  | 
 | ||||||
|  | 6 8 7 1 9 2 4 5 3 | ||||||
|  | 9 1 3 4 7 5 2 8 6 | ||||||
|  | 5 4 2 8 3 6 1 9 7 | ||||||
|  | 1 2 6 9 8 7 5 3 4 | ||||||
|  | 8 7 5 2 4 3 9 6 1 | ||||||
|  | 3 9 4 5 6 1 7 2 8 | ||||||
|  | 7 5 9 3 1 8 6 4 2 | ||||||
|  | 4 6 8 7 2 9 3 1 5 | ||||||
|  | 2 3 1 6 5 4 8 7 9 | ||||||
							
								
								
									
										19
									
								
								boards/056.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								boards/056.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 8 2 0 0 0 0 7 0 3 | ||||||
|  | 7 0 0 5 4 0 1 0 0 | ||||||
|  | 5 6 0 0 0 7 0 0 0 | ||||||
|  | 0 0 3 0 0 0 0 0 0 | ||||||
|  | 0 0 0 0 5 0 0 0 9 | ||||||
|  | 0 0 0 4 0 1 0 0 0 | ||||||
|  | 9 0 0 0 0 0 0 2 0 | ||||||
|  | 0 0 7 8 2 0 3 1 0 | ||||||
|  | 0 0 0 0 0 0 8 0 7 | ||||||
|  | 
 | ||||||
|  | 8 2 4 9 1 6 7 5 3 | ||||||
|  | 7 3 9 5 4 8 1 6 2 | ||||||
|  | 5 6 1 2 3 7 9 8 4 | ||||||
|  | 4 9 3 6 8 2 5 7 1 | ||||||
|  | 1 8 6 7 5 3 2 4 9 | ||||||
|  | 2 7 5 4 9 1 6 3 8 | ||||||
|  | 9 1 8 3 7 5 4 2 6 | ||||||
|  | 6 4 7 8 2 9 3 1 5 | ||||||
|  | 3 5 2 1 6 4 8 9 7 | ||||||
							
								
								
									
										9
									
								
								boards/057.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								boards/057.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | 0 6 0 0 0 0 0 0 9 | ||||||
|  | 0 0 0 0 0 3 5 8 0 | ||||||
|  | 0 4 5 6 0 0 1 7 0 | ||||||
|  | 0 0 0 9 0 0 0 0 1 | ||||||
|  | 6 0 9 8 4 1 7 0 5 | ||||||
|  | 1 0 0 0 0 2 0 0 0 | ||||||
|  | 0 7 1 0 0 8 9 6 0 | ||||||
|  | 0 9 6 2 0 0 0 0 0 | ||||||
|  | 4 0 0 0 0 0 0 1 0 | ||||||
| @ -1,6 +1,6 @@ | |||||||
| return { | return { | ||||||
|     board = { |     board = { | ||||||
|         filePath = "boards/040.txt", |         filePath = "boards/057.txt", | ||||||
|     }, |     }, | ||||||
|     window = { |     window = { | ||||||
|         bgColor = "FFFFFF", |         bgColor = "FFFFFF", | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								main.lua
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								main.lua
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| require "sudoku.utils" | sudoku = require "sudoku.sudoku" | ||||||
| uiUtils = require "ui.utils" | uiUtils = require "ui.utils" | ||||||
| config = require "config" | config = require "config" | ||||||
| SudokuCanvas = require "ui.sudokucanvas" | SudokuCanvas = require "ui.sudokucanvas" | ||||||
| @ -11,10 +11,10 @@ function love.load() | |||||||
|     love.mouse.setGrabbed(false) |     love.mouse.setGrabbed(false) | ||||||
|     love.keyboard.setKeyRepeat(true) |     love.keyboard.setKeyRepeat(true) | ||||||
|     math.randomseed(os.time()) |     math.randomseed(os.time()) | ||||||
|     local board = loadBoard(config.board.filePath) |     board = sudoku.loadBoard(config.board.filePath) | ||||||
|     local width, height = love.graphics.getDimensions() |     local width, height = love.graphics.getDimensions() | ||||||
|     sudokuCanvas = SudokuCanvas:new(200, 100, height/1.5, config.SudokuCanvas) |     sudokuCanvas = SudokuCanvas:new(500, 50, height/1.1, config.SudokuCanvas) | ||||||
|     sudokuCanvas:setBoard(board) |     sudokuCanvas:setBoard(board[1]) | ||||||
|     myFont = love.graphics.newFont(24) |     myFont = love.graphics.newFont(24) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
								
							| @ -1,132 +0,0 @@ | |||||||
| local function checkCT(ct) |  | ||||||
|     local r = {} |  | ||||||
|     for i = 1, 8 do |  | ||||||
|         for j = i+1, 9 do |  | ||||||
|             if ct[i] == ct[j] and ct[i] ~= 0 then |  | ||||||
|                 table.insert(r, {i, j}) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if #r > 0 then return false, r end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| local function findThisTable(this, that) |  | ||||||
|     for i = 1, #that do |  | ||||||
|         if #that[i] == #this then |  | ||||||
|             local flag = true |  | ||||||
|             for j = 1, #this do |  | ||||||
|                 if this[j] ~= that[i][j] then flag = false; break end |  | ||||||
|             end |  | ||||||
|             if flag then return true, i end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return false |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function check(board) |  | ||||||
|     local rr = {} |  | ||||||
|     for x = 1, 9 do |  | ||||||
|         local ct = {} |  | ||||||
|         for y = 1, 9 do |  | ||||||
|             ct[y] = board[x][y] |  | ||||||
|         end |  | ||||||
|         local ok, r = checkCT(ct) |  | ||||||
|         if not ok then |  | ||||||
|             for _, p in ipairs(r) do |  | ||||||
|                 local t = {x, p[1], x, p[2], board[x][p[1]]} |  | ||||||
|                 if not findThisTable(t, rr) then |  | ||||||
|                     table.insert(rr, t) |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for y = 1, 9 do |  | ||||||
|         local ct = {} |  | ||||||
|         for x = 1, 9 do |  | ||||||
|             ct[x] = board[x][y] |  | ||||||
|         end |  | ||||||
|         local ok, r = checkCT(ct) |  | ||||||
|         if not ok then |  | ||||||
|             for _, p in ipairs(r) do |  | ||||||
|                 local t = {p[1], y, p[2], y, board[p[1]][y]} |  | ||||||
|                 if not findThisTable(t, rr) then |  | ||||||
|                     table.insert(rr, t) |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for i = 0, 2 do |  | ||||||
|         for j = 0, 2 do |  | ||||||
|             local ct = {} |  | ||||||
|             for x = 1, 3 do |  | ||||||
|                 for y = 1, 3 do |  | ||||||
|                     ct[(x-1)*3+y] = board[x+i*3][y+j*3] |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|             local ok, r = checkCT(ct) |  | ||||||
|             if not ok then |  | ||||||
|                 for _, p in ipairs(r) do |  | ||||||
|                     -- local x1 = ((p[1] - 1) // 3 + 1) + i * 3 |  | ||||||
|                     local x1 = math.floor((p[1] - 1) / 3 + 1) + i * 3 |  | ||||||
|                     local y1 = ((p[1] - 1) % 3 + 1) + j * 3 |  | ||||||
|                     -- local x2 = ((p[2] - 1) // 3 + 1) + i * 3 |  | ||||||
|                     local x2 = math.floor((p[2] - 1) / 3 + 1) + i * 3 |  | ||||||
|                     local y2 = ((p[2] - 1) % 3 + 1) + j * 3 |  | ||||||
|                     local t = {x1, y1, x2, y2, board[x1][y1]} |  | ||||||
|                     if not findThisTable(t, rr) then |  | ||||||
|                         table.insert(rr, t) |  | ||||||
|                     end |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if #rr > 0 then |  | ||||||
|         return false, rr |  | ||||||
|     end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function checkSolved(board) |  | ||||||
|     local r = {} |  | ||||||
|     for i = 1, 9 do |  | ||||||
|         for j = 1, 9 do |  | ||||||
|             if board[i][j] < 1 or board[i][j] > 9 then |  | ||||||
|                 table.insert(r, {i, j, board[i][j]}) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     local ok, rr = check(board) |  | ||||||
|     if #r > 0 or (rr and #rr > 0) then |  | ||||||
|         return false, r, rr |  | ||||||
|     end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function pcheck(board) |  | ||||||
|     local ok, r, rr = checkSolved(board) |  | ||||||
|     if ok then |  | ||||||
|         print("Board is solved!") |  | ||||||
|         return  |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(r) do |  | ||||||
|         print(S("(%d, %d) = %d", unpack(p))) |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(rr) do |  | ||||||
|         print(S("(%d, %d) = (%d, %d) = %d", unpack(p))) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function scheck(board) |  | ||||||
|     local msg = {} |  | ||||||
|     local ok, r = check(board) |  | ||||||
|     if ok then |  | ||||||
|         return {"No Error!"} |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(r) do |  | ||||||
|         local s = string.format("(%d, %d) = (%d, %d) = %d", unpack(p)) |  | ||||||
|         print(s) |  | ||||||
|         table.insert(msg, s) |  | ||||||
|     end |  | ||||||
|     return msg |  | ||||||
| end |  | ||||||
| @ -1,47 +1,510 @@ | |||||||
| require "sudoku.utils" | -- dbg = require ("debugger") | ||||||
| require "sudoku.check" | -- dbg.auto_where = 2 | ||||||
| 
 | 
 | ||||||
| function calValidOptions(b, x, y) | function table2string(t) | ||||||
|     if b[x][y] ~= 0 then return {} end |     local myself = table2string | ||||||
|     local elm |     local l = {} | ||||||
|  |     local n = 0 | ||||||
|  |     for k, v in pairs(t) do | ||||||
|  |         n = n + 1 | ||||||
|  |         if type(v) == "table" then | ||||||
|  |             l[n] = k .. ': ' .. myself(v) | ||||||
|  |         elseif type(v) == "string" then | ||||||
|  |             l[n] = k .. ': ' .. '"' .. v .. '"' | ||||||
|  |         else | ||||||
|  |             l[n] = k .. ': ' .. v | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return "{" .. table.concat(l, ", ") .. "}" | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function find(array, element) | ||||||
|  |     local index = 0 | ||||||
|  |     for i = 1, #array do | ||||||
|  |         if array[i] == element then | ||||||
|  |             index = i | ||||||
|  |             break | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return index | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function createEmptyBoard() | ||||||
|  |     local b = {} | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         b[i] = {} | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             b[i][j] = 0 | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return b | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function cloneBoard(b) | ||||||
|  |     local c = {} | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         c[i] = {} | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             c[i][j] = b[i][j] | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return c | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function loadBoard(fn) | ||||||
|  |     local boards = {} | ||||||
|  |     local r = 0 | ||||||
|  |     local board = {} | ||||||
|  |     for line in io.lines(fn) do | ||||||
|  |         if line:gsub("%s+", "") == "" then | ||||||
|  |             table.insert(boards, board) | ||||||
|  |             board = {} | ||||||
|  |             r = 0 | ||||||
|  |         else | ||||||
|  |             r = r + 1 | ||||||
|  |             local c = 0 | ||||||
|  |             board[r] = {} | ||||||
|  |             for item in line:gmatch("%w+") do | ||||||
|  |                 c = c + 1 | ||||||
|  |                 board[r][c] = tonumber(item) | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     table.insert(boards, board) | ||||||
|  |     return boards | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function saveBoard(fn, b1, b2) | ||||||
|  |     local f = io.open(fn, "w") | ||||||
|  |     for row = 1, 9 do | ||||||
|  |         f:write(table.concat(b1[row], " ")) | ||||||
|  |         f:write("\n") | ||||||
|  |     end | ||||||
|  |     f:write("\n") | ||||||
|  |     for row = 1, 9 do | ||||||
|  |         f:write(table.concat(b2[row], " ")) | ||||||
|  |         f:write("\n") | ||||||
|  |     end | ||||||
|  |     f:close() | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function showBoard(board) | ||||||
|  |     for row = 1, 9 do | ||||||
|  |         print(table.concat(board[row], " ")) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function checkBoardsEqual(b1, b2) | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             if b1[i][j] ~= b2[i][j] then return false end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return true | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function iterZones(board) | ||||||
|  |     local row = 0 | ||||||
|  |     local column = 0 | ||||||
|  |     local block = 0 | ||||||
|  |     return function() | ||||||
|  |         local a = {} | ||||||
|  |         local p = {} | ||||||
|  |         if row < 9 then | ||||||
|  |             row = row + 1 | ||||||
|  |             for i = 1, 9 do | ||||||
|  |                 a[i] = board[row][i] | ||||||
|  |                 p[i] = {row, i} | ||||||
|  |             end | ||||||
|  |             return a, p | ||||||
|  |         end | ||||||
|  |         if column < 9 then | ||||||
|  |             column = column + 1 | ||||||
|  |             for i = 1, 9 do | ||||||
|  |                 a[i] = board[i][column] | ||||||
|  |                 p[i] = {i, column} | ||||||
|  |             end | ||||||
|  |             return a, p | ||||||
|  |         end | ||||||
|  |         if block < 9 then | ||||||
|  |             block = block + 1 | ||||||
|  |             local dx = math.floor((block - 1) / 3) | ||||||
|  |             local dy = (block - 1) % 3 | ||||||
|  |             local n = 0 | ||||||
|  |             for i = 1, 3 do | ||||||
|  |                 for j = 1, 3 do | ||||||
|  |                     local x = i + 3 * dx | ||||||
|  |                     local y = j + 3 * dy | ||||||
|  |                     n = n + 1 | ||||||
|  |                     a[n] = board[x][y] | ||||||
|  |                     p[n] = {x, y} | ||||||
|  |                 end | ||||||
|  |             end | ||||||
|  |             return a, p | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function checkAUX(zone, pos) | ||||||
|  |     local isComplete = true | ||||||
|  |     local ok = true | ||||||
|  |     local conflictList = {} | ||||||
|  |     local n = 0 | ||||||
|  |     for i = 1, 8 do | ||||||
|  |         for j = i+1, 9 do | ||||||
|  |             if zone[i] == 0 then | ||||||
|  |                 isComplete = false | ||||||
|  |             elseif zone[i] == zone[j] then | ||||||
|  |                 ok = false | ||||||
|  |                 n = n + 1 | ||||||
|  |                 conflictList[n] = {x1=pos[i][1], y1=pos[i][2], x2=pos[j][1], y2=pos[j][2]} | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return ok, isComplete, conflictList | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function checkBoard(board) | ||||||
|  |     local ok = true | ||||||
|  |     local isComplete = true | ||||||
|  |     local conflictList = {} | ||||||
|  |     for zone, pos in iterZones(board) do | ||||||
|  |         local tOk, tIsComplete, tConflictList = checkAUX(zone, pos) | ||||||
|  |         if not tOk then ok = false end | ||||||
|  |         if not tIsComplete then isComplete = false end | ||||||
|  |         for _, conflict in ipairs(tConflictList) do | ||||||
|  |             table.insert(conflictList, conflict) | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     if not ok then isComplete = false end | ||||||
|  |     return ok, isComplete, conflictList | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function calCellValidOptions(board, x, y) | ||||||
|  |     if board[x][y] ~= 0 then return {} end | ||||||
|     local u = {} |     local u = {} | ||||||
|     local v = {} |     local v = {} | ||||||
|     for i = 1, 9 do |     for i = 1, 9 do | ||||||
|         elm = b[x][i] |         if board[x][i] ~= 0 then table.insert(u, board[x][i]) end | ||||||
|         if elm ~= 0 and find(u, elm) == 0 then |         if board[i][y] ~= 0 then table.insert(u, board[i][y]) end | ||||||
|             table.insert(u, elm) |  | ||||||
|     end |     end | ||||||
|         elm = b[i][y] |     local dx = math.floor((x - 1) / 3) * 3 | ||||||
|         if elm ~= 0 and find(u, elm) == 0 then |     local dy = math.floor((y - 1) / 3) * 3 | ||||||
|             table.insert(u, elm) |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     -- local xc = ((x - 1) // 3) * 3 |  | ||||||
|     -- local yc = ((y - 1) // 3) * 3 |  | ||||||
|     local xc = math.floor((x - 1) / 3) * 3 |  | ||||||
|     local yc = math.floor((y - 1) / 3) * 3 |  | ||||||
|     for i = 1, 3 do |     for i = 1, 3 do | ||||||
|         for j = 1, 3 do |         for j = 1, 3 do | ||||||
|             elm = b[i+xc][j+yc] |             local a = board[i+dx][j+dy] | ||||||
|             if elm ~= 0 and find(u, elm) == 0 then |             if a ~= 0 then table.insert(u, a) end | ||||||
|                 table.insert(u, elm) |  | ||||||
|             end |  | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|     for i = 1, 9 do |     for i = 1, 9 do | ||||||
|         if find(u, i) == 0 then table.insert(v, i) end |         local found = false | ||||||
|  |         for _, elm in ipairs(u) do | ||||||
|  |             if elm == i then found = true; break end | ||||||
|  |         end | ||||||
|  |         if not found then table.insert(v, i) end | ||||||
|     end |     end | ||||||
|     return v |     return v | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function buildSearchSpace(b) | function buildSearchSpace(board) | ||||||
|     local s = {} |     local s = {} | ||||||
|     for i = 1, 9 do |     for i = 1, 9 do | ||||||
|         s[i] = {} |         s[i] = {} | ||||||
|         for j = 1, 9 do |         for j = 1, 9 do | ||||||
|             s[i][j] = calValidOptions(b, i, j) |             s[i][j] = calCellValidOptions(board, i, j) | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|     return s |     return s | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | function findPairsIndSearchSpace(board, searchSpace) | ||||||
|  |     local r = {} | ||||||
|  |     local zoneIndex = 0 | ||||||
|  |     for zone, pos in iterZones(board) do | ||||||
|  |         zoneIndex = zoneIndex + 1 | ||||||
|  |         for i = 1, 8 do | ||||||
|  |             local x1 = pos[i][1] | ||||||
|  |             local y1 = pos[i][2] | ||||||
|  |             local s1 = searchSpace[x1][y1] | ||||||
|  |             if #s1 == 2 then | ||||||
|  |                 for j = i + 1, 9 do | ||||||
|  |                     local x2 = pos[j][1] | ||||||
|  |                     local y2 = pos[j][2] | ||||||
|  |                     local s2 = searchSpace[x2][y2] | ||||||
|  |                     if #s2 == 2 then | ||||||
|  |                         if s1[1] == s2[1] and s1[2] == s2[2] then | ||||||
|  |                             -- if zoneIndex <= 18 or x1 ~= x2 and y1 ~= y2 then | ||||||
|  |                             table.insert(r, {zoneIndex=zoneIndex, cells={i, j}, pair=s1}) | ||||||
|  |                                 -- print("----------") | ||||||
|  |                                 -- print("zone: ", zoneIndex) | ||||||
|  |                                 -- print(table2string(zone)) | ||||||
|  |                                 -- print(i, j) | ||||||
|  |                                 -- print(table2string(s1)) | ||||||
|  |                             -- end | ||||||
|  |                         end | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return r | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function showSearchSpace(s) | ||||||
|  |     local hl = ("+-------+-------+-------+-------+-------+-------+-------+-------+-------+") | ||||||
|  |     print(hl) | ||||||
|  |     for i = 1, 27 do | ||||||
|  |         local x = math.floor((i - 1) / 3) + 1 | ||||||
|  |         local a = (i - 1) % 3 | ||||||
|  |         local row = {} | ||||||
|  |         for j = 1, 27 do | ||||||
|  |             local y = math.floor((j - 1) / 3) + 1 | ||||||
|  |             local k = ((j - 1) % 3 + 1) + 3 * a | ||||||
|  |             local found = false | ||||||
|  |             for _, m in ipairs(s[x][y]) do | ||||||
|  |                 if m == k then found = true; break end | ||||||
|  |             end | ||||||
|  |             if found then | ||||||
|  |                 table.insert(row, k) | ||||||
|  |             else | ||||||
|  |                 table.insert(row, " ") | ||||||
|  |             end | ||||||
|  |             if j % 3 == 0 then table.insert(row, "|") end | ||||||
|  |         end | ||||||
|  |         print("| "..table.concat(row, " ")) | ||||||
|  |         if i % 3 == 0 then print(hl) end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function getZoneByIndex(board, zoneIndex) | ||||||
|  |     local index = (zoneIndex - 1) % 9 + 1 | ||||||
|  |     local block = math.floor((zoneIndex - 1) / 9) + 1 | ||||||
|  |     local a = {} | ||||||
|  |     local p = {} | ||||||
|  |     if block == 1 then | ||||||
|  |         for i = 1, 9 do | ||||||
|  |             a[i] = board[index][i] | ||||||
|  |             p[i] = {index, i} | ||||||
|  |         end | ||||||
|  |     elseif block == 2 then | ||||||
|  |         for i = 1, 9 do | ||||||
|  |             a[i] = board[i][index] | ||||||
|  |             p[i] = {index, i} | ||||||
|  |         end | ||||||
|  |     elseif block == 3 then | ||||||
|  |         local dx = math.floor((index - 1) / 3) | ||||||
|  |         local dy = (index - 1) % 3 | ||||||
|  |         local n = 0 | ||||||
|  |         for i = 1, 3 do | ||||||
|  |             for j = 1, 3 do | ||||||
|  |                 local x = i + 3 * dx | ||||||
|  |                 local y = j + 3 * dy | ||||||
|  |                 n = n + 1 | ||||||
|  |                 a[n] = board[x][y] | ||||||
|  |                 p[n] = {x, y} | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return a, p | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function getZonePosByIndex(zoneIndex) | ||||||
|  |     local index = (zoneIndex - 1) % 9 + 1 | ||||||
|  |     local block = math.floor((zoneIndex - 1) / 9) + 1 | ||||||
|  |     local p = {} | ||||||
|  |     if block == 1 then | ||||||
|  |         for i = 1, 9 do | ||||||
|  |             p[i] = {index, i} | ||||||
|  |         end | ||||||
|  |     elseif block == 2 then | ||||||
|  |         for i = 1, 9 do | ||||||
|  |             p[i] = {index, i} | ||||||
|  |         end | ||||||
|  |     elseif block == 3 then | ||||||
|  |         local dx = math.floor((index - 1) / 3) | ||||||
|  |         local dy = (index - 1) % 3 | ||||||
|  |         local n = 0 | ||||||
|  |         for i = 1, 3 do | ||||||
|  |             for j = 1, 3 do | ||||||
|  |                 local x = i + 3 * dx | ||||||
|  |                 local y = j + 3 * dy | ||||||
|  |                 n = n + 1 | ||||||
|  |                 p[n] = {x, y} | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return p | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function iterZonePos(zoneIndex) | ||||||
|  |     local p = getZonePosByIndex(zoneIndex) | ||||||
|  |     local i = 0 | ||||||
|  |     return function() | ||||||
|  |         if i < 9 then | ||||||
|  |             i = i + 1 | ||||||
|  |             return p[i][1], p[i][2] | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function fillSingles(board, searchSpace) | ||||||
|  |     local count = 0 | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             if #searchSpace[i][j] == 1 then | ||||||
|  |                 board[i][j] = searchSpace[i][j][1] | ||||||
|  |                 count = count + 1 | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return count | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function applyFillSinglesRepeatedly(board, s) | ||||||
|  |     local s = s or buildSearchSpace(board) | ||||||
|  |     local count = fillSingles(board, s) | ||||||
|  |     local total = count | ||||||
|  |     while count ~= 0 do | ||||||
|  |         s = buildSearchSpace(board) | ||||||
|  |         count = fillSingles(board, s) | ||||||
|  |         total = total + count | ||||||
|  |     end | ||||||
|  |     return total | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function eliminatePairsInSearchSpaceAUX(board, searchSpace, pair, zoneIndex, cells) | ||||||
|  |     local _, pos = getZoneByIndex(board, zoneIndex) | ||||||
|  |     local count = 0 | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         if i ~= cells[1] and i ~= cells[2] then | ||||||
|  |             local x = pos[i][1] | ||||||
|  |             local y = pos[i][2] | ||||||
|  |             local del = {} | ||||||
|  |             for index, v in ipairs(searchSpace[x][y]) do | ||||||
|  |                 if v == pair[1] or v == pair[2] then | ||||||
|  |                     count = count + 1 | ||||||
|  |                     table.insert(del, index) | ||||||
|  |                 end | ||||||
|  |             end | ||||||
|  |             for _, index in ipairs(del) do | ||||||
|  |                 table.remove(searchSpace[x][y], index) | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return count | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function eliminatePairsInSearchSpace(board, searchSpace) | ||||||
|  |     local p = findPairsIndSearchSpace(board, searchSpace) | ||||||
|  |     local count = 0 | ||||||
|  |     for _, m in ipairs(p) do | ||||||
|  |         count = count + eliminatePairsInSearchSpaceAUX(board, searchSpace, m.pair, m.zoneIndex, m.cells) | ||||||
|  |     end | ||||||
|  |     return count | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function allPairs(board) | ||||||
|  |     local s = buildSearchSpace(board) | ||||||
|  |     applyFillSinglesRepeatedly(board, s) | ||||||
|  |     eliminatePairsInSearchSpace(board, s) | ||||||
|  |     local count = applyFillSinglesRepeatedly(board, s) | ||||||
|  |     while count ~= 0 do | ||||||
|  |         -- print("--------------------------------------------------") | ||||||
|  |         -- showBoard(board) | ||||||
|  |         -- showSearchSpace(s) | ||||||
|  |         -- print(count) | ||||||
|  |         -- io.read(1) | ||||||
|  |         s = buildSearchSpace(board) | ||||||
|  |         eliminatePairsInSearchSpace(board, s) | ||||||
|  |         count = applyFillSinglesRepeatedly(board, s) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function findFirstEmptyCell(board) | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             if board[i][j] == 0 then | ||||||
|  |                 return i, j | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function checkSearchSpace(board, searchSpace) | ||||||
|  |     local s = searchSpace or buildSearchSpace(board) | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             if board[i][j] == 0 then | ||||||
|  |                 if #s[i][j] == 0 then return false end | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return true | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function findFirstLeastOption(searchSpace) | ||||||
|  |     local min = 9 | ||||||
|  |     local x, y | ||||||
|  |     for i = 1, 9 do | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             local len = #searchSpace[i][j] | ||||||
|  |             if len > 0 and len < min then | ||||||
|  |                 min = len | ||||||
|  |                 x = i | ||||||
|  |                 y = j | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return x, y, min | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function backTrace(trace) | ||||||
|  |     while true do | ||||||
|  |         local currentStep = trace[#trace] | ||||||
|  |         applyFillSinglesRepeatedly(currentStep.board) | ||||||
|  |         local ok, finished = checkBoard(currentStep.board) | ||||||
|  |         if not ok then rollBack(trace); goto endOfTheLoop end | ||||||
|  |         if finished then return currentStep.board end | ||||||
|  |         local s = buildSearchSpace(currentStep.board) | ||||||
|  |         ok = checkSearchSpace(currentStep.board, s) | ||||||
|  |         if not ok then rollBack(trace); goto endOfTheLoop end | ||||||
|  |         if not currentStep.pointer then | ||||||
|  |             local x, y = findFirstLeastOption(s) | ||||||
|  |             currentStep.options = s[x][y] | ||||||
|  |             currentStep.pointer = 0 | ||||||
|  |             currentStep.x = x | ||||||
|  |             currentStep.y = y | ||||||
|  |         end | ||||||
|  |         currentStep.pointer = currentStep.pointer + 1 | ||||||
|  |         if currentStep.pointer > #currentStep.options then rollBack(trace); goto endOfTheLoop end | ||||||
|  |         local nextStep = {} | ||||||
|  |         nextStep.board = cloneBoard(currentStep.board) | ||||||
|  |         nextStep.board[currentStep.x][currentStep.y] = currentStep.options[currentStep.pointer] | ||||||
|  |         trace[#trace+1] = nextStep | ||||||
|  |     ::endOfTheLoop:: | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function rollBack(trace) | ||||||
|  |     assert(#trace > 1, "Something is very wrong!") | ||||||
|  |     table.remove(trace) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function solve(board) | ||||||
|  |     local t = {} | ||||||
|  |     t[1] = {board=cloneBoard(board),} | ||||||
|  |     return backTrace(t) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | return { | ||||||
|  |     loadBoard = loadBoard, | ||||||
|  |     cloneBoard = cloneBoard, | ||||||
|  |     createEmptyBoard = createEmptyBoard, | ||||||
|  |     calCellValidOptions = calCellValidOptions, | ||||||
|  |     checkBoard = checkBoard, | ||||||
|  |     applyFillSinglesRepeatedly = applyFillSinglesRepeatedly, | ||||||
|  |     showBoard = showBoard, | ||||||
|  |     checkBoardsEqual = checkBoardsEqual,  | ||||||
|  |     saveBoard = saveBoard, | ||||||
|  |     solve = solve, | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,49 +0,0 @@ | |||||||
| function find(array, element) |  | ||||||
|     local index = 0 |  | ||||||
|     for i = 1, #array do |  | ||||||
|         if array[i] == element then |  | ||||||
|             index = i |  | ||||||
|             break |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return index |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function showBoard(board) |  | ||||||
|     for row = 1, 9 do |  | ||||||
|         print(table.concat(board[row], " ")) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function cloneBoard(b) |  | ||||||
|     local c = {} |  | ||||||
|     for i = 1, 9 do |  | ||||||
|         c[i] = {} |  | ||||||
|         for j = 1, 9 do |  | ||||||
|             c[i][j] = b[i][j] |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return c |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function loadBoard(fn) |  | ||||||
|     local problem = {} |  | ||||||
|     local solution = {} |  | ||||||
|     local board = problem |  | ||||||
|     local r = 0 |  | ||||||
|     for line in io.lines(fn) do |  | ||||||
|         if line:gsub("%s+", "") == "" then |  | ||||||
|             board = solution |  | ||||||
|             r = 0 |  | ||||||
|         else |  | ||||||
|             r = r + 1 |  | ||||||
|             local c = 0 |  | ||||||
|             board[r] = {} |  | ||||||
|             for item in line:gmatch("%w+") do |  | ||||||
|                 c = c + 1 |  | ||||||
|                 board[r][c] = tonumber(item) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return problem, solution |  | ||||||
| end |  | ||||||
| @ -1,23 +1,65 @@ | |||||||
| function table2string(t) |  | ||||||
|     local myself = table2string |  | ||||||
|     local l = {} |  | ||||||
|     local n = 0 |  | ||||||
|     for k, v in pairs(t) do |  | ||||||
|         n = n + 1 |  | ||||||
|         if type(v) == "table" then |  | ||||||
|             l[n] = k .. ': ' .. myself(v) |  | ||||||
|         elseif type(v) == "string" then |  | ||||||
|             l[n] = k .. ': ' .. '"' .. v .. '"' |  | ||||||
|         else |  | ||||||
|             l[n] = k .. ': ' .. v |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return "{" .. table.concat(l, ", ") .. "}" |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| SudokuCanvas = {} | SudokuCanvas = {} | ||||||
| SudokuCanvas.__index = SudokuCanvas | SudokuCanvas.__index = SudokuCanvas | ||||||
| 
 | 
 | ||||||
|  | function SudokuCanvas:pushHistory() | ||||||
|  |     if #self.history <= 1 then | ||||||
|  |         table.insert(self.history, sudoku.cloneBoard(self.board[2])) | ||||||
|  |         -- showHistory(self) | ||||||
|  |         -- print("pushHistory: ", #self.history) | ||||||
|  |     elseif not sudoku.checkBoardsEqual(self.board[2], self.history[#self.history]) then | ||||||
|  |         table.insert(self.history, sudoku.cloneBoard(self.board[2])) | ||||||
|  |         -- showHistory(self) | ||||||
|  |         -- print("pushHistory: ", #self.history) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function showHistory(self) | ||||||
|  |     for i, v in ipairs(self.history) do | ||||||
|  |         print(string.format("-- [%03d] ----------", i)) | ||||||
|  |         sudoku.showBoard(v) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function undo(self) | ||||||
|  |     if #self.history > 1 then | ||||||
|  |         showHistory(self) | ||||||
|  |         table.remove(self.history) | ||||||
|  |         self.board[2] = sudoku.cloneBoard(self.history[#self.history]) | ||||||
|  |         self.board[3] = sudoku.cloneBoard(self.board[2]) | ||||||
|  | 
 | ||||||
|  |         -- self.board[2] = sudoku.cloneBoard(self.history[#self.history]) | ||||||
|  |         -- self.history[#self.history] = nil | ||||||
|  | 
 | ||||||
|  |         self:checkBoard(true) | ||||||
|  |         print"-------------------------------------------" | ||||||
|  |         showHistory(self) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function applyAllSingles(self) | ||||||
|  |     sudoku.applyFillSinglesRepeatedly(self.board[2]) | ||||||
|  |     self.board[3] = sudoku.cloneBoard(self.board[2]) | ||||||
|  |     self:checkBoard() | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function showValidOptionsForCurrentCell(self, x, y) | ||||||
|  |     local s = sudoku.calCellValidOptions(self.board[2], y, x) | ||||||
|  |     for num = 1, 9 do | ||||||
|  |         self.smallNumbers[x][y][num].enabled = false | ||||||
|  |     end | ||||||
|  |     for _, num in ipairs(s) do | ||||||
|  |         self.smallNumbers[x][y][num].enabled = true | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function showValidOptionsForAllCells(self) | ||||||
|  |     for x = 1, 9 do | ||||||
|  |         for y = 1, 9 do | ||||||
|  |             showValidOptionsForCurrentCell(self, x, y) | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| local function selectSmallNumbersFont(cellSize) | local function selectSmallNumbersFont(cellSize) | ||||||
|     local fntSize = 65 |     local fntSize = 65 | ||||||
|     local margin = 0 |     local margin = 0 | ||||||
| @ -187,9 +229,11 @@ end | |||||||
| function SudokuCanvas:setBoard(board, board2) | function SudokuCanvas:setBoard(board, board2) | ||||||
|     local board2 = board2 or board |     local board2 = board2 or board | ||||||
|     self.board = {} |     self.board = {} | ||||||
|     self.board[1] = cloneBoard(board) |     self.board[1] = sudoku.cloneBoard(board) | ||||||
|     self.board[2] = cloneBoard(board2) |     self.board[2] = sudoku.cloneBoard(board2) | ||||||
|     self.board[3] = cloneBoard(board2) |     self.board[3] = sudoku.cloneBoard(board2) | ||||||
|  |     -- self.board[4] = createEmptyBoard() | ||||||
|  |     self:checkBoard() | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function SudokuCanvas:new(x, y, size, options) | function SudokuCanvas:new(x, y, size, options) | ||||||
| @ -208,6 +252,7 @@ function SudokuCanvas:new(x, y, size, options) | |||||||
|         colors = options.colors, |         colors = options.colors, | ||||||
|         enabled = true, |         enabled = true, | ||||||
|         focused = true, |         focused = true, | ||||||
|  |         history = {}, | ||||||
|     } |     } | ||||||
|     o.grid = buildGrid(x, y, cellSize) |     o.grid = buildGrid(x, y, cellSize) | ||||||
|     o.smallNumbers = calSmallNumbersCoordinates(o.grid) |     o.smallNumbers = calSmallNumbersCoordinates(o.grid) | ||||||
| @ -225,6 +270,16 @@ end | |||||||
| function SudokuCanvas:focus() | function SudokuCanvas:focus() | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | function SudokuCanvas:checkBoard(hist) | ||||||
|  |     if not hist then self:pushHistory() end | ||||||
|  |     local ok, isComplete, conflictList = sudoku.checkBoard(self.board[2]) | ||||||
|  |     self.board[4] = sudoku.createEmptyBoard() | ||||||
|  |     for _, c in ipairs(conflictList) do | ||||||
|  |         self.board[4][c.x1][c.y1] = 1 | ||||||
|  |         self.board[4][c.x2][c.y2] = 1 | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| function SudokuCanvas:draw() | function SudokuCanvas:draw() | ||||||
|     local grid = self.grid |     local grid = self.grid | ||||||
| 
 | 
 | ||||||
| @ -270,14 +325,22 @@ function SudokuCanvas:draw() | |||||||
|                 local px = self.bigNumbers[x][y][num].typed.x |                 local px = self.bigNumbers[x][y][num].typed.x | ||||||
|                 local py = self.bigNumbers[x][y][num].typed.y |                 local py = self.bigNumbers[x][y][num].typed.y | ||||||
|                 love.graphics.setFont(self.bigNumbers.typedFont) |                 love.graphics.setFont(self.bigNumbers.typedFont) | ||||||
|  |                 if self.board[4][y][x] ~= 0 then | ||||||
|  |                     uiUtils.setColor(self.colors.bigNumbersError) | ||||||
|  |                 else | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersTyped) |                     uiUtils.setColor(self.colors.bigNumbersTyped) | ||||||
|  |                 end | ||||||
|                 love.graphics.print(tostring(num), px, py) |                 love.graphics.print(tostring(num), px, py) | ||||||
|             elseif self.board[2][y][x] ~= 0 then |             elseif self.board[2][y][x] ~= 0 then | ||||||
|                 local num = self.board[2][y][x] |                 local num = self.board[2][y][x] | ||||||
|                 local px = self.bigNumbers[x][y][num].handWritten.x |                 local px = self.bigNumbers[x][y][num].handWritten.x | ||||||
|                 local py = self.bigNumbers[x][y][num].handWritten.y |                 local py = self.bigNumbers[x][y][num].handWritten.y | ||||||
|                 love.graphics.setFont(self.bigNumbers.handWrittenFont) |                 love.graphics.setFont(self.bigNumbers.handWrittenFont) | ||||||
|  |                 if self.board[4][y][x] ~= 0 then | ||||||
|  |                     uiUtils.setColor(self.colors.bigNumbersError) | ||||||
|  |                 else | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersHandWritten) |                     uiUtils.setColor(self.colors.bigNumbersHandWritten) | ||||||
|  |                 end | ||||||
|                 love.graphics.print(tostring(num), px, py) |                 love.graphics.print(tostring(num), px, py) | ||||||
|             end |             end | ||||||
|         end |         end | ||||||
| @ -315,17 +378,25 @@ function SudokuCanvas:keypressed(key) | |||||||
|         local num = key:byte() - 48 |         local num = key:byte() - 48 | ||||||
|         if self.board[1][y][x] == 0 then |         if self.board[1][y][x] == 0 then | ||||||
|             if mode == "big" then |             if mode == "big" then | ||||||
|  |                 if self.board[2][y][x] == num then | ||||||
|  |                     self.board[2][y][x] = 0 | ||||||
|  |                     self.board[3][y][x] = 0 | ||||||
|  |                 else | ||||||
|                     self.board[2][y][x] = num |                     self.board[2][y][x] = num | ||||||
|                     self.board[3][y][x] = num |                     self.board[3][y][x] = num | ||||||
|  |                 end | ||||||
|  |                 -- self:checkBoard() | ||||||
|             else |             else | ||||||
|                 self.smallNumbers[x][y][num].enabled = not self.smallNumbers[x][y][num].enabled |                 self.smallNumbers[x][y][num].enabled = not self.smallNumbers[x][y][num].enabled | ||||||
|             end |             end | ||||||
|  |             self:checkBoard() | ||||||
|         end |         end | ||||||
|     elseif key == "delete" or key == "0" then |     elseif key == "delete" or key == "0" then | ||||||
|         if self.board[1][y][x] == 0 then |         if self.board[1][y][x] == 0 then | ||||||
|             if mode == "big" then |             if mode == "big" then | ||||||
|                 self.board[2][y][x] = 0 |                 self.board[2][y][x] = 0 | ||||||
|                 self.board[3][y][x] = 0 |                 self.board[3][y][x] = 0 | ||||||
|  |                 self:checkBoard() | ||||||
|             else |             else | ||||||
|                 for num = 1, 9 do |                 for num = 1, 9 do | ||||||
|                     self.smallNumbers[x][y][num].enabled = false |                     self.smallNumbers[x][y][num].enabled = false | ||||||
| @ -353,6 +424,18 @@ function SudokuCanvas:keypressed(key) | |||||||
|             self.board[2][y][x] = self.board[3][y][x] |             self.board[2][y][x] = self.board[3][y][x] | ||||||
|             mode = "big" |             mode = "big" | ||||||
|         end |         end | ||||||
|  |     elseif key == "s" then | ||||||
|  |         -- showValidOptionsForCurrentCell(self, x, y) | ||||||
|  |         showValidOptionsForAllCells(self) | ||||||
|  |     elseif key == "a" then | ||||||
|  |         applyAllSingles(self) | ||||||
|  |     elseif key == "u" then | ||||||
|  |         undo(self) | ||||||
|  |     elseif key == "f" then | ||||||
|  |         sudoku.saveBoard("lastBoard.txt", self.board[1], self.board[2]) | ||||||
|  |     elseif key == "c" then | ||||||
|  |         self.board[2] = sudoku.solve(self.board[1]) | ||||||
|  |         self:checkBoard() | ||||||
|     end |     end | ||||||
|     self.cursor.x = x |     self.cursor.x = x | ||||||
|     self.cursor.y = y |     self.cursor.y = y | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user