<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body class="solver">
<div id="solver">
<div class="table">
<div class="r0">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r1">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r2">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r3">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r4">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r5">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r6">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r7">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
<div class="r8">
<div>
<input type="text" class="0" maxlength="1">
</div>
<div>
<input type="text" class="1" maxlength="1">
</div>
<div>
<input type="text" class="2" maxlength="1">
</div>
<div>
<input type="text" class="3" maxlength="1">
</div>
<div>
<input type="text" class="4" maxlength="1">
</div>
<div>
<input type="text" class="5" maxlength="1">
</div>
<div>
<input type="text" class="6" maxlength="1">
</div>
<div>
<input type="text" class="7" maxlength="1">
</div>
<div>
<input type="text" class="8" maxlength="1">
</div>
</div>
</div>
<div class="right_pannel">
<p class="msg">Stand by</p>
<div>
<textarea class="initVal">
</textarea>
<div class="buttons">
<button onclick="javascirpt:exe();" style="width: 50px;">Solve</button>
<button onclick="javascirpt:set();" style="width: 36px;">Set</button>
<button onclick="javascirpt:load();" style="width: 45px;">Load</button>
<button onclick="javascirpt:clr();" style="width: 48px;">Clear</button>
</div>
<div>
<label><input type="checkbox" name="show" value="on" class="chk_show">Show
process(slow)</label>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
/****************스도쿠 함수 시작*****************/
/****************스도쿠 함수 시작*****************/
/****************스도쿠 함수 시작*****************/
var r = new Array(9);
var c = new Array(9);
var s = new Array(9);
for (var i = 0; i < 9; i++) {
r[i] = new Array(9);
c[i] = new Array(9);
s[i] = new Array(9);
}
var Set = function(rn, cn) {
this.rn = rn;
this.cn = cn;
this.num = [ true, true, true, true, true, true, true, true, true ];
};
function init() {
for (var i = 0; i < 9; i++)
for (var j = 0; j < 9; j++)
c[j][i] = r[i][j] = { v : 0 };
for (var rn = 0; rn < 9; rn += 3)
for (var cn = 0; cn < 9; cn += 3)
for (var i = 0; i < 3; i++)
for (var j = 0; j < 3; j++)
s[rn + parseInt(cn / 3)][i * 3 + j] = r[rn + i][cn + j];
}
function sizeofNumset(set) { // 가능한 숫자 개수 카운터
var n = set.num;
return n[0] + n[1] + n[2] + n[3] + n[4] + n[5] + n[6] + n[7] + n[8];
}
function findAblNum(rn, cn) { // 해당 칸의 가능한 숫자 세트 탐색
var nums = new Set(rn, cn);
var sn = parseInt(rn / 3) * 3 + parseInt(cn / 3); // 섹터 번호 구함
for (var i = 0; i < 9; i++) {
// 행(r),열(c),섹터(s) 탐색
if (r[rn][i].v > 0) // 채워져 있으면
nums.num[r[rn][i].v - 1] = false; // 마킹
if (c[cn][i].v > 0)
nums.num[c[cn][i].v - 1] = false;
if (s[sn][i].v > 0)
nums.num[s[sn][i].v - 1] = false;
}
return nums;
}
function findMinPossible() { // 가장 경우의 수가 적은칸의 세트 리턴
var size = 10;
var minset = null;
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (r[i][j].v > 0) continue; // 채워진칸 무시
var temp = findAblNum(i, j);
var nsize = sizeofNumset(temp);
if (!nsize) // 빈칸인데 가능한 숫자가 없으면
return new Set(10, 10); // 오답 표시 리턴
else if (nsize === 1) // 가능한 숫자가 하나일 경우 바로 리턴
return temp;
else if (nsize < size) {
size = nsize;
minset = temp;
}
}
}
return minset;
}
function solve() {
var set = findMinPossible(); // 가장 경우의 수가 적은 칸 탐색
if (set === null) // 더 이상 빈칸이 없음을 뜻함.
return true; // 풀린것!
if (set.rn > 9) // 불가능한 칸이 있음을 뜻함
return false;
for (var i = 1; i <= 9; i++) { // 숫자 1~9를 채우는 부분
if (!set.num[i - 1])
continue; // 불가능한 숫자는 스킵
r[set.rn][set.cn].v = i; // 가능한 숫자를 채움
if (solve()) // 채운걸 풀어봄
return true; // 그게 풀렸으면 탈출
}
// 채울 수 있는 숫자가 없거나 다 채워봤는데 안된거니까
r[set.rn][set.cn].v = 0; // 지우고
return false; // 오답 리턴
}
(function main() {
init();
})();
/*************여기까지 스도쿠 함수 끝*************/
/*************여기까지 스도쿠 함수 끝*************/
/*************여기까지 스도쿠 함수 끝*************/
/* 중요하지 않은 html UI 상호 작용 함수 함수 */
var delay = 1;
function fill(rn, cn, val) {
if(val>0)
cnt++;
setTimeout(function() {
grd[rn][cn].value = val > 0 ? val : "";
}, cnt * delay);
}
function display() {
for (var i = 0; i < 9; i++)
for (var j = 0; j < 9; j++)
grd[i][j].value = r[i][j].v > 0 ? r[i][j].v : "";
}
function solve2() { // solve 함수에 풀이 상황 표시 추가
var set = findMinPossible();
if (set === null)
return true;
if (set.rn > 9)
return false;
for (var i = 1; i <= 9; i++) {
if (!set.num[i - 1])
continue;
r[set.rn][set.cn].v = i;
fill(set.rn, set.cn, i); // 이것만 추가
if (solve2())
return true;
}
r[set.rn][set.cn].v = 0;
fill(set.rn, set.cn, 0); // 이것만 추가
return false;
}
function set() {
clr();
var input = initVal.value.replace(/[^0-9\.]/g, "");
for (var i = 0; i < 9; i++)
for (var j = 0; j < 9; j++)
grd[i][j].value = /[1-9]/.test(input[i * 9 + j]) ? input[i * 9 + j]
: "";
}
function load() {
var output = "";
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++)
output += /[1-9]/.test(grd[i][j].value) ? grd[i][j].value : 0;
output += '\n';
}
initVal.value = output;
}
function clr() {
msg.textContent = "Stand by";
var inputs = table.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++)
inputs[i].value = inputs[i].className = "";
}
function exe() {
msg.textContent = "Initializing";
for (var i = 0; i < button.length; i++)
button[i].disabled = true;
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if (/[1-9]/.test(grd[i][j].value))
r[i][j].v = parseInt(grd[i][j].value);
else {
r[i][j].v = 0;
grd[i][j].className = "unstatic";
}
}
}
msg.textContent = "Running";
setTimeout(function() {
var flag = false;
cnt = 1;
flag = chk_show.checked ? solve2() : solve();
setTimeout(function() {
for (var i = 0; i < button.length; i++)
button[i].disabled = false;
msg.textContent = flag ? "Solved" : "No Solution";
display();
}, chk_show.checked ? cnt * delay : 0);
}, 1);
}
var grd = new Array(9);
var msg, button, initVal, solver, table, chk_show;
for (var i = 0; i < 9; i++)
grd[i] = new Array(9);
(function() {
// 요소 참조
solver = document.getElementById("solver");
chk_show = solver.getElementsByClassName('chk_show')[0];
msg = solver.getElementsByClassName('msg')[0];
table = solver.getElementsByClassName('table')[0];
button = solver.getElementsByTagName('button');
initVal = solver.getElementsByClassName('initVal')[0];
for (var i = 0; i < 9; i++) {
var row = solver.getElementsByClassName('r' + i)[0]
.getElementsByTagName('input');
for (var j = 0; j < 9; j++)
grd[i][j] = row[j];
}
initVal.value = '800000000\n003600000\n070090200\n050007000\n000045700\n000100030\n001000068\n008500010\n090000400';
set();
// 그리드 css
for (var i = 0; i < 9; i++)
for (var j = 0; j < 9; j++) {
var sn = parseInt(i / 3) * 3 + parseInt(j / 3);
grd[i][j].parentNode.className = sn % 2 ? "even" : "odd";
}
chk_show.addEventListener("click", function() {
if(!chk_show.checked)
return;
var choice = prompt("Set delay per action(ms)\ndefalut: 1ms\n1~200ms recommended", delay);
if(choice === null)
return;
delay = parseInt(choice) || 1;
delay = delay < 1 ? 1 : delay;
});
})();
#solver,.solver{
width: 745px;
margin: 0 auto;
}
#solver .table input {
width: 55px;
height: 55px;
font-size: 33pt;
text-align: center;
vertical-align: middle;
color: #2B75E4;
border: none;
box-shadow: 0px 0px 1px #000000;
background-color: transparent;
}
#solver .msg {
font-size: 38pt;
color: #2B75E4;
height: 70px;
width: 180px;
white-space: nowrap;
}
#solver p {
margin: 0px 0px;
}
#solver .table input.unstatic {
color: #696969;
}
#solver .table>div {
display: table;
}
#solver .table>div>div {
display: table-cell;
}
#solver .table {
background-color: white;
display: table;
border: 3pt solid black;
float: left;
}
.right_pannel {
float: left;
margin-left: 20px;
}
.initVal {
-webkit-box-sizing: border-box;
/* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box;
/* Firefox, other Gecko */
box-sizing: border-box;
/* Opera/IE 8+ */
height: 220px;
width: 196px;
}
#solver .table>div:nth-child(3),
#solver .table>div:nth-child(6) {
border-bottom: 3pt solid black;
}
#solver .table>div>div:nth-child(3),
#solver .table>div>div:nth-child(6) {
border-right: 3pt solid black;
}
.buttons button {
font-size: 10pt;
line-height: 20px;
}
.even {
background-color: rgba(0, 0, 0, 0.09);
}