Skip to content

Commit 6d3cf95

Browse files
committed
Visualization completed
1 parent 0fb6ec3 commit 6d3cf95

File tree

9 files changed

+230
-53
lines changed

9 files changed

+230
-53
lines changed

App.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from sudoku import *
2+
import eel
3+
4+
current_sudoku_onboard = []
5+
6+
# python functions exposed to javascript
7+
@eel.expose
8+
def generate_new_sudoku(level):
9+
global current_sudoku_onboard
10+
# generating sudoku for required level
11+
current_sudoku_onboard = Sudoku().generate_sudoku(int(level))
12+
# drawing sudoku by calling javascript function from python
13+
eel.draw_sudoku(current_sudoku_onboard)
14+
15+
16+
@eel.expose
17+
def solve_sudoku(mode):
18+
global current_sudoku_onboard
19+
# solving the sudoku (quick mode or visualize)
20+
Sudoku().solve(current_sudoku_onboard, int(mode))
21+
22+
23+
if __name__ == "__main__":
24+
# initializing eel with the dir containing HTML resources
25+
eel.init("www")
26+
27+
# starting eel server
28+
eel.start('index.html', size=(540, 660))

README.md

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
1-
# Sudoku Backtracking Visualizer
2-
3-
A simple programe to solve sudoku using backtracking algorithm and visulize the working of backtracking algorithm in real time.
1+
# Sudoku Backtracking Visualizer [![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/tarunk04/sudoku-backtracking-visualizer/blob/master/LICENSE)
2+
A sudoku game with built-in feature to visualize the solving of sudoku using backtracking algorithm.
3+
Game offer 4 difficulty levels:
4+
* Easy
5+
* Medium
6+
* Hard
7+
* Expert
8+
<br>
49

10+
**Note: Game is not playable yet although visualization can done on any level of game.**
511

12+
# Requirements
13+
* `eel` python library. Use `pip install eel` to install.
14+
* basic knowledge of HTML,CSS,JavaScript
615

