Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7a8c111

Browse files
Merge pull request avinashkranjan#1805 from smty2018/master
[GSSOC'23]Sudoku Game
2 parents d8a3794 + 08b43dc commit 7a8c111

File tree

2 files changed

+244
-0
lines changed

2 files changed

+244
-0
lines changed

‎Sudoku_Game/READ_ME.md‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Sudoku Game
2+
The Sudoku game in Python.
3+
4+
Rules of the Game
5+
Sudoku is a number placement puzzle game that is played on a 9x9 grid. The goal of the game is to fill in the empty cells of the grid with numbers from 1 to 9, such that each column, each row, and each of the nine 3x3 sub-grids (also called "boxes" or "regions") contains all of the numbers from 1 to 9 without repetition.
6+
7+
The rules of Sudoku are as follows:
8+
9+
Each row must contain all numbers from 1 to 9 without repetition.
10+
Each column must contain all numbers from 1 to 9 without repetition.
11+
Each 3x3 sub-grid (box) must contain all numbers from 1 to 9 without repetition.
12+
The puzzle initially provides some numbers (called "givens") as clues. These numbers cannot be changed.
13+
The player's task is to fill in the remaining empty cells with numbers from 1 to 9, following the rules above.
14+
15+
Opening the game:
16+
Clone the repository or download the sudoku.py file.
17+
Open the file in a Python environment (e.g., IDLE, Jupyter Notebook, or any text editor with Python support).
18+
Run the script to start the game.
19+
20+
Requirements:
21+
import tkinter as tk
22+
from tkinter import messagebox,simpledialog
23+
import random
24+
25+
26+
Instructions to Play
27+
1. Run the game.Maximize the window.
28+
2. Select the level ("Easy","Medium","Hard") from the select level drop down. The grid will appear
29+
3. Select the cell you want to input. ("Input from 1-9")
30+
4. Finish Solving the puzzle and check your answer.
31+
5. Stuck at a particular stage? Use Solve button to view the solution
32+
6. You can use the new game button to create a new puzzle.
33+
34+
Screenshots:![Screenshot 2023年06月14日 151023](https://github.com/smty2018/Amazing-Python-Scripts/assets/74114936/ba3f4aa4-277f-4458-acb3-c148d57dd5f9)
35+
![Screenshot 2023年06月14日 151045](https://github.com/smty2018/Amazing-Python-Scripts/assets/74114936/ed63d309-1292-421c-8c84-02d1f9ea7ab8)
36+
![Screenshot 2023年06月14日 171242](https://github.com/smty2018/Amazing-Python-Scripts/assets/74114936/b66a8f2f-c0b7-4916-a11d-eb4783cf7813)

‎Sudoku_Game/sudoku.py‎

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import tkinter as tk
2+
from tkinter import messagebox,simpledialog
3+
import random
4+
5+
6+
class Sudoku:
7+
def __init__(self, master):
8+
self.master = master
9+
self.board = [[0] * 9 for _ in range(9)]
10+
self.solution = [[num for num in row] for row in self.board]
11+
self.empty_cells = self.get_empty_cells(self.board)
12+
self.create_widgets()
13+
14+
def create_widgets(self):
15+
self.master.configure(bg='#ECECEC')
16+
self.canvas = tk.Canvas(self.master, width=680, height=680, bg='#F8C8DC', highlightthickness=0)
17+
self.canvas.pack(side=tk.TOP, padx=0, pady=0)
18+
19+
self.draw_board()
20+
21+
self.button_frame = tk.Frame(self.master, bg='#ECECEC')
22+
self.button_frame.pack(side=tk.TOP, pady=20)
23+
24+
self.check_button = tk.Button(self.button_frame, text='Check', font=('Inter', 12, 'bold'),
25+
bg='#E75442', fg='#FFFFFF', bd=0, command=self.check_solution)
26+
self.check_button.pack(side=tk.LEFT, padx=10)
27+
28+
self.solve_button = tk.Button(self.button_frame, text='Solve', font=('Inter', 12, 'bold'),
29+
bg='#3AC6FF', fg='#FFFFFF', bd=0, command=self.solve_puzzle)
30+
self.solve_button.pack(side=tk.LEFT, padx=10)
31+
32+
self.level_frame = tk.Frame(self.master, bg='#ECECEC')
33+
self.level_frame.pack(side=tk.TOP, pady=0)
34+
35+
self.level_label = tk.Label(self.level_frame, text='Select Level:', font=('Inter', 12,"bold"), bg='#77DD77', fg='#ECECEC')
36+
self.level_label.pack(side=tk.LEFT, padx=10)
37+
38+
self.level_var = tk.StringVar()
39+
self.level_var.set('Easy')
40+
self.level_dropdown = tk.OptionMenu(self.level_frame, self.level_var, 'Easy', 'Medium', 'Hard',
41+
command=self.new_game)
42+
self.level_dropdown.config(font=('Arial', 12,"bold"), bg='#ffb347', fg='#ECECEC', bd=0)
43+
self.level_dropdown.pack(side=tk.LEFT, padx=10)
44+
45+
self.new_game_button = tk.Button(self.level_frame, text='New Game', font=('Inter', 12, 'bold'),
46+
bg='#FFD700', fg='#ECECEC', bd=0, command=self.new_game_wrapper)
47+
self.new_game_button.pack(side=tk.LEFT, padx=10)
48+
self.canvas.bind("<Button-1>", self.on_cell_click)
49+
50+
51+
def new_game_wrapper(self):
52+
level = self.level_var.get()
53+
self.new_game(level)
54+
55+
def new_game(self, level):
56+
if level == 'Easy':
57+
num_cells = 40
58+
elif level == 'Medium':
59+
num_cells = 50
60+
elif level == 'Hard':
61+
num_cells = 60
62+
63+
self.board = [[0] * 9 for _ in range(9)]
64+
self.generate_puzzle()
65+
self.remove_cells(num_cells)
66+
self.empty_cells = self.get_empty_cells(self.board)
67+
self.draw_board()
68+
69+
def generate_puzzle(self):
70+
self.solve_board(self.board)
71+
for _ in range(81):
72+
row = random.randint(0, 8)
73+
col = random.randint(0, 8)
74+
temp = self.board[row][col]
75+
self.board[row][col] = 0
76+
count = 0
77+
solution_copy = [row[:] for row in self.board]
78+
self.solve_board(solution_copy)
79+
for i in range(9):
80+
if 0 in solution_copy[i]:
81+
count += 1
82+
if count != 1:
83+
self.board[row][col] = temp
84+
85+
def solve_board(self, board):
86+
empty_cell = self.get_empty_cell(board)
87+
if not empty_cell:
88+
return True
89+
90+
row, col = empty_cell
91+
for num in range(1, 10):
92+
if self.is_valid_move(board, row, col, num):
93+
board[row][col] = num
94+
if self.solve_board(board):
95+
return True
96+
board[row][col] = 0
97+
return False
98+
99+
def on_cell_click(self, event):
100+
x, y = event.x, event.y
101+
row, col = (y - 80) // 60, (x - 80) // 60
102+
if self.board[row][col] != 0:
103+
messagebox.showinfo('Invalid Move', 'Cannot change pre-filled cells!')
104+
return
105+
num = tk.simpledialog.askinteger('Input', 'Enter a number (1-9):', minvalue=1, maxvalue=9)
106+
if num:
107+
self.board[row][col] = num
108+
self.draw_board()
109+
110+
111+
def get_empty_cell(self, board):
112+
for i in range(9):
113+
for j in range(9):
114+
if board[i][j] == 0:
115+
return i, j
116+
return None
117+
118+
def is_valid_move(self, board, row, col, num):
119+
return (
120+
self.is_valid_row(board, row, num)
121+
and self.is_valid_col(board, col, num)
122+
and self.is_valid_box(board, row - row % 3, col - col % 3, num)
123+
)
124+
125+
def is_valid_row(self, board, row, num):
126+
for i in range(9):
127+
if board[row][i] == num:
128+
return False
129+
return True
130+
131+
def is_valid_col(self, board, col, num):
132+
for i in range(9):
133+
if board[i][col] == num:
134+
return False
135+
return True
136+
137+
def is_valid_box(self, board, start_row, start_col, num):
138+
for i in range(3):
139+
for j in range(3):
140+
if board[start_row + i][start_col + j] == num:
141+
return False
142+
return True
143+
144+
def draw_board(self):
145+
self.clear_board()
146+
for i in range(9):
147+
for j in range(9):
148+
x = i * 60 + 80
149+
y = j * 60 + 80
150+
cell_value = self.board[j][i]
151+
if cell_value != 0:
152+
# Adjust the coordinates to avoid intersection
153+
text_x = x + 15
154+
text_y = y + 15
155+
self.canvas.create_text(text_x, text_y, text=str(cell_value), font=('Inter', 20, 'bold'), fill='#333333')
156+
157+
self.draw_grid()
158+
159+
def draw_grid(self):
160+
for i in range(10):
161+
if i % 3 == 0:
162+
line_width = 2
163+
else:
164+
line_width = 1
165+
self.canvas.create_line(60 * i + 80, 80, 60 * i + 80, 620, width=line_width, fill='#333333')
166+
self.canvas.create_line(80, 60 * i + 80, 620, 60 * i + 80, width=line_width, fill='#333333')
167+
168+
def clear_board(self):
169+
self.canvas.delete('all')
170+
171+
def check_solution(self):
172+
for i in range(9):
173+
for j in range(9):
174+
if self.board[i][j] != self.solution[i][j]:
175+
messagebox.showinfo('Incorrect', 'The solution is not correct!')
176+
return
177+
messagebox.showinfo('Correct', 'Congratulations! You solved the puzzle!')
178+
179+
def remove_cells(self, num_cells):
180+
cells = [(i, j) for i in range(9) for j in range(9)]
181+
random.shuffle(cells)
182+
for i in range(num_cells):
183+
row, col = cells[i]
184+
self.board[row][col] = 0
185+
186+
def get_empty_cells(self, board):
187+
empty_cells = []
188+
for i in range(9):
189+
for j in range(9):
190+
if board[i][j] == 0:
191+
empty_cells.append((i, j))
192+
return empty_cells
193+
194+
def solve_puzzle(self):
195+
solution_board = [row[:] for row in self.board]
196+
if self.solve_board(solution_board):
197+
self.solution = solution_board
198+
self.board = solution_board
199+
self.draw_board()
200+
else:
201+
messagebox.showinfo('Unsolvable', 'The puzzle does not have a solution.')
202+
203+
204+
if __name__ == '__main__':
205+
root = tk.Tk()
206+
root.title('Sudoku')
207+
gui = Sudoku(root)
208+
root.mainloop()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /