Developing a Sudoku Game in HTML5
Sudoko is a number puzzle game that is very popular right now. The puzzle is a 9x9 grid, divided into nine 3x3 boxes, each of which is comprised of 9 cells. The following figure shows the total grid of 81 cells.
Goal of the puzzle
The goal is to fill every cell with a number, 1 through 9, such that each row, column, and box contains only one instance of each number from 1 through 9.
The initial state of each puzzle consists of some cells in the grid already populated with numbers. Given this initial state, there is one, and only one, solution to the puzzle, and it can be deduced using logic to fill in all of the missing numbers.
Consider the puzzle in the figure . As mentioned, every box must include the numbers 1 through 9. Currently, the upper-left box doesn't have a 2 in it, but I can figure out where the 2 in that box should go through simple deduction. I know it can't be in the top row because there's already a 2 in that row (the 2 in the upper-right corner, highlighted in yellow). I know it can't be in the middle row, because there's already a 2 there, as well (the 2 in the second row, fourth column). It obviously can't be in the third row, second column, as there's already a 7 there (highlighted in yellow), and it can't be in the cell to the 7's right, because there's already a 2 in that column (highlighted in yellow in the eighth row). Therefore, the 2 must be in the third row, first column—the cell highlighted in red. I can fill in that 2, moving me one step closer to solving the puzzle.
Rules of the Puzzle
- No number can repeat itself in the same 3x3 square
- No number can repeat itself on the same 9 cells column or row.
- Every empty cell should have a "mirror" empty cell (for example cells [0,7] & [8,1] or [3,3] & [5,5]). Also when cells and 3x3 Cox index starts from "0", left to right, top to bottom.
- Each game should have one and only one solution to be considered a valid Sudoku game.
Game Options
1. Game
- New: The user can select among multiple difficuly levels:
1. Easy
2. Medium
3. Hard
- Save/Restore: The user can save the game.
2. Edit
- Undo: Undoes the last digit entered or other user actions such as Accept or Solve. It is implemented using a stack so records can undo an unlimited number of actions. A Load, Reset, or Clear empties the undo stack.
- Hint: Enters the answer to the current cell in that cell. It gets the answer from the current board hence if the board is already incorrect, no hint will be given.
- Restart: Play the same game from a state before any move was first made.
- Solve: Solves the entire problem from the current position. This may not give the solution if values already entered are incorrect.
3. Sound
- On: The user can hear the sound while solving the Sudoku.
- Off: The user solves the Sudoku in silent mode.
4. Keyboard
- On: The user can solve the Sudoku using the keyboard.
- Off: The user solves the Sudoku without any use of the keyboard.
5. Help
- No number can repeat itself in the same 3x3 square.
- No number can repeat itself on the same 9 cells column or row.
- Every empty cell should have a "mirror" empty cell (for example cells [0,7] & [8,1] or [3,3] & [5,5]) Also when cells and 3x3 Cox index starts from "0", left to right, top to bottom.
- Each game should have one and only solution to be considered a valid Sudoku game.
- About:The puzzle was introduced in Japan by Nikoli in the paper Monthly Nikolist in April 1984 as "Sūji wa dokushin ni kagiru", which can be translated as "the digits must be single" or "the digits are limited to one occurrence". (In Japanese, dokushin means an "unmarried person".) At a later date, the name was abbreviated to Sudoku by Maki Kaji , taking only the first Kanji of compound words to form a shorter version. Sudoku is a registered trademark in Japan and the puzzle is generally referred to as Number Place. In 1986, Nikoli introduced two innovations: the number of givens was restricted to no more than 32, and puzzles became "symmetrical".
Example
<!doctype html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Sudoku Preview - CodeCanyon</title>
<meta name="Description" content="Sudoku is a logic-based, combinatorial puzzle. The objective is to fill a 9×9 grid with digits so...">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="http://1.envato-static.com/assets/fullscreen_preview-2dff58760ddd3fb5acb3540e65f6ef43.css" media="screen" rel="stylesheet" type="text/css" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/icons/codecanyon.net/apple-touch-icon-144x144-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/icons/codecanyon.net/apple-touch-icon-114x114-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/icons/codecanyon.net/apple-touch-icon-72x72-precomposed.png" />
<link rel="apple-touch-icon-precomposed" href="/icons/codecanyon.net/apple-touch-icon-precomposed.png" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script>window.jQuery || document.write("<script src='http://3.envato-static.com/assets/lib/jquery-1.8.1.min-da0866090343e2cef3f789ab7482744a.js'><\/script>")</script>
<script>
//function to fix height of iframe!
var calcHeight = function () {
var headerDimensions = $('#header-bar').height();
$('#preview-frame').height($(window).height() - headerDimensions);
}
$(document).ready(function () {
calcHeight();
$('#header-bar a.close').mouseover(function () {
$('#header-bar a.close').addClass('activated');
}).mouseout(function () {
$('#header-bar a.close').removeClass('activated');
});
});
$(window).resize(function () {
calcHeight();
}).load(function () {
calcHeight();
});
</script>
<!-- JAVASCRIPT FOR AND GOOGLE ANALYTICS -->
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-11834194-12']);
_gaq.push(['_trackPageLoadTime']);
_gaq.push(['_trackPageview']);
_gaq.push(['b._setAccount', 'UA-11834194-36']);
_gaq.push(['b._trackPageLoadTime']);
_gaq.push(['b._trackPageview']);
(function () {
var ga = document.createElement('script');
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
ga.setAttribute('async', 'true');
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- END JAVASCRIPT -->
<meta content="" name="WT.si_n" />
<meta content="" name="WT.si_x" />
<meta content="" name="WT.si_cs" />
<script type="text/javascript">var NREUMQ = NREUMQ || []; NREUMQ.push(["mark", "firstbyte", new Date().getTime()]);</script>
</head>
<body>
<div id="header-bar">
<div class="close-header">
<a id="close-button" title="Close CodeCanyon Bar" class="close" href="http://codeblog.cz/sudoku/">X</a>
</div>
<p class="meta-data">
<a class="close" href="http://codeblog.cz/sudoku/">Remove Frame</a> <a class="purchase" href="/item/sudoku/3576054">Purchase this Item!</a>
</p>
<a class="acodecanyon-preview-logo site-loopback" href="/item/sudoku/3576054">codecanyon</a><span class="preview">item preview</span>
</div>
<iframe id="preview-frame" src="http://codeblog.cz/sudoku/" name="preview-frame" frameborder="0" noresize="noresize"></iframe>
<!-- START OF SmartSource Data Collector TAG v10.2.0 -->
<!-- Copyright (c) 2012 Webtrends Inc. All rights reserved. -->
<script>
window.webtrendsAsyncInit = function () {
var dcs = new Webtrends.dcs().init({
dcsid: "dcsu1to8wvz5bd8f6if7d3qse_2j4x"
, domain: "statse.webtrendslive.com"
, timezone: 10
, offsite: true
, download: true
, downloadtypes: "xls,doc,pdf,txt,csv,zip,docx,xlsx,rar,gzip"
, onsitedoms: "codecanyon.net"
, plugins: {
hm: { src: "//s.webtrends.com/js/webtrends.hm.js" }
}
}).track();
};
marketplace.load("http://0.envato-static.com/assets/webtrends.min-5a2a0b3d9f0eeafea3f60e4831cf4958.js");
</script>
<noscript><img alt="dcsimg" id="dcsimg" width="1" height="1" src="//statse.webtrendslive.com/dcs4nx9hnvz5bd4wo8cwvxpse_5g4u/njs.gif?dcsuri=/nojavascript&WT.js=No&WT.tv=10.2.0&dcssip=www.3docean.net"/></noscript>
<!-- END OF SmartSource Data Collector TAG v10.2.0 -->
<!--[if lt IE 7]>
<script src="http://3.envato-static.com/assets/lib/DD_belatedPNG-27285c137194823d2b38f405dd132024.js" type="text/javascript"></script>
<script src="http://2.envato-static.com/assets/utilities/ie6-bf43a1fe705b18ce14da6c1e3ab8f752.js" type="text/javascript"></script>
<![endif]-->
<script type="text/javascript">if (!NREUMQ.f) {
NREUMQ.f = function () {
NREUMQ.push(["load", new Date().getTime()]);
var e = document.createElement("script");
e.type = "text/javascript";
e.src = (("http:" === document.location.protocol) ? "http:" : "https:") + "//" +
"d1ros97qkrwjf5.cloudfront.net/42/eum/rum.js";
document.body.appendChild(e);
if (NREUMQ.a) NREUMQ.a();
};
NREUMQ.a = window.onload; window.onload = NREUMQ.f;
};
NREUMQ.push(["nrfj", "beacon-1.newrelic.com", "fcf8d519de", "13909,1601845,716468", "dA4NFkNbVV1URBcMRVIMTAREWFVuQlVKAFRZPhMQVEJQVEY=", 5, 37, new Date().getTime(), "", "", "", "", ""]);</script>
</body>
</html>
Output