16+
# Setup
17+
* Clone this repository:
18+
```console
19+
git clone https://github.com/tarunk04/sudoku-backtracking-visualizer.git
20+
```
21+
or click `Download ZIP` in right panel of repository and extract it.
22+
* Run the `App.py`.
23+
24+
# Preview
25+
![GUI](screenshots/Sudoku%20-%20Backtracking%20Algorithm%20visualizer.png)
26+
27+
# Backtracking in Action
28+
![visualizer](screenshots/visualizer.gif)
29+
30+
# Author
31+
Tarun Kumar
32+
33+
**Author's Note**
34+
35+
The author is not responsible for any misuse the program. Any commercial use of the code is not permissible however any contribution or suggestions are most welcome. Read the LICENSE carefully.
36+
# License
37+
The MIT License, see the included, see the [License](https://github.com/tarunk04/sudoku-backtracking-visualizer/blob/master/LICENSE) file.
31.1 KB
Loading

screenshots/visualizer.gif

3.31 MB
Loading

algo.py renamed to sudoku.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ def __solve_backtrack__(self, i, j, visualize=False):
4040
i += 1
4141
# end condition
4242
if i > 8:
43+
if visualize == False:
44+
eel.draw_sudoku(self.sudoku_solved)
4345
return True
4446

4547
# skipping cell if the cell has already a number
4648
if self.sudoku_solved[i][j] != 0:
47-
if self.__solve_backtrack__(i, (j + 1),visualize):
49+
if self.__solve_backtrack__(i, (j + 1), visualize):
4850
return True
4951
# solving for the cell if the cell is empty
5052
else:
@@ -59,7 +61,7 @@ def __solve_backtrack__(self, i, j, visualize=False):
5961
time.sleep(0.2)
6062
eel.update_sudoku(val, 9 * i + j)
6163
time.sleep(0.2)
62-
if self.__solve_backtrack__(i, (j + 1),visualize):
64+
if self.__solve_backtrack__(i, (j + 1), visualize):
6365
return True
6466
# it the current validated number fails reset the cell
6567
self.sudoku_solved[i][j] = 0
@@ -95,11 +97,13 @@ def __count_solutions__(self, i, j):
9597
self.__count_solutions__(i, (j + 1))
9698
# it the current validated number fails reset the cell
9799
self.sudoku_solved[i][j] = 0
100+
if self.counter > 1:
101+
return
98102

99103
def solve(self, sudoku, visualize=False):
100104
self.sudoku_matrix = copy.deepcopy(sudoku)
101105
self.sudoku_solved = copy.deepcopy(sudoku)
102-
self.__solve_backtrack__(0, 0, visualize=True)
106+
self.__solve_backtrack__(0, 0, visualize=visualize)
103107
return self.sudoku_solved
104108

105109
def solution_count(self, sudoku):
@@ -150,19 +154,20 @@ def generate_sudoku(self, level=2):
150154
# generate solved sudoku
151155
self.generate_solved_sudoku()
152156
if level == 1:
153-
remove_cell = random.randint(18, 30)
157+
remove_cell = random.randint(32, 38)
154158
if level == 2:
155-
remove_cell = random.randint(33, 44)
159+
remove_cell = random.randint(40, 46)
156160
if level == 3:
157-
remove_cell = random.randint(46, 52)
161+
remove_cell = random.randint(48, 52)
158162
if level == 4:
159-
remove_cell = random.randint(54, 57)
163+
remove_cell = random.randint(54, 56)
160164
if level == 5:
161165
remove_cell = random.randint(59, 61)
162166

163167
sudoku_board = copy.deepcopy(self.new_sudoku)
164-
168+
print(remove_cell)
165169
while remove_cell > 0:
170+
# print(remove_cell)
166171
while True:
167172
row = random.randint(0, 8)
168173
col = random.randint(0, 8)
@@ -179,7 +184,7 @@ def generate_sudoku(self, level=2):
179184
remove_cell -= 1
180185
self.counter = 0
181186
# break
182-
# self.__print_board__(sudoku_board)
187+
self.__print_board__(sudoku_board)
183188
return sudoku_board
184189

185190
def __print_board__(self, board):

visualizer.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

www/index.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,31 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5-
<title>Sudoku - Backtracking Algorithm visualizer</title>
5+
<title>Sudoku - Backtracking Algorithm Visualizer</title>
66
<script src="/jquery.js"></script>
77
<script src="/eel.js"></script>
88
<script src="/script.js"></script>
99
<link rel="stylesheet" type="text/css" href="style.css">
1010
</head>
1111
<body>
12+
<div class="action_message" style="display: none">
13+
</div>
1214
<div class="container">
15+
<!-- header containing buttons and game infos -->
1316
<div class="header">
1417
<div class="buttoms">
1518
<div class="btn" id="new_btn">New Puzzle</div>
1619
<div class="btn" id="solve_btn">Solve</div>
1720
</div>
18-
<div class="timer"></div>
21+
<div class="game_info">
22+
<div class="level"></div>
23+
<div class="timer"></div>
24+
</div>
1925
</div>
2026
<div class="body">
27+
<!-- Sudoku Borad -->
2128
<div class="sudoku_board">
29+
<!-- 9 3x3 grids -->
2230
<div class="grid" id="grid0"></div>
2331
<div class="grid" id="grid1"></div>
2432
<div class="grid" id="grid2"></div>

www/script.js

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ function format_sudoku_data() {
1111
return data
1212
}
1313

14-
1514
$(function () {
1615
var i = 0
1716
html = ""
@@ -23,36 +22,91 @@ $(function () {
2322
}
2423

2524
$('#new_btn').click(function () {
26-
eel.generate_new_sudoku()
25+
var level = ["Easy", "Medium", "Hard", "Expert"]
26+
var i = 1
27+
html = ""
28+
$(".action_message").html("");
29+
for (; i < 5; i++) {
30+
temp = `<div class="btn btn_margin select_level" id="level${i}" data-level="${i}">${level[i - 1]}</div>`
31+
html = $(".action_message").html() + temp;
32+
$(".action_message").html(html);
33+
}
34+
close_btn = "<div class='close'>x</div>"
35+
html = $(".action_message").html() + close_btn;
36+
$(".action_message").html(html);
37+
$(".action_message").toggle(20);
38+
$('.close').on("click", function () {
39+
$(".action_message").toggle(20);
40+
});
41+
$('.select_level').on("click", function () {
42+
eel.generate_new_sudoku($(this).attr("data-level"));
43+
$(".level").html(level[$(this).attr("data-level") - 1]);
44+
$(".cell").removeClass("empty")
45+
});
46+
2747
});
2848
$('#solve_btn').click(function () {
29-
eel.solve_sudoku()
49+
var level = ["Quick Solve", "Visualize"]
50+
var i = 1
51+
html = ""
52+
$(".action_message").html("");
53+
for (; i < 3; i++) {
54+
temp = `<div class="btn btn_margin solve_mode" data-mode="${i - 1}">${level[i - 1]}</div>`
55+
html = $(".action_message").html() + temp;
56+
$(".action_message").html(html);
57+
}
58+
close_btn = "<div class='close'>x</div>"
59+
html = $(".action_message").html() + close_btn;
60+
$(".action_message").html(html);
61+
$(".action_message").toggle(20);
62+
$('.close').on("click", function () {
63+
$(".action_message").toggle(20);
64+
});
65+
$('.solve_mode').on("click", function () {
66+
eel.solve_sudoku($(this).attr("data-mode"));
67+
if ($(this).attr("data-mode") == 1)
68+
$(".action_message").toggle(20);
69+
});
70+
3071
});
3172

3273
});
3374

3475

76+
// JavaScript functions exposed to python
3577
eel.expose(draw_sudoku)
3678
eel.expose(update_sudoku)
3779

80+
// Function for drawing sudoku
3881
function draw_sudoku(data) {
3982
for (i = 0; i < 81; i++) {
40-
row = ~~(i / 9)
41-
col = i % 9
42-
if (data[row][col] != 0) $("#" + i).text(data[row][col])
43-
else $("#" + i).text("")
83+
// row and col values for corresponding i values
84+
row = ~~(i / 9);
85+
col = i % 9;
86+
87+
// filling sudoku board with values
88+
if (data[row][col] != 0) { // cell in not empty
89+
if ($("#" + i).html() != "") $("#" + i).removeClass("empty");
90+
$("#" + i).text(data[row][col]);
91+
} else { // cell is empty
92+
$("#" + i).addClass("empty");
93+
$("#" + i).text("");
94+
}
4495
}
96+
// toggle level selector pane
97+
$(".action_message").toggle(20);
4598
}
4699

100+
// Function updating sudoku board during visualiztion
47101
function update_sudoku(val, i) {
48-
if (val == 0) {
102+
if (val == 0) { // if cell value wrong during backtracking
49103
$("#" + i).removeClass("solved");
50104
$("#" + i).addClass("error");
51105
setTimeout(function () {
52106
$("#" + i).removeClass("error");
53107
$("#" + i).text("")
54108
}, 200);
55-
} else {
109+
} else { // one of the valid cell value
56110
$("#" + i).addClass("solved");
57111
$("#" + i).text(val);
58112
}

0 commit comments

Comments
 (0)