-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmart_dot.py
More file actions
148 lines (124 loc) · 6.3 KB
/
smart_dot.py
File metadata and controls
148 lines (124 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import tkinter as tk
import random
class SmartDotGameBacktracking:
def __init__(self, root, grid_size=5, num_dots=8):
self.root = root
self.grid_size = grid_size
self.num_dots = num_dots
self.grid = [[0] * grid_size for _ in range(grid_size)]
self.row_clues = [0] * grid_size
self.col_clues = [0] * grid_size
self.solution = None
self.message_label = None # Label to show win/lose messages
self.generate_puzzle()
self.create_grid()
def generate_puzzle(self):
def is_valid(r, c):
# Check if placing a dot here exceeds the row or column clues
if self.row_clues[r] >= self.grid_size or self.col_clues[c] >= self.grid_size:
return False
return True
def solve(cells, dots_left):
if dots_left == 0:
return True # All dots placed
if not cells:
return False # No more cells to consider
# Choose the next cell to try
r, c = cells.pop()
# Try placing a dot
if is_valid(r, c):
self.grid[r][c] = 1
self.row_clues[r] += 1
self.col_clues[c] += 1
if solve(cells[:], dots_left - 1): # Pass a copy of the remaining cells
return True
# Backtrack
self.grid[r][c] = 0
self.row_clues[r] -= 1
self.col_clues[c] -= 1
# Try without placing a dot
return solve(cells[:], dots_left)
# Create a list of all cells in the grid and shuffle them
cells = [(r, c) for r in range(self.grid_size) for c in range(self.grid_size)]
random.shuffle(cells) # Randomize cell order
solve(cells, self.num_dots)
self.solution = [(r, c) for r in range(self.grid_size) for c in range(self.grid_size) if self.grid[r][c] == 1]
def create_grid(self):
# Add row clues with styling
for row in range(self.grid_size):
clue_label = tk.Label(self.root, text=str(self.row_clues[row]), font=("Arial", 14, "bold"), fg="darkblue")
clue_label.grid(row=row + 1, column=0, padx=5, pady=5)
# Add column clues with styling
for col in range(self.grid_size):
clue_label = tk.Label(self.root, text=str(self.col_clues[col]), font=("Arial", 14, "bold"), fg="darkblue")
clue_label.grid(row=0, column=col + 1, padx=5, pady=5)
# Add grid buttons with styling
self.grid_buttons = {}
for row in range(self.grid_size):
for col in range(self.grid_size):
button = tk.Button(
self.root, width=4, height=2, bg="lightgray", relief="raised",
command=lambda r=row, c=col: self.check_cell(r, c),
font=("Arial", 12, "bold")
)
button.grid(row=row + 1, column=col + 1, padx=2, pady=2)
self.grid_buttons[(row, col)] = button
# Add "Show Solution" button with styling
show_solution_button = tk.Button(self.root, text="Show Solution", command=self.display_solution, font=("Arial", 12, "bold"), bg="orange", fg="white")
show_solution_button.grid(row=self.grid_size + 1, column=0, columnspan=self.grid_size // 2, pady=10)
# Add "Reset" button with styling
reset_button = tk.Button(self.root, text="Reset", command=self.reset_game, font=("Arial", 12, "bold"), bg="green", fg="white")
reset_button.grid(row=self.grid_size + 1, column=self.grid_size // 2, columnspan=self.grid_size // 2, pady=10)
def check_cell(self, row, col):
# Check if the clicked cell contains a hidden dot
if (row, col) in self.solution:
self.grid_buttons[(row, col)].config(text="●", bg="green", fg="white", state="disabled")
self.solution.remove((row, col))
else:
# If wrong cell is clicked, display "You Lose" and disable all buttons
self.grid_buttons[(row, col)].config(text="X", bg="red", fg="white", state="disabled")
self.display_lose_message()
self.disable_all_buttons()
return
# Check for win condition
if not self.solution:
self.display_win_message()
def display_solution(self):
# Reveal all dots in the solution
for (row, col) in self.solution:
self.grid_buttons[(row, col)].config(text="●", bg="blue", fg="white", state="disabled")
def clear_messages(self):
# Clear any existing win/lose message
if self.message_label:
self.message_label.destroy()
self.message_label = None
def display_win_message(self):
self.clear_messages() # Clear any existing message
self.message_label = tk.Label(self.root, text="You Win!", font=("Arial", 20, "bold"), fg="blue")
self.message_label.grid(row=self.grid_size + 2, column=0, columnspan=self.grid_size, pady=10)
def display_lose_message(self):
self.clear_messages() # Clear any existing message
self.message_label = tk.Label(self.root, text="You Lose!", font=("Arial", 20, "bold"), fg="red")
self.message_label.grid(row=self.grid_size + 2, column=0, columnspan=self.grid_size, pady=10)
def disable_all_buttons(self):
# Disable all buttons on the grid
for button in self.grid_buttons.values():
button.config(state="disabled")
def reset_game(self):
# Clear existing win/lose message and reset the game grid
self.clear_messages()
for row in range(self.grid_size):
for col in range(self.grid_size):
self.grid_buttons[(row, col)].config(text="", bg="lightgray", fg="black", state="normal")
self.row_clues = [0] * self.grid_size
self.col_clues = [0] * self.grid_size
self.grid = [[0] * self.grid_size for _ in range(self.grid_size)]
self.generate_puzzle()
self.create_grid()
# Main loop
if __name__ == "__main__":
root = tk.Tk()
root.title("Smart Dot Game with Randomized Backtracking")
root.configure(bg="lightblue")
game = SmartDotGameBacktracking(root, grid_size=5, num_dots=8)
root.mainloop()