22import numpy as np
33from typing import List , Any , Union , Tuple , Dict
44
5-
65"""
76 Sudoku Puzzle Demo
8-
7+
98 How to easily generate a GUI for a Sudoku puzzle.
109 The Window definition and creation is a single line of code.
11-
10+
1211 Code to generate a playable puzzle was supplied from:
1312 https://github.com/MorvanZhou/sudoku
14-
13+
1514 Copyright 2020 PySimpleGUI.com
16-
15+
1716"""
1817
1918
@@ -27,7 +26,7 @@ def generate_sudoku(mask_rate):
2726 """
2827 while True :
2928 n = 9
30- solution = np .zeros ((n , n ), np .int )
29+ solution = np .zeros ((n , n ), np .int_ )
3130 rg = np .arange (1 , n + 1 )
3231 solution [0 , :] = np .random .choice (rg , n , replace = False )
3332 try :
@@ -36,10 +35,11 @@ def generate_sudoku(mask_rate):
3635 col_rest = np .setdiff1d (rg , solution [:r , c ])
3736 row_rest = np .setdiff1d (rg , solution [r , :c ])
3837 avb1 = np .intersect1d (col_rest , row_rest )
39- sub_r , sub_c = r // 3 , c // 3
40- avb2 = np .setdiff1d (np .arange (0 , n + 1 ), solution [sub_r * 3 :(sub_r + 1 ) * 3 , sub_c * 3 :(sub_c + 1 ) * 3 ].ravel ())
38+ sub_r , sub_c = r // 3 , c // 3
39+ avb2 = np .setdiff1d (np .arange (0 , n + 1 ), solution [sub_r * 3 :(sub_r + 1 ) * 3 , sub_c * 3 :(sub_c + 1 ) * 3 ].ravel ())
4140 avb = np .intersect1d (avb1 , avb2 )
42- solution [r , c ] = np .random .choice (avb , size = 1 )
41+ # solution[r, c] = np.random.choice(avb, size=1)
42+ solution [r , c ] = np .random .choice (avb , size = 1 )[0 ]
4343 break
4444 except ValueError :
4545 pass
@@ -48,7 +48,6 @@ def generate_sudoku(mask_rate):
4848 return puzzle , solution
4949
5050
51-
5251def check_progress (window , solution ):
5352 """
5453 Gives you a visual hint on your progress.
@@ -65,38 +64,23 @@ def check_progress(window, solution):
6564 solved = True
6665 for r , row in enumerate (solution ):
6766 for c , col in enumerate (row ):
68- value = window [r ,c ].get ()
67+ value = window [r , c ].get ()
6968 if value :
7069 try :
7170 value = int (value )
7271 except :
7372 value = 0
7473 if value != solution [r ][c ]:
75- window [r ,c ].update (background_color = 'red' )
74+ window [r , c ].update (background_color = 'red' )
7675 solved = False
7776 else :
78- window [r ,c ].update (background_color = sg .theme_input_background_color ())
77+ window [r , c ].update (background_color = sg .theme_input_background_color ())
7978 else :
8079 solved = False
8180 window [r , c ].update (background_color = 'yellow' )
8281 return solved
8382
8483
85- def create_and_show_puzzle (window ):
86- # create and display a puzzle by updating the Input elements
87- rate = DEFAULT_MASK_RATE
88- if window ['-RATE-' ].get ():
89- try :
90- rate = float (window ['-RATE-' ].get ())
91- except :
92- pass
93- puzzle , solution = generate_sudoku (mask_rate = rate )
94- for r , row in enumerate (puzzle ):
95- for c , col in enumerate (row ):
96- window [r , c ].update (puzzle [r ][c ] if puzzle [r ][c ] else '' , background_color = sg .theme_input_background_color ())
97- return puzzle , solution
98-
99-
10084def main (mask_rate = 0.7 ):
10185 """"
10286 The Main GUI - It does it all.
@@ -105,33 +89,45 @@ def main(mask_rate=0.7):
10589 addressing of the individual squares is via a key that's a tuple (0,0) to (8,8)
10690 """
10791
108-
109-
92+ def create_and_show_puzzle ():
93+ # create and display a puzzle by updating the Input elements
94+ rate = mask_rate
95+ if window ['-RATE-' ].get ():
96+ try :
97+ rate = float (window ['-RATE-' ].get ())
98+ except :
99+ pass
100+ puzzle , solution = generate_sudoku (mask_rate = rate )
101+ for r , row in enumerate (puzzle ):
102+ for c , col in enumerate (row ):
103+ window [r , c ].update (puzzle [r ][c ] if puzzle [r ][c ] else '' , background_color = sg .theme_input_background_color ())
104+ return puzzle , solution
110105
111106 # It's 1 line of code to make a Sudoku board. If you don't like it, then replace it.
112107 # Dude (Dudette), it's 1-line of code. If you don't like the board, write a line of code.
113108 # The keys for the inputs are tuples (0-8, 0-8) that reference each Input Element.
114109 # Get an input element for a position using: window[row, col]
115110 # To get a better understanding, take it apart. Spread it out. You'll learn in the process.
116111 window = sg .Window ('Sudoku' ,
117- [[sg .Frame ('' , [[sg .I (random .randint (1 ,9 ), justification = 'r' , size = (3 ,1 ),enable_events = True , key = (fr * 3 + r ,fc * 3 + c )) for c in range (3 )] for r in range (3 )]) for fc in range (3 )] for fr in range (3 )] +
118- [[sg .B ('Solve' ), sg .B ('Check' ), sg .B ('Hint' ), sg .B ('New Game' ), sg .T ('Mask rate (0-1)' ), sg .In (str (mask_rate ), size = (3 ,1 ),key = '-RATE-' )],], finalize = True )
112+ [[sg .Frame ('' , [[sg .I (random .randint (1 , 9 ), justification = 'r' , size = (3 , 1 ), key = (fr * 3 + r , fc * 3 + c )) for c in range (3 )] for r in range (3 )]) for fc in
113+ range (3 )] for fr in range (3 )] +
114+ [[sg .B ('Solve' ), sg .B ('Check' ), sg .B ('Hint' ), sg .B ('New Game' )], [sg .T ('Mask rate (0-1)' ), sg .In (str (mask_rate ), size = (3 , 1 ), key = '-RATE-' )], ],
115+ finalize = True )
119116
120117 # create and display a puzzle by updating the Input elements
121118
122- puzzle , solution = create_and_show_puzzle (window )
123- check_showing = False
124- while True : # The Event Loop
119+ puzzle , solution = create_and_show_puzzle ()
120+
121+ while True : # The Event Loop
125122 event , values = window .read ()
126- if event == sg . WIN_CLOSED :
123+ if event is None :
127124 break
128125
129126 if event == 'Solve' :
130127 for r , row in enumerate (solution ):
131128 for c , col in enumerate (row ):
132129 window [r , c ].update (solution [r ][c ], background_color = sg .theme_input_background_color ())
133130 elif event == 'Check' :
134- check_showing = True
135131 solved = check_progress (window , solution )
136132 if solved :
137133 sg .popup ('Solved! You have solved the puzzle correctly.' )
@@ -140,17 +136,14 @@ def main(mask_rate=0.7):
140136 try :
141137 elem .update (solution [elem .Key [0 ]][elem .Key [1 ]], background_color = sg .theme_input_background_color ())
142138 except :
143- pass # Likely because an input element didn't have focus
139+ pass # Likely because an input element didn't have focus
144140 elif event == 'New Game' :
145- puzzle , solution = create_and_show_puzzle (window )
146- elif check_showing : # an input was changed, so clear any background colors from prior hints
147- check_showing = False
148- for r , row in enumerate (solution ):
149- for c , col in enumerate (row ):
150- window [r , c ].update (background_color = sg .theme_input_background_color ())
141+ puzzle , solution = create_and_show_puzzle ()
142+
151143 window .close ()
152144
145+
153146if __name__ == "__main__" :
154- DEFAULT_MASK_RATE = 0.7 # % Of cells to hide
155- main (DEFAULT_MASK_RATE )
147+ mask_rate = 0.7 # % Of cells to hide
148+ main (mask_rate )
156149
0 commit comments