Compare commits
	
		
			No commits in common. "1bb8bdc6b05f761b5e44c212bae8ba634b4806e1" and "231612cce47c941f3a68b8ad046caed88948de25" have entirely different histories.
		
	
	
		
			1bb8bdc6b0
			...
			231612cce4
		
	
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -1,16 +0,0 @@ | |||||||
| # 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,13 +7,3 @@ | |||||||
| 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 |  | ||||||
|  | |||||||
| @ -1,9 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| 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/057.txt", |         filePath = "boards/040.txt", | ||||||
|     }, |     }, | ||||||
|     window = { |     window = { | ||||||
|         bgColor = "FFFFFF", |         bgColor = "FFFFFF", | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								main.lua
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								main.lua
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| sudoku = require "sudoku.sudoku" | require "sudoku.utils" | ||||||
| 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()) | ||||||
|     board = sudoku.loadBoard(config.board.filePath) |     local board = loadBoard(config.board.filePath) | ||||||
|     local width, height = love.graphics.getDimensions() |     local width, height = love.graphics.getDimensions() | ||||||
|     sudokuCanvas = SudokuCanvas:new(500, 50, height/1.1, config.SudokuCanvas) |     sudokuCanvas = SudokuCanvas:new(200, 100, height/1.5, config.SudokuCanvas) | ||||||
|     sudokuCanvas:setBoard(board[1]) |     sudokuCanvas:setBoard(board) | ||||||
|     myFont = love.graphics.newFont(24) |     myFont = love.graphics.newFont(24) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,132 @@ | |||||||
|  | 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,510 +1,47 @@ | |||||||
| -- dbg = require ("debugger") | require "sudoku.utils" | ||||||
| -- dbg.auto_where = 2 | require "sudoku.check" | ||||||
| 
 | 
 | ||||||
| function table2string(t) | function calValidOptions(b, x, y) | ||||||
|     local myself = table2string |     if b[x][y] ~= 0 then return {} end | ||||||
|     local l = {} |     local elm | ||||||
|     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 | ||||||
|         if board[x][i] ~= 0 then table.insert(u, board[x][i]) end |         elm = b[x][i] | ||||||
|         if board[i][y] ~= 0 then table.insert(u, board[i][y]) end |         if elm ~= 0 and find(u, elm) == 0 then | ||||||
|  |             table.insert(u, elm) | ||||||
|  |         end | ||||||
|  |         elm = b[i][y] | ||||||
|  |         if elm ~= 0 and find(u, elm) == 0 then | ||||||
|  |             table.insert(u, elm) | ||||||
|  |         end | ||||||
|     end |     end | ||||||
|     local dx = math.floor((x - 1) / 3) * 3 |     -- local xc = ((x - 1) // 3) * 3 | ||||||
|     local dy = math.floor((y - 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 | ||||||
|             local a = board[i+dx][j+dy] |             elm = b[i+xc][j+yc] | ||||||
|             if a ~= 0 then table.insert(u, a) end |             if elm ~= 0 and find(u, elm) == 0 then | ||||||
|  |                 table.insert(u, elm) | ||||||
|  |             end | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|     for i = 1, 9 do |     for i = 1, 9 do | ||||||
|         local found = false |         if find(u, i) == 0 then table.insert(v, i) end | ||||||
|         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(board) | function buildSearchSpace(b) | ||||||
|     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] = calCellValidOptions(board, i, j) |             s[i][j] = calValidOptions(b, 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, |  | ||||||
| } |  | ||||||
|  | |||||||
							
								
								
									
										49
									
								
								sudoku/utils.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								sudoku/utils.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | 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,65 +1,23 @@ | |||||||
| SudokuCanvas = {} | function table2string(t) | ||||||
| SudokuCanvas.__index = SudokuCanvas |     local myself = table2string | ||||||
| 
 |     local l = {} | ||||||
| function SudokuCanvas:pushHistory() |     local n = 0 | ||||||
|     if #self.history <= 1 then |     for k, v in pairs(t) do | ||||||
|         table.insert(self.history, sudoku.cloneBoard(self.board[2])) |         n = n + 1 | ||||||
|         -- showHistory(self) |         if type(v) == "table" then | ||||||
|         -- print("pushHistory: ", #self.history) |             l[n] = k .. ': ' .. myself(v) | ||||||
|     elseif not sudoku.checkBoardsEqual(self.board[2], self.history[#self.history]) then |         elseif type(v) == "string" then | ||||||
|         table.insert(self.history, sudoku.cloneBoard(self.board[2])) |             l[n] = k .. ': ' .. '"' .. v .. '"' | ||||||
|         -- showHistory(self) |         else | ||||||
|         -- print("pushHistory: ", #self.history) |             l[n] = k .. ': ' .. v | ||||||
|     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 |     end | ||||||
|  |     return "{" .. table.concat(l, ", ") .. "}" | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | SudokuCanvas = {} | ||||||
|  | SudokuCanvas.__index = SudokuCanvas | ||||||
|  | 
 | ||||||
| local function selectSmallNumbersFont(cellSize) | local function selectSmallNumbersFont(cellSize) | ||||||
|     local fntSize = 65 |     local fntSize = 65 | ||||||
|     local margin = 0 |     local margin = 0 | ||||||
| @ -229,11 +187,9 @@ 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] = sudoku.cloneBoard(board) |     self.board[1] = cloneBoard(board) | ||||||
|     self.board[2] = sudoku.cloneBoard(board2) |     self.board[2] = cloneBoard(board2) | ||||||
|     self.board[3] = sudoku.cloneBoard(board2) |     self.board[3] = cloneBoard(board2) | ||||||
|     -- self.board[4] = createEmptyBoard() |  | ||||||
|     self:checkBoard() |  | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function SudokuCanvas:new(x, y, size, options) | function SudokuCanvas:new(x, y, size, options) | ||||||
| @ -252,7 +208,6 @@ 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) | ||||||
| @ -270,16 +225,6 @@ 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 | ||||||
| 
 | 
 | ||||||
| @ -325,22 +270,14 @@ 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.bigNumbersTyped) | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersError) |  | ||||||
|                 else |  | ||||||
|                     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.bigNumbersHandWritten) | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersError) |  | ||||||
|                 else |  | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersHandWritten) |  | ||||||
|                 end |  | ||||||
|                 love.graphics.print(tostring(num), px, py) |                 love.graphics.print(tostring(num), px, py) | ||||||
|             end |             end | ||||||
|         end |         end | ||||||
| @ -378,25 +315,17 @@ 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] = num | ||||||
|                     self.board[2][y][x] = 0 |                 self.board[3][y][x] = num | ||||||
|                     self.board[3][y][x] = 0 |  | ||||||
|                 else |  | ||||||
|                     self.board[2][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 | ||||||
| @ -424,18 +353,6 @@ 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