├── .babelrc ├── .gitignore ├── CNAME ├── LICENSE ├── README.md ├── bundle.css ├── bundle.js ├── css ├── github-corner.less ├── main.less └── normalize.less ├── favicon.ico ├── index.html ├── js ├── boards.js ├── game.jsx ├── index.jsx ├── store.js └── sudoku.jsx ├── package.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | {"presets": ["es2015", "react"]} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | sudoku.js.org -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 2015-2016 Andrey Nering 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Sudoku 2 | 3 | A simple web sudoku game made with [ReactJS][reactjs] and [Redux][redux]. 4 | [Play online here][play]. 5 | 6 | See the [VueJS version here][vuejssudoku]. 7 | 8 | ### Features 9 | 10 | - Mobile-friendly 11 | - Uses [LocalStorage][localstorage] to save the current game state 12 | 13 | ### Building locally 14 | 15 | Prerequisites: 16 | 17 | - NodeJS 18 | - NPM 19 | - [Webpack][webpack] (installed globally) 20 | - [LESS][less] and the [clean CSS plugin][lesscleancss] (installed globally) 21 | 22 | ```bash 23 | $ git clone https://github.com/andreynering/sudoku.git 24 | $ cd sudoku 25 | $ npm install 26 | $ npm run buildjs 27 | $ npm run buildcss 28 | ``` 29 | 30 | [reactjs]: https://facebook.github.io/react/ 31 | [redux]: http://redux.js.org/ 32 | [play]: https://sudoku.js.org/ 33 | [vuejssudoku]: https://github.com/andreynering/vuejs-sudoku 34 | [webpack]: https://webpack.github.io/ 35 | [localstorage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage 36 | [less]: http://lesscss.org/ 37 | [lesscleancss]: https://github.com/less/less-plugin-clean-css 38 | -------------------------------------------------------------------------------- /bundle.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}body,html{font-family:Helvetica,Arial,sans-serif;background:#fff;margin:0}h1{font-size:30px}p{font-size:16px;font-weight:100;line-height:24px}.wrapper{padding-right:20px;padding-left:20px;padding-top:50px;max-width:580px;margin:auto}.version{border:2px solid #eee;margin-top:25px;height:200px;display:-webkit-flex;display:flex}.version-section{padding:10px;height:100%}.version-section.dark{background:#151513}.demo{border-right:2px solid #eee;position:relative;width:200px}.code{vertical-align:top;width:336px}.code textarea{border:2px solid #eee;outline:0;height:100%;width:100%;font-family:monospace;font-size:10px}.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%{transform:rotate(0)}20%{transform:rotate(-25deg)}40%{transform:rotate(10deg)}60%{transform:rotate(-25deg)}80%{transform:rotate(10deg)}100%{transform:rotate(0)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}footer{width:100%;margin-top:25px;margin-bottom:100px;background:#F3F3F3;height:50px;padding:15px;padding-left:25px;padding-right:25px;color:#2D2D2D;font-size:13px;letter-spacing:1px;font-family:monospace}footer a{color:#2d2d2d}footer span{margin-left:10px;margin-right:10px}.twitter-share-button{margin-bottom:-4px}@media (max-width:500px){footer{text-align:center;height:auto;line-height:30px}footer span{display:none}footer a{display:block}.twitter-share-button{margin-bottom:-8px}}.sudoku-table{border:3px solid #000;margin-left:auto;margin-right:auto;font-size:16pt}.sudoku-table td{border:1px solid #000;width:35px;height:35px}.sudoku-table input{width:35px;height:35px;border:0;text-align:center}.controls{margin-top:15px;margin-left:auto;margin-right:auto}.controls *{margin-left:5px}.i2,.i5{border-bottom:3px solid #000!important}.j2,.j5{border-right:3px solid #000!important}.not-editable input{font-weight:700}.has-conflict input{color:red}@media (max-width:600px){.github-corner{display:none}}@media (min-width:600px){.sudoku-table{margin-top:50px}.controls{width:400px}}.dialog{background-color:#f0f0f0;width:400px;height:400px;margin-left:auto;margin-right:auto}.dialog *{margin-left:5px;font-size:20px}.dialog-close{position:relative;top:2px;right:2px}.congratulations{color:red}.index{text-align:center} -------------------------------------------------------------------------------- /css/github-corner.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Github Corners, page css 3 | * Author: Tim Holman 4 | */ 5 | 6 | * { 7 | box-sizing: border-box; 8 | } 9 | 10 | html, body { 11 | font-family: Helvetica, Arial, sans-serif; 12 | background: #fff; 13 | margin: 0px; 14 | } 15 | 16 | h1 { 17 | font-size: 30px; 18 | } 19 | 20 | p { 21 | font-size: 16px; 22 | font-weight: 100; 23 | line-height: 24px; 24 | } 25 | 26 | .wrapper { 27 | padding-right: 20px; 28 | padding-left: 20px; 29 | padding-top: 50px; 30 | max-width: 580px; 31 | margin: auto; 32 | } 33 | 34 | /** 35 | * Demo Code 36 | */ 37 | 38 | .version { 39 | border: 2px solid #eee; 40 | margin-top: 25px; 41 | height: 200px; 42 | display: -webkit-flex; 43 | display: flex; 44 | } 45 | 46 | .version-section { 47 | padding: 10px; 48 | height: 100%; 49 | } 50 | 51 | .version-section.dark { 52 | background: #151513; 53 | } 54 | 55 | .demo { 56 | border-right: 2px solid #eee; 57 | position: relative; 58 | width: 200px; 59 | } 60 | 61 | .code { 62 | vertical-align: top; 63 | width: 336px; 64 | } 65 | 66 | .code textarea { 67 | border: 2px solid #eee; 68 | outline: 0px; 69 | height: 100%; 70 | width: 100%; 71 | font-family: monospace; 72 | font-size: 10px; 73 | } 74 | 75 | .github-corner:hover .octo-arm { 76 | animation: octocat-wave 560ms ease-in-out; 77 | } 78 | 79 | @keyframes octocat-wave { 80 | 0% { 81 | transform: rotate(0deg); 82 | } 83 | 84 | 20% { 85 | transform: rotate(-25deg); 86 | } 87 | 88 | 40% { 89 | transform: rotate(10deg); 90 | } 91 | 92 | 60% { 93 | transform: rotate(-25deg); 94 | } 95 | 96 | 80% { 97 | transform: rotate(10deg); 98 | } 99 | 100 | 100% { 101 | transform: rotate(0deg); 102 | } 103 | } 104 | 105 | @media (max-width: 500px) { 106 | .github-corner:hover .octo-arm { 107 | animation: none; 108 | } 109 | 110 | .github-corner .octo-arm { 111 | animation: octocat-wave 560ms ease-in-out; 112 | } 113 | } 114 | 115 | /** 116 | * Footer 117 | */ 118 | 119 | footer { 120 | width: 100%; 121 | margin-top: 25px; 122 | margin-bottom: 100px; 123 | background: #F3F3F3; 124 | height: 50px; 125 | padding: 15px; 126 | padding-left: 25px; 127 | padding-right: 25px; 128 | color: #2D2D2D; 129 | font-size: 13px; 130 | letter-spacing: 1px; 131 | font-family: monospace; 132 | } 133 | 134 | footer a { 135 | color: #2d2d2d; 136 | } 137 | 138 | footer span { 139 | margin-left: 10px; 140 | margin-right: 10px; 141 | } 142 | 143 | .twitter-share-button { 144 | margin-bottom: -4px; 145 | } 146 | 147 | /** 148 | * Media 149 | */ 150 | 151 | @media (max-width: 500px) { 152 | 153 | footer { 154 | text-align: center; 155 | height: auto; 156 | line-height: 30px; 157 | } 158 | 159 | footer span { 160 | display: none; 161 | } 162 | 163 | footer a { 164 | display: block; 165 | } 166 | 167 | .twitter-share-button { 168 | margin-bottom: -8px; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /css/main.less: -------------------------------------------------------------------------------- 1 | @import "normalize"; 2 | @import "github-corner"; 3 | 4 | .sudoku-table { 5 | border: 3px solid black; 6 | margin-left: auto; 7 | margin-right: auto; 8 | font-size: 16pt; 9 | 10 | td { 11 | border: 1px solid black; 12 | width: 35px; 13 | height: 35px; 14 | } 15 | 16 | input { 17 | width: 35px; 18 | height: 35px; 19 | border: 0px; 20 | text-align: center; 21 | } 22 | } 23 | 24 | .controls { 25 | margin-top: 15px; 26 | margin-left: auto; 27 | margin-right: auto; 28 | 29 | * { 30 | margin-left: 5px; 31 | } 32 | } 33 | 34 | .i2, .i5 { 35 | border-bottom: 3px solid black !important; 36 | } 37 | 38 | .j2, .j5 { 39 | border-right: 3px solid black !important; 40 | } 41 | 42 | .not-editable { 43 | input { 44 | font-weight: bold; 45 | } 46 | } 47 | 48 | .has-conflict { 49 | input { 50 | color: red; 51 | } 52 | } 53 | 54 | @media (max-width: 600px) { 55 | .github-corner { 56 | display: none; 57 | } 58 | } 59 | 60 | @media (min-width: 600px) { 61 | .sudoku-table { 62 | margin-top: 50px; 63 | } 64 | 65 | .controls { 66 | width: 400px; 67 | } 68 | } 69 | 70 | .dialog { 71 | background-color: #f0f0f0; 72 | width: 400px; 73 | height: 400px; 74 | margin-left: auto; 75 | margin-right: auto; 76 | 77 | * { 78 | margin-left: 5px; 79 | font-size: 20px; 80 | } 81 | } 82 | 83 | .dialog-close { 84 | position: relative; 85 | top: 2px; 86 | right: 2px; 87 | } 88 | 89 | .congratulations { 90 | color: red; 91 | } 92 | 93 | .index { 94 | text-align: center; 95 | } 96 | -------------------------------------------------------------------------------- /css/normalize.less: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS and IE text size adjust after device orientation change, 6 | * without disabling user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability of focused elements when they are also in an 95 | * active/hover state. 96 | */ 97 | 98 | a:active, 99 | a:hover { 100 | outline: 0; 101 | } 102 | 103 | /* Text-level semantics 104 | ========================================================================== */ 105 | 106 | /** 107 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 108 | */ 109 | 110 | abbr[title] { 111 | border-bottom: 1px dotted; 112 | } 113 | 114 | /** 115 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 116 | */ 117 | 118 | b, 119 | strong { 120 | font-weight: bold; 121 | } 122 | 123 | /** 124 | * Address styling not present in Safari and Chrome. 125 | */ 126 | 127 | dfn { 128 | font-style: italic; 129 | } 130 | 131 | /** 132 | * Address variable `h1` font-size and margin within `section` and `article` 133 | * contexts in Firefox 4+, Safari, and Chrome. 134 | */ 135 | 136 | h1 { 137 | font-size: 2em; 138 | margin: 0.67em 0; 139 | } 140 | 141 | /** 142 | * Address styling not present in IE 8/9. 143 | */ 144 | 145 | mark { 146 | background: #ff0; 147 | color: #000; 148 | } 149 | 150 | /** 151 | * Address inconsistent and variable font size in all browsers. 152 | */ 153 | 154 | small { 155 | font-size: 80%; 156 | } 157 | 158 | /** 159 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 160 | */ 161 | 162 | sub, 163 | sup { 164 | font-size: 75%; 165 | line-height: 0; 166 | position: relative; 167 | vertical-align: baseline; 168 | } 169 | 170 | sup { 171 | top: -0.5em; 172 | } 173 | 174 | sub { 175 | bottom: -0.25em; 176 | } 177 | 178 | /* Embedded content 179 | ========================================================================== */ 180 | 181 | /** 182 | * Remove border when inside `a` element in IE 8/9/10. 183 | */ 184 | 185 | img { 186 | border: 0; 187 | } 188 | 189 | /** 190 | * Correct overflow not hidden in IE 9/10/11. 191 | */ 192 | 193 | svg:not(:root) { 194 | overflow: hidden; 195 | } 196 | 197 | /* Grouping content 198 | ========================================================================== */ 199 | 200 | /** 201 | * Address margin not present in IE 8/9 and Safari. 202 | */ 203 | 204 | figure { 205 | margin: 1em 40px; 206 | } 207 | 208 | /** 209 | * Address differences between Firefox and other browsers. 210 | */ 211 | 212 | hr { 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. 354 | */ 355 | 356 | input[type="search"] { 357 | -webkit-appearance: textfield; /* 1 */ 358 | box-sizing: content-box; /* 2 */ 359 | } 360 | 361 | /** 362 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 363 | * Safari (but not Chrome) clips the cancel button when the search input has 364 | * padding (and `textfield` appearance). 365 | */ 366 | 367 | input[type="search"]::-webkit-search-cancel-button, 368 | input[type="search"]::-webkit-search-decoration { 369 | -webkit-appearance: none; 370 | } 371 | 372 | /** 373 | * Define consistent border, margin, and padding. 374 | */ 375 | 376 | fieldset { 377 | border: 1px solid #c0c0c0; 378 | margin: 0 2px; 379 | padding: 0.35em 0.625em 0.75em; 380 | } 381 | 382 | /** 383 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 384 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 385 | */ 386 | 387 | legend { 388 | border: 0; /* 1 */ 389 | padding: 0; /* 2 */ 390 | } 391 | 392 | /** 393 | * Remove default vertical scrollbar in IE 8/9/10/11. 394 | */ 395 | 396 | textarea { 397 | overflow: auto; 398 | } 399 | 400 | /** 401 | * Don't inherit the `font-weight` (applied by a rule above). 402 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 403 | */ 404 | 405 | optgroup { 406 | font-weight: bold; 407 | } 408 | 409 | /* Tables 410 | ========================================================================== */ 411 | 412 | /** 413 | * Remove most spacing between table cells. 414 | */ 415 | 416 | table { 417 | border-collapse: collapse; 418 | border-spacing: 0; 419 | } 420 | 421 | td, 422 | th { 423 | padding: 0; 424 | } 425 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreynering/sudoku/f8a58fcdcf15d1594850a3021d74f17795b0a4bf/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | Sudoku - Play Online 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /js/boards.js: -------------------------------------------------------------------------------- 1 | var easy = [ 2 | '016002400320009000040103000005000069009050300630000800000306010000400072004900680', 3 | '017030590000000403000006070120009050000402000060700021030600000901000000054020310', 4 | '018093005002710000046000000000000079100904002250000000000000920000032500600850140', 5 | '018700059700000000405800030607900000000050000000007106050001904000000003830002560', 6 | '019000000002390010357200000000002930200000008091600000000008293080024600000000850', 7 | '020056000000009018500000200000780059005000800270045000006000004430600000000570090', 8 | '020080004800140020059200300760000000000907000000000056002004910040031007600090030', 9 | '020089107001002300950000600400900000000010000000004003009000012002400500103520080', 10 | '020090407700302500000000006359000000040020060000000745900000000004601003806030070', 11 | '020100004010024090900300260402030000000205000000070509041007003080510070700002080', 12 | '020103000000006190000002704800000070530000016090000003403600000018300000000509080', 13 | '020300000090000580703000000100508020200090008050703009000000801081000030000009060', 14 | '020307000900000170701604005310500000200000006000002017800709400079000008000106030', 15 | '023100900100000080700059013071003400300000008002400370910520007030000004007001290', 16 | '024010090010000300003648000000780000270030041000029000000851700009000050080090410', 17 | '025000070000000901600410200000069000009104500000370000004053009206000000050000480', 18 | '025607100000005900700030000001200080090000010050009200000060002004900000008503670', 19 | '027900010000070000000000026308517000006040800000863405280000000000050000010004380', 20 | '028003140700000000014000005031264000000000000000978430100000290000000007049600350', 21 | '029004700580001000070056900000000007712000698400000000001620030000900046008500170', 22 | '030000000005010203060930400000100630306050108024003000009042060602080700000000080', 23 | '030000046200000075000400300053090000406805709000070150009006000640000008170000030', 24 | '030002900500000000000004378800230090600040003070089001325600000000000007007900060', 25 | '030020050600004002005000004083007900000851000001900840400000600100700008050010090', 26 | '030060824860014000900300000000049750000000000076250000000002007000470085795030040', 27 | '030504790756010000000000003470000000003060200000000071300000000000050824018709030', 28 | '030700920801050007000000085050200000070401060000005070510000000200080409089007010', 29 | '030897500005040100000001006000000279800000001719000000500600000001030900003189060', 30 | '031450000640000000005002001000001950500947003019300000300100500000000024000084730', 31 | '035290000000800350010030000009600830400050007082001900000060020021009000000025640', 32 | '036059000000000900009010076000007080907000104050800000460030500002000000000720840', 33 | '036090001800000000021003807058700000000935000000008650107200360000000009500080720', 34 | '040000000002800003001376020007008106409060208506900700060291300200004900000000040', 35 | '040000000100052600900403070000001039800020005390800000050208006008530002000000010', 36 | '040000103000300080000028500005004200210807096003200700009170000020003000506000070', 37 | '040001009000000054509400002102070000000803000000040207200006803360000000800500060', 38 | '040002510002056003907000000000000097003040200120000000000000301400860700091500080', 39 | '040006000000002040098045000034000058600000004870000620000130560080700000000200070', 40 | '040020000018005000070308400450000000000276000000000068005702010000400790000010050', 41 | '040100005000080000280306000028030079300000006760050430000507092000090000500003010', 42 | '040507000000000091009003480003040002001609300400010700037900800680000000000804030', 43 | '040690000000000000387001600500020470001040300064080005008400291000000000000068030', 44 | '040800300000004200067209140000000801080070050601000000073601490005700000006008010', 45 | '040900000002630507690000008000120000700000001000095000400000023506042100000001070', 46 | '040950160000000000000632900567200000090000070000005698002569000000000000086074050', 47 | '041000000008006740306000000070095010803167402010320070000000804035200900000000230', 48 | '041059000600000000800360000200004053006935200750200001000048007000000006000620410', 49 | '042000000900354000000000050706830000030040020000019807050000000000728009000000270', 50 | '042003950000000070000000301470300500050906010006001034708000000060000000035600290', 51 | '042600000600090030009100080060001000007000500000200070010003400090050006000008920', 52 | '047000061800200000006703800000060180600070009019050000003609500000005003480000690', 53 | '047200609008970040000000000005000030314060597090000200000000000080056300201008960', 54 | '048039000025000040900000003060001000002853100000600050600000001080000730000410520', 55 | '048390010000008000000001520009080006000905000800030900032400000000200000050073460', 56 | '048602050000000000005070832000000014437000528680000000872010900000000000010908370', 57 | '048690200701002000000000049000080320100000005056030000820000000000100508004058670', 58 | '048700050000300000000080609060007034080124060420600080803010000000008000090006720', 59 | '049000080000671000000900002500410200092000740007095003800004000000759000010000570', 60 | '050000000102400050630580000095000068400030001820000430000052017010009305000000090', 61 | '050000004230004600006000035500800700090010080008009002670000200001600058800000070', 62 | '050000080920750160000000790400270801000000000305089007069000000032065078040000030', 63 | '050000300900070084001800200185207000000060000000409138007002800690080002002000060', 64 | '050007906087003000000002000500190007740000095900078003000300000000800610801700040', 65 | '050008000691500008000000625780960000000000000000072094439000000500004937000300060', 66 | '050009487300000000080270300006000035100806002520000600005068040000000003693400070', 67 | '050013080400500006308000004210070000000000000000020093500000307700008001020750040', 68 | '050020004007580920400006000000000493060000050328000000000700006013042500500090010', 69 | '050040000900000032308005060000200008070304010600001000090700406580000003000050090', 70 | '050300800000409356000750009006000007000000000300000600700082000639504000005007010', 71 | '050400000000080659010306000627000000300000005000000294000209070275010000000007020', 72 | '050409760210003000004020000001005040005000600060800100000030800000200071097501020', 73 | '050430000479802600000000000003074200047000530001350700000000000005607912000029070', 74 | '050600741060000000308200000004300000630907082000005900000003504000000060481002070', 75 | '050800100000019600000000240685000000007308900000000862063000000008720000009001030', 76 | '051037000000010009706008100695400000000000000000005694008300701300050000000170530', 77 | '051080006006350400000006020810000200000508000004000057040100000007039500500040680', 78 | '052071003007500082060000000000004090004000500010300000000000060520007100900610870', 79 | '053106000680000000200000065004280016000060000720031900410000003000000024000902680', 80 | '056003700000006500000000029004070000729000135000050400810000000005400000003900210', 81 | '056070000900002000078564030420008050000000000080700042030486710000300008000090420', 82 | '057000002000050180000301700029106000000070000000504910004805000086010000500000630', 83 | '057420000630005000089310000000000400300748005004000000000067130000200094000034260', 84 | '058040030000087205300000087009006000000030000000400700210000003803210000040050920', 85 | '058300000000194700000006920490000017000000000830000054082900000003718000000002470', 86 | '058900060100007090203050108900000000006000800000000005309080406010600002040009380', 87 | '060000000000250060108000207009500070040793010080006500602000701090075000000000040', 88 | '060000000001009020000007143000250096036000210490068000843700000020800700000000030', 89 | '060000000004050068008930004050000630010040020026000040900085200640070900000000070', 90 | '060000000005026400020000098240093860000040000053860042370000050001570300000000070', 91 | '060000200070000386304068005000037000080090070000580000100850407258000090006000020', 92 | '060000504009100000014500790600002000000873000000900003097008640000004900103000080', 93 | '060040820500000000020008001070100004046203750900005060200800010000000008091060040', 94 | '060100000703000510108200000070040008901683402600020090000006801046000905000002040', 95 | '060180004400700020005300080300000700000060000001000003040009500080005002900031040', 96 | '060407810500002000000000923071000059000000000690000240136000000000200004027501080', 97 | '060510208000006039002000000000000014080401090450000000000000500270800000503079080', 98 | '060829000040060030007000080700030500001905600006070009070000100020010090000293040', 99 | '060830002030020000000000100620078001000514000400260053002000000000040090700085060', 100 | '061000000054082000830000000070400002205306907600005040000000095000260810000000260', 101 | '062300700004060900900000000308000062500020004290000103000000007001080600005009340', 102 | '062900010038452090500060000000000051200506004350000000000070008080295170070008520', 103 | '064002300003710000700003000340009007500000006900800043000900008000025700005400920', 104 | '068039000900060018100000000000500702810000064203004000000000006350020001000340820', 105 | '068120000007004000900800000070003200403080105006400080000009001000300400000061920', 106 | '069000000308500900200009000080390001006040700900027080000100004007006502000000160', 107 | '069030000000165900700000000096051030003649200040370590000000001007528000000010780', 108 | '069400000725030049403000000000006090030010020050900000000000406890040235000008910', 109 | '070000080005018006000000251200805600050060040003902007768000000500180400010000060', 110 | '070000300000347509800000000009604018000020000680103900000000003901482000006000020', 111 | '070009005000001000123008070600000100002486700007000002080300921000800000200100050', 112 | '070010209009480000006300007930000000004030800000000054600003400000062100802050060', 113 | '070018000000002807003500000240900070001287300030005062000009600609800000000430080', 114 | '070020900000007104000051060620008400000060000008500026090170000201300000004080030', 115 | '070400000290001400000900002006003009400789001500600300100005000005100063000008010', 116 | '070400003090100000003605008000000304084000720306000000200509400000003010100002090', 117 | '070500018000000004453700600000200060009604200060007000005009142100000000620001080', 118 | '070900004002000000050087060003000245800010007624000900060230010000000500200006090', 119 | '071439000000000000603075200000000061010596070540000000002960704000000000000742610', 120 | '071605830006090007020000004000570000008000200000064000500000010800050700063701540', 121 | '072003900430000000090470000005020000003849700000060400000032040000000092006100570', 122 | '072610000080300007100070006050000140620000078014000060400060003200008050000053420', 123 | '073900000012000000004850000009270000760493081000065900000089300000000470000007520', 124 | '076080000800000200091027000400002005050030060100400007000840730003000001000060890', 125 | '076180020200000507000007100800005000092000610000900008005800000904000006020054370', 126 | '076308090000001002004007030460200900000000000008006014030800100200100000080702640', 127 | '076430005300072086000000000010300200080060030002008060000000000960710002200083510', 128 | '079540000600000190000036800006073500300000007007460900002650000091000003000019450', 129 | '080000000000609502024300000000706210070090030039204000000003170103907000000000040', 130 | '080000000000946007060307000570000009804503702600000015000801030100469000000000050', 131 | '080000030020017000400235910600003000290040056000500001034652009000370040070000020', 132 | '080006300570090000201804907620000000000080000000000038809207106000060079005900020', 133 | '080030000004000120902600000020308000370000058000702060000009607016000400000080010', 134 | '080030057000564000000000200050000049004873600860000030003000000000928000790050020', 135 | '080030407200074180001000000060089000000000000000120070000000600025390008706010020', 136 | '080200530069050000001048000000000670200000009048000000000410900000070120097005060', 137 | '080409030032000080600800000000000063006758100970000000000001004050000670010604050', 138 | '080750340700009600000000007001080093970000026240090100300000000002300008064015030', 139 | '081007040000000060907500000005004608000706000702800900000003402030000000070400530', 140 | '083001209910008070500009000008000060000050000070000900000800006040600013109300840', 141 | '084060009000000300000037016150000003008106500400000061210580000003000000500010230', 142 | '084500000001002650000060090000000567060401030235000000050080000017900300000007420', 143 | '086000094400090000000000508090038100070609030001740050703000000000070005910000240', 144 | '087000069000070000000104700030208057700030001960701030001803000000090000590000370', 145 | '089000000000065000047900621065001000000609000000300850231008560000520000000000940', 146 | '089571400000000000073004020000006005305000802800900000010400360000000000006753980', 147 | '089700100010000000460200000530120000800050002000067095000008064000000070004001230', 148 | '090000000040300000080690257006070100210080075008030900853027090000003020000000080', 149 | '090000000740005000000871050500302079800000005930506001080713000000600087000000060', 150 | '090000146170000000050400020000024300002080900007590000080006010000000038526000070', 151 | '090000726300050400600009100000680000000705000000012000009100007002090003748000060', 152 | '090006370000817500050000000041608093000000000380704610000000050002975000065100030', 153 | '090028003000007400030100000000000280658000739017000000000006050009300000300750040', 154 | '090046500800019630000800000000100790100000005029004000000001000051490002002530010', 155 | '090050800382010000401000000024038100030090020009640580000000908000060475005070060', 156 | '090082100782600400000000006000000365049203780863000000400000000008009674005340010', 157 | '090176000000400900000020074520610400800000002006058037150060000002003000000791060', 158 | '090200100056400038000006007361000000000000000000000743200900000410003670007005090', 159 | '090250400301060000000001590000000803000579000605000000089600000000090305003048070', 160 | '090300100000750608004100000000000720400000001058000000000006400802094000009003050', 161 | '091007000000060800030205060573000900000000000006000327040501080009070000000300570', 162 | '092000003570800000000200040010080400208904701005010020060001000000008092700000650', 163 | '092450300008020107000100000264000000000070000000000568000008000905060400003019850', 164 | '093050000000407801408600050200070000800105006000020005040009602902704000000060790', 165 | '096040000000803000000100423503000000089000510000000604872001000000308000000090860', 166 | '096150803800004005014000000000000002005783400700000000000000760100600004607042580', 167 | '097000000000000630000052810380009000060030080000600041024960000018000000000000270', 168 | '097000230000740081010030000009000504000090000205000100000010040620059000051000390', 169 | '097028000000000060000500210003006490050943080019800700035007000080000000000430820', 170 | '098003000003004000010502060000038002800000005300650000070406080000300100000100290', 171 | '100000000000014275000930000005000009039157420700000800000041000968520000000000003', 172 | '100000000020013950080069007090500000037000620000006090600970080015320060000000009', 173 | '100000000070000800000850069700003980000469000032100004620017000009000030000000006', 174 | '100000040740003001800007602000004380000789000028300000203900004600200018010000003', 175 | '100000048000910000760200000000060427003000500874090000000005091000031000430000005', 176 | '100000070574100000008005400700030100940502037006010002003800700000009361050000008', 177 | '100000095096300704000000000010062000802000307000480010000000000704005620980000001', 178 | '100000400000200056206700000000120800020080070009057000000006708430008000005000003', 179 | '100000500007240003806950014700530000000000000000026005650078401900015800001000007', 180 | '100000860000000070000632015790800040030040080020001053970316000010000000085000001', 181 | '100003700020008000007090624002700006050109070700004900275080100000900040001300002', 182 | '100004950000000000020509610030600000000475000000003080051806090000000000064900007', 183 | '100005869000300000005010320000000008480609072300000000023080900000007000869400001', 184 | '100030000090010827005000000000003005703020409200400000000000500821090070000060003', 185 | '100030209008005000409000000600078300307000506002650004000000802000200100901080003', 186 | '100060000030470000040008306405007000670000085000600401703500040000046050000090003', 187 | '100060200096720000430500000001905006000000000200106400000001064000058790004090002', 188 | '100078000000000502093100000000000320306000907082000000000005490201000000000630008', 189 | '100083906082090040000000000000001003940368052300900000000000000090050260401270005', 190 | '100085000004000080302400000007000160010529030035000200000002504020000700000190006', 191 | '100090007080600000000400698060000305050000040307000060294005000000003080500040006', 192 | '100204800030800170400000009900007000000631000000400008600000007041008050005306002', 193 | '100208070048930060790000000900000000005020800000000007000000016080075420020406005', 194 | '100300070000000000500070389012004000860050024000800730485020007000000000020009005', 195 | '100400009004050600000260004200600010900000007030007002500043000003070100400002003', 196 | '100508047004070000000004000702800604300090005609002308000400000000020100870109003', 197 | '100603200000000680009200500030000006200080001800000040002005900095000000006307002', 198 | '100800000000010030850000900007036009082070450600480100004000087030090000000003001', 199 | '100800000007930100020071800090067008700389002800420070008250090006093400000008003', 200 | '100900000004700025080000640000150003800000004600032000095000070710004500000007006', 201 | '100900502000500030000104000010000647006807100974000050000309000060002000809006005', 202 | '102000000000080200043500100000350004075208690800064000004005980001070000000000301', 203 | '102000070600029000000410500000000240070506030031000000003048000000150006060000803', 204 | '102400000070000452090000010500060200000834000009010006010000080258000070000007905', 205 | '104000000809060000030018006040009010000603000090500080200850090000020107000000805', 206 | '104007000800000200007500680000040006020090040700060000089002400003000009000300807', 207 | '105000000000094020000003070840930700500000009003082045080500000060840000000000107', 208 | '105007000000062500709005800800700040400000007070003006004500208007210000000900704', 209 | '106000090700009360040602001000001620000040000078200000800306010053900006060000509', 210 | '106500000000008204500007600200004080000805000040300002007900003903700000000003709', 211 | '106902000040150800000000000001069074072000190490310200000000000004071050000503409', 212 | '107080003405901000000000000258000000040602010000000792000000000000205609600090507', 213 | '107500000005004378000200005032070050000000000010080420600002000974100200000006107', 214 | '107600930000012500000900400960180000000000000000037069001006000005320000094008601', 215 | '108400000009800010546900000900000180003000700061000009000004896090005300000007401', 216 | '108400093000009000005230000800900000350000041000008002000017600000800000630002708', 217 | '109006000000480000058003076602000000007010400000000209980300620000047000000200305', 218 | '109060000340000090000000430500830000030649070000021003063000000090000025000010308', 219 | '109300000060010000000900780090085107700000003801790020017009000000050070000004905', 220 | '120005300006000005000072000304050009000010000200040503000860000800000400001900026', 221 | '120008030007300500000270846003000000200000005000000700842039000009006300030100059', 222 | '120076500400000100000540300080000000700215003000000050009084000007000004008120065', 223 | '120560000309000400000300068406100030000000000050007601930002000002000806000045029', 224 | '123060400007800600600090007000100000000254000000008000900010008004005700005020136', 225 | '124000070050037000006810000000500320500000009041003000000085100000960080060000932', 226 | '140053009005000003000900050000590810900030007028074000080009000500000200300760084', 227 | '140703250020000000009000004080034075000601000690270030400000800000000040016405097', 228 | '140720050000084000900103007000000600290465031007000000800309006000670000070042019', 229 | '140839000730100000000000030015060300960000042004010690020000000000001064000623017', 230 | '140900030502013000003600000020004007009080400400500020000001300000370506060009014', 231 | '145006000000000000600753100006380002090000050800049300009631005000000000000900437', 232 | '150296000000000090092430000000002034600000007920600000000024350080000000000713049', 233 | '150700000020048006300000000004800090002401600070009300000000001600120080000007025', 234 | '156280090000000640000000500008630009001908700300045800005000000043000000090063485', 235 | '158006090000000001004801300860000000007080500000000012003504600900000000040200173', 236 | '160097030040500000000300000850000100002408500006000078000006000000009040030750069', 237 | '160270000020004901000000500000620400490000013006041000001000000608900050000017068', 238 | '160300000004950000000014002207000090600205001050000803500140000000087100000009068', 239 | '160720000000360000000000006078200060015000920090008430900000000000031000000087095', 240 | '160903080200000001040000700502000040800050003030000105003000090400000008090308052', 241 | '167009000009800050000000000002945078000010000970268300000000000080006700000500189', 242 | '170000000008041650005030018000010095000506000510070000730060200091480500000000049', 243 | '170000430006000790000000001200009080410278069060500002900000000083000200042000058', 244 | '170040030006700000005008006294000000000030000000000194400900800000005200020060075', 245 | '170200830400508017800700002000000700310000058002000000200009006040607009063001075', 246 | '179300050080000009230400000007060000000749000000020800000007065600000090090002138', 247 | '186000000000000003370400500700600100900253007004001008009004031600000000000000856', 248 | '186400000700908020005000000200100000460000059000005003000000900010703002000004378', 249 | '190000002800000000050239001907020006000304000600070803300892040000000008400000035', 250 | '190003000506049120000000000000500940009368700062001000000000000041730805000100067', 251 | '190053080005006009000000040001000002904070506600000100080000000200800900030910058', 252 | '190060005476002100005009000000000081000805000680000000000700300003200794200040016', 253 | '192000568004001000000020000403500002060000040200009106000080000000300600985000731', 254 | '200000000700059068050008100920400000005080700000007026004600070360790001000000005', 255 | '200000007097000041800096020005009410000317000029400700010270004970000830500000002', 256 | '200009708700653004000070090800090030001000400070040009030080000900325001507900003', 257 | '200030000000005723800906050000000006100809005400000000090104002746500000000060004', 258 | '200053709030000086007902000000000091001060300370000000000309600890000010702840003', 259 | '200401060079000000180790200004600030000010000090008400008049027000000190040107005', 260 | '200500300050870000000006000930680420400000009025034018000300000000012090007005002', 261 | '200710094700000800040983070450200000000000000000009023010692040006000007590037001', 262 | '200800014700010000001095800000000790006907500072000000003620100000040006610009003', 263 | ]; 264 | 265 | var medium = [ 266 | '000023087600000500010700000009000004050872030800000700000005090002000006530960000', 267 | '000024600020039008060000024107000000008903500000000403950000040300590060006470000', 268 | '000025043200400076000000800000000065008659700540000000001000000650004007970830000', 269 | '000026003005000607000001940030000200709010806008000090084100000502000400300650000', 270 | '000026300000000074309004800060000003090401050500000020007600409950000000004810000', 271 | '000026713800500040200000000084010000600070004000060820000000005020007009567980000', 272 | '000028509000136000600000000290000100800000003001000097000000004000985000305470000', 273 | '000029300208000400095600000510000008000301000900000074000007640006000503004510000', 274 | '000030000000009106078000950080006001037010540500700060025000490309400000000020000', 275 | '000030000000207809000800103100003048000060000960400007702008000409301000000050000', 276 | '000030000040500980720100006000000120870000063039000000500004012083001050000070000', 277 | '000030000050000839000700010970100026030675090610009073080001000329000060000060000', 278 | '000030000204500060000010243129000000000000000000000827653090000040006501000050000', 279 | '000030009090000006007800230009100068008090500670002900016005800700000090500070000', 280 | '000030064306014700000700000004000502000908000207000100000007000001840307730090000', 281 | '000030096004109502000500000000000608002756900607000000000003000401205700730080000', 282 | '000030096900006200032500000590008400040000050001200079000009120005300007710020000', 283 | '000030120010004900000006073000109650000000000041305000190600000002800010073040000', 284 | '000030190000005000192000005000007048078000630420100000200000983000700000081090000', 285 | '000030217000009300013500000900000005105060802200000003000003480009400000824010000', 286 | '000030241020600700000000000050061008230040069100890020000000000005006090497020000', 287 | '000030600038000040000009750004903020000000000070401900089600000050000230002050000', 288 | '000030659000576302000000000000400120400000003079001000000000000308752000567040000', 289 | '000030802000500001000040750030400085040070010590002030016090000900001000203080000', 290 | '000030809000400070000900510468000005007080900900000281095001000030007000201060000', 291 | '000030840001402050900000000000600034700305008310009000000000002080201300093050000', 292 | '000030942970540000000009000000003800702010603006200000000300000000026075524090000', 293 | '000032160003400080006000000600005700810000052005200001000000800080007500027910000', 294 | '000032400061700002030000008000004010006503700050900000700000090800007320009380000', 295 | '000032460000604000000000012020009300009000600008100050230000000000201000041860000', 296 | '000035001907008000104000000020060008079000360500070090000000503000500209200910000', 297 | '000036090000001207020000001604900000050010060000003709300000080801400000070360000', 298 | '000036700005209006200000000026000008809000502100000670000000007900102300003740000', 299 | '000037000500000000007000932806003205050609080403800706169000300000000001000410000', 300 | '000038091900060000000000423010600002005000800700003050192000000000040009430950000', 301 | '000038106030000000000700350006140900000975000003062400021007000000000070704310000', 302 | '000040000000000032207001450600009041000306000590400006042100705160000000000080000', 303 | '000040000075108400000000006020000870010805090038000040200000000007906580000030000', 304 | '000040000903805000061370000712000009009000400600000725000098370000706208000010000', 305 | '000040001305000000002087400000100090026000140010003000004250800000000709500060000', 306 | '000040002803200000029701400761500000000000000000004871008406930000008706300070000', 307 | '000040007000200960051000008506007090000804000030600102800000350027003000300090000', 308 | '000040009059600000023000050800500000097000360000003005080000690000002580200010000', 309 | '000040020000003000076208400000001305009070200102800000008309760000500000020060000', 310 | '000040030600100050003000801706083000000060000000450709308000500040005002050070000', 311 | '000040036000003004005000900006002007907080301400600500004000800200700000590030000', 312 | '000040050600283000009100006106000000908000604000000308200009500000462003070010000', 313 | '000040050700000820002500030000056271000000000126370000040009600083000009060080000', 314 | '000040065000003001936000000000070010680010047040090000000000572400200000790060000', 315 | '000040090200700010040009008007006500002908600009400800900300080060001007030090000', 316 | '000040100482700000003000007100008204000904000704200005500000400000002936006080000', 317 | '000040273800010050000200001000000630000154000079000000400001000050060008167030000', 318 | '000040360000000100836200000290700500000000000007005026000006954004000000078020000', 319 | '000040800009802100070000003000013620200000004087250000700000050005601700003070000', 320 | '000041000370050490000000750000072040005184600020360000069000000041090026000410000', 321 | '000042000900000807005900000006009304200836009803400600000005100709000002000190000', 322 | '000042036005100000000800007047060001800000003600080940200004000000001400490650000', 323 | '000045003002307900400000200120000070006000300070000052009000008008709500200130000', 324 | '000045007607800405000200000300000510160000042028000006000002000206009701800310000', 325 | '000045200200300005001020040103000600800000003004000807020090700600004002009750000', 326 | '000046008000000060080000237060900041000501000310004070649000080050000000200430000', 327 | '000046713000000000000238509070000801000000000403000020104865000000000000952310000', 328 | '000046910000100020400000083029010000000834000000050870940000008080001000036470000', 329 | '000048000001000408008102060000020080890000052030070000040207900509000800000390000', 330 | '000050000008724500050080049783000000000000000000000368190040050005839400000070000', 331 | '000050000009401530400008000170000000290503078000000016000800009054302600000040000', 332 | '000050000030086057007100090005700080480000036060008900070009400820470060000030000', 333 | '000050002470029005000600470000000801030000040907000000083005000700390026200010000', 334 | '000050009069000400000009802905703004000010000700508603807900000001000530400080000', 335 | '000050009914003005370000000000006900008030700001400000000000087700800351800020000', 336 | '000050013041900000000061200170000504000000000508000037006790000000003650320010000', 337 | '000050018000600000982007000057000042000000000810000570000500396000009000340010000', 338 | '000050030000700810008931570010200000090506080000007090087345100053009000060070000', 339 | '000050062320006000090700800012007000000060000000300580005009010000400053930080000', 340 | '000050100000009483001024000010000008098000640300000010000980500289600000007010000', 341 | '000050100060100800000034900800000530040000010023000004008540000007001020005070000', 342 | '000050283200000000607003000020300809000000000403009050000600508000000002395070000', 343 | '000050300537000900000008005000005049040293010790600000100800000003000427009040000', 344 | '000050302030000000742000005020035080000904000090870060200000956000000010803060000', 345 | '000050360000731090050000000000900002304000507200003000000000050010698000086020000', 346 | '000050627600203000090000040004020050000305000050090800040000070000108004312070000', 347 | '000050800000000070930400600000008760070346050096200000004001032050000000001060000', 348 | '000050840801096000000780005130000070006000500080000092500048000000670309098030000', 349 | '000051269160000000050800010800000070000183000090000002080006090000000025516420000', 350 | '000052370063700000000080500000003706002000100806400000007020000000007830051930000', 351 | '000052600026930000000004090600000908400000005903000004070200000000019280001340000', 352 | '000054070037000000060002501090000004000647000800000030201400050000000290050230000', 353 | '000054700280300060050001030000008000036090240000400000040200090020003054001540000', 354 | '000057001004003090006940050652300000000000000000009362040095100060200700200430000', 355 | '000057409000000000000001078060040035405030901830020040780300000000000000901580000', 356 | '000057900080009000020040050900004008001000600200100007030080010000300040005970000', 357 | '000059020270000090610002008020003000900000007000400060400200053080000019090630000', 358 | '000059204000000050530700000008000390300010005012000600000005068080000000109360000', 359 | '000060000060008700209005000057000041010050080980000250000400103001700020000080000', 360 | '000060000064010009273800000640005000005090800000100056000002983900070240000080000', 361 | '000060000960010028042000010004006097700000003830900500080000270270040036000090000', 362 | '000060002700004010024900070000005086400812005580600000030006940090300007200090000', 363 | '000060020030017098402950000920700000000000000000001047000096703370580060050070000', 364 | '000060093080007400003000068000023000190405037000170000870000600001800070460090000', 365 | '000060250000409380000070009097600502000000000503007460800050000045206000062030000', 366 | '000060398000938000000000005200003800100846009004500007400000000000359000819020000', 367 | '000060753900010000000002010000007800206000907003600000040500000000070006687090000', 368 | '000060790000008000002490001000059106908000207506280000800024500000800000067010000', 369 | '000061005605040320009500040742000000000000000000000217020008500034020106500130000', 370 | '000061040006009087073000600000000230080000010017000000002000960760500400090820000', 371 | '000062000406000720090000008007800006200040003500001400600000040073000501000730000', 372 | '000063201002000000050004090709200000001609400000007908030900050000000800204150000', 373 | '000063400009500000000048009580000670020000040041000038600830000000004700008290000', 374 | '000064002000013670000000009625400003100000006300006298700000000063240000400670000', 375 | '000064210814230000000007000090002703300000001507300090000700000000083147076420000', 376 | '000065049035007060000008000048000000600000005000000170000200000070800320980610000', 377 | '000065080049000016300000900000008701000257000407600000004000009730000540090520000', 378 | '000067400086050000170003000000600900047000610001002000000100084000090270005470000', 379 | '000069000000000029008301040001053000059000160000190300090806400520000000000570000', 380 | '000069230620030000000700000268000001370000052900000376000001000000040025037520000', 381 | '000070000000006005000500486800000072200138009530000001973002000600400000000090000', 382 | '000070000009300050415900063200000000067090520000000001670001295090007100000030000', 383 | '000070000013000407800000035000900084020641050940003000160000002507000360000050000', 384 | '000070002000900405020000060052040609006153200401020350040000080208004000900030000', 385 | '000070020000000038026003075304600500000000000005009806930100450540000000010020000', 386 | '000070050500008130004105007180000500000406000006000098200503900043800005060010000', 387 | '000070400200010370300800000100009600600000003007200004000004001051020008006050000', 388 | '000070450806000000000009103490100700000503000005002019207900000000000601068010000', 389 | '000070500079508300000302078300000002015000680700000009850106000004705860007030000', 390 | '000070504754086000600500000000000841007000600849000000000004002000850976902030000', 391 | '000070509043008000800000030900600820000020000038004006010000003000700260702050000', 392 | '000070923000800000002090060620000040000746000070000035010060700000001000456020000', 393 | '000072004920100000500800320693000000000000000000000486079005008000001093800260000', 394 | '000073650200400000050008002800020005002000900700030006900600040000005007035780000', 395 | '000074150605000000004000960000810020700000001080037000097000500000000204043180000', 396 | '000074206004012000000000080001080007502060803900030600090000000000720100703640000', 397 | '000074285000000000000006790460080001000709000700010038035800000000000000184950000', 398 | '000075000053020100000400056500000820090050060062000007920006000007040680000180000', 399 | '000075000500001300920000000046500007700060002300004960000000096004600001000950000', 400 | '000075801000000050208010400000000089700103005620000000002050307060000000405620000', 401 | '000076050000050310400008007049000001700030005100000740600800004071040000030610000', 402 | '000078000006001870090600540007000000030715020000000700041007030089100200000960000', 403 | '000078640000000000000406528904000300000000000008000701435607000000000000062390000', 404 | '000078900000000085000009207803900540009000700064001809507800000480000000006130000', 405 | '000079203370120000000000001009300500830000029007005800600000000000061048701580000', 406 | '000080000003000070420006500506193700000000000009572106002300045090000800000060000', 407 | '000080000027300000000001950300000706590000032702000008064200000000009460000010000', 408 | '000080000030100006876009000010000070008205900050000080000600742700001030000040000', 409 | '000080000050400001100006205004900007000648000600007500306800002800003070000050000', 410 | '000080000278009000091200000020305007100000009600907080000002640000400372000050000', 411 | '000080000365070000008009261030000500506000903002000080691500300000090612000010000', 412 | '000080000600000028043200100000007005005326700200400000006009870370000004000030000', 413 | '000080001309200000005010030006390000090000010000072500020050300000009704400030000', 414 | '000080006600400070028697000000000314080000020513000000000159640050004002100020000', 415 | '000080010002605094300041500068300000000000000000007120003150009750406200090070000', 416 | '000080040300107000600000097200009075050000060780500001460000003000605009070090000', 417 | '000080043047001069300009000008000004000312000900000600000100006890700530750090000', 418 | '000080047000300000000015032003500400006030100008007500950240000000001000460050000', 419 | '000080050500002600000006030074600900081000760006009480010200000005700004020090000', 420 | '000080170400070000700000092030940206500000009902058040270000001000090004084020000', 421 | '000080230000000074460500001000075010507060309030890000200003048310000000076040000', 422 | '000080290350900000000040006003004009090603020500200100400090000000005064038060000', 423 | '000080301001320000000004080006800700104000906009003800090400000000037600503090000', 424 | '000080600700004000000000325002300807090805030308001200834000000000700003001090000', 425 | '000080600839020000000007050700300000604090203000008006010800000000050971003070000', 426 | '000080607000030050060005081800001000300859006000400009520900060040010000903070000', 427 | '000080700000715900760300001130000000005000200000000047500007082009651000006020000', 428 | '000081064150003070000000003000002006904000308600900000400000000090100047510790000', 429 | '000081090000060052000700410098000000003906500000000720087002000910040000020630000', 430 | '000083625000090007060007390279000000000000000000000256012700040700050000453210000', 431 | '000085004592000300000003010300000500004050600006000002040900000009000436700160000', 432 | '000085900000000415000300200400090760500000008036070002003006000654000000007130000', 433 | '000086024706000000000000659009300008040000030600001400374000000000000807290670000', 434 | '000086049600000000009200560500148006000000000800632004078001200000000001140570000', 435 | '000089001500000007009006805610005000000000000000200093807400200900000008100930000', 436 | '000090000000073600509060170050400006068000750400006080076080502004620000000040000', 437 | '000090000003800460080000200040002870905080106078100020002000050054001600000040000', 438 | '000090000109870000830020400620000010300000007040000032007030095000069703000080000', 439 | '000090000203008000000462170000000089730050041690000000079384000000700304000020000', 440 | '000090000802000003006100050000057060008020300020610000050008900400000705000070000', 441 | '000090003030674000050000070900200001600709005300001004070000010000467050400010000', 442 | '000090003603800020000016904936000010000020000040000398309760000010009506700080000', 443 | '000090006900000250010200908000300009084000730600005000107004090093000001400050000', 444 | '000090040002800560060100820501000000000207000000000605086004050019008400070030000', 445 | '000090050009700208680100000310000800000050000006000039000004086907008500050010000', 446 | '000090051040000030850204000700006000025000710000700004000301097080000040910050000', 447 | '000090062900300070000002050014020000060508040000070690090800000070001004380040000', 448 | '000090100906000050300507900500006000040000080000900004004208001010000703002010000', 449 | '000090370003701500490000000900050000004182900000060008000000016009306700065070000', 450 | '000090700070000006196800000080051000002070600000230090000005183800000020004080000', 451 | '000090840090341200000000001000000108560020037107000000900000000001682050042050000', 452 | '000090852070005600000000003008050924000609000912040300600000000004100030327080000', 453 | '000091034030400900000000082610500009000030000900006015760000000001007050540910000', 454 | '000091750527040000000000000000000319350070028182000000000000000000050234045980000', 455 | '000092400080130000004000600820000006007903800400000095008000900000028040002740000', 456 | '000092504000000000540016300970000400000809000001000079008960047000000000107430000', 457 | '000093004900000060020167900740000010000872000030000029006725090090000001500940000', 458 | '000093150000000000000145627003000070507000806040000300394256000000000000056730000', 459 | '000094000520010800430500002700000020000359000040000009300005064007040018000130000', 460 | '000094020000000008000002490040080210150030046023060080035600000800000000060920000', 461 | '000094100800000000090300205501000000700010002000000409103009070000000003002540000', 462 | '000094500006100030030000801310002400008000600004800073901000050040001200002980000', 463 | '000094706970000010000001004010700038000000000350002090800900000090000065706140000', 464 | '000095000190000000040007920900500007058060230200003009075900060000000083000280000', 465 | '000095204034000105020000000008051009000709000700420500000000080901000450402510000', 466 | '000095400900300520001600030000000090680020053010000000070002900058007002006580000', 467 | '000095408900000000006020010079000001800000006400000720050080900000000007607340000', 468 | '000096480180000000000820090003007940070000060091400200040078000000000079027950000', 469 | '000097050000000001857401200795000004000000000100000862009508123300000000010240000', 470 | '000098260300000000000650080060000540900205008054000090040086000000000007025970000', 471 | '000100000000060090034009201029000700040010050003000680108200540070040000000003000', 472 | '000100000000060917003790006006000072070000050390000600900056200485020000000001000', 473 | '000100000000867015186000000620370000070000040000052036000000928850231000000009000', 474 | '000100000009000086000597000075800400200000008001005620000941000840000700000003000', 475 | '000100000400000506203045000300050298000000000957020001000860403801000002000007000', 476 | '000100000800020006320000508004300000030917040000002900607000029400050007000003000', 477 | '000100000849200000130080007006800010900615003010004200500040098000008534000001000', 478 | '000100002040600300570020000000000054405090106160000000000040035004003020900008000', 479 | '000100004100004069003057000975000000010000030000000581000420600280700005700001000', 480 | '000100007000056309700400006007000080095060730040000600400003002102690000900007000', 481 | '000100020030027600208500000614002000000000000000600715000005804006210070050009000', 482 | '000100079000000000000607281096004100830000027004200690315408000000000000960003000', 483 | '000100406500000800000065701090080000400000009000030010904350000007000002802004000', 484 | '000100603930800000000000240850009000001708900000200074073000000000003027209006000', 485 | '000100702000005106700080040600000030007608200020000001070060005803700000509004000', 486 | '000103005801000002030960000000006850000304000027800000000039070600000901200407000', 487 | '000103040590000006003020800860230000000000000000061059005090400900000083070602000', 488 | '000104000081070390000000010030400007200090001500006080050000000074080560000305000', 489 | '000104800000900210300000000030002100860000074001400020000000007084007000009503000', 490 | '000105000000030650800000240000021009080000060700640000027000003068050000000407000', 491 | '000105908058060730000008060000000190100000002036000000040300000082090340903406000', 492 | '000106000000000965060200470472000500000070000009000736046003050387000000000701000', 493 | '000107004008040000000508019001005700030000020004200100520701000000090200900602000', 494 | '000108000080000006005400837238000010400000005050000783124006908800000060000804000', 495 | '000108074020000000400970030004500000063000420000002500030017005000000010670209000', 496 | '000120008000008000050000047008700405010000030907004200740000090000800000300095000', 497 | '000124000502000700036700000050000006009638500600000020000001680008000401000582000', 498 | '000129700050000000010054600038090200400000006007040810004610020000000090001972000', 499 | '000129703500708090000000000020900008093000560100002070000000000060207001908613000', 500 | '000130000000006070090007028740000000016070230000000014230700090080600000000019000', 501 | '000130000700000000009004803403276000600000004000543609504900700000000001000025000', 502 | '000130006009040000020000950000300008307050602500002000094000010000020800800097000', 503 | '000130080530084000002000000740000000029805670000000012000000200000290041080057000', 504 | '000140000000000960359000070000008096083060250690300000070000129014000000000051000', 505 | '000142000950000001006900020000000250500070009061000000070008900800000034000713000', 506 | '000143506000600000000008270150300400300000007006004053032800000000009000605231000', 507 | '000160094004000003000023001030000006007605400600000050800390000400000800920016000', 508 | '000164000005000030070000002004500200150000047006003800300000010080000500000928000', 509 | '000175490050000000000689075092000000100000007000000580780914000000000010031268000', 510 | '000179600200060030040000005039750000000000000000086340900000060080040007006598000', 511 | '000190500401000020003560010046008001000000000800300940030025100080000705009081000', 512 | '000190603060300005100008009300000400040080090008000006600700004900003020703029000', 513 | '000192000019580002000000050090000705380000016607000080060000000400067590000839000', 514 | '000200000000009586800070120008000005002743900700000300089020003253100000000005000', 515 | '000200000000010078065030000004000035780604029150000400000080750930070000000001000', 516 | '000200000000500630090040807000400176200000005571009000603080040089003000000004000', 517 | '000200000030000080807940060300050008790408052500010006080026509010000030000004000', 518 | '000200000130900400090000007200091004060030050300420009800000060005009038000003000', 519 | '000200001000570030240010890100000320030000070024000006052090083070082000900004000', 520 | '000200003000000250430800006904700000020030060000005701500003092083000000600007000', 521 | '000200006000500007060039104040000200030010080009000040306850090500003000700002000', 522 | '000200007000090004400173209800000600010000040009000005504716008200080000300009000', 523 | '000200007056040000030605002823000004001000300500000289400302090000090820900008000', 524 | '000200009300007080087000061802000000000413000000000907950000840010500002400008000', 525 | '000200048000008300000350620045700000700000005000002190051076000006800000470005000', 526 | '000200050200100900070000140706904000000000000000708605059000030003007001080002000', 527 | '000200080000401900070000002009003170001080500028900400200000050005108000040002000', 528 | '000200300030840000020000109000010054000507000560090000108000070000064090003008000', 529 | '000200509200019000950060200000000354000000000714000000007080023000950001108006000', 530 | '000200840200000007010007500020083004000725000600190080009400060100000003057001000', 531 | '000203060032000001000500002029000000007805600000000790600001000400000980090308000', 532 | '000203100080000450000000090090120005007504900400097020040000000072000010006305000', 533 | '000203900000004083093500100700000000080602030000000006006001720570400000001305000', 534 | '000204900840005700000700100360000000002000500000000073009002000005800049008501000', 535 | '000205030019000000200040600600007000495000726000900008007010003000000170060504000', 536 | '000205134000000008000008509005000041002591700670000900507300000800000000149806000', 537 | '000209430008000500050600002040700000800010003000004080400007090002000700075106000', 538 | '000230009000000800000068710109000208700050003304000605073890000001000000500023000', 539 | '000240300000001000724000058000300425000000000957002000140000839000500000006034000', 540 | '000240700000065104804000006000000067000903000920000000400000301305870000007031000', 541 | '000248076007000009050706000000000014004070800890000000000503090500000600680419000', 542 | '000250003260497000000006490008000024000060000910000800079600000000725049500049000', 543 | '000267310060000000000000084001020400608953107003040500410000000000000040092174000', 544 | '000280003092000001080005000003004210000050000054900700000600080600000130400091000', 545 | '000280300400001207900000046010000000006759400000000030890000004705100002002098000', 546 | '000280400000700605900000710030000041000020000260000030025000004701005000003012000', 547 | '000280507000003000620007000060000008370060021900000070000700083000900000704021000', 548 | '000286000000003240008000037000007004049000820600400000210000700095700000000892000', 549 | '000290001810000000009050706076009204000080000901400650204060300000000069100073000', 550 | '000297000000000950000060083060012400009040700004380060410070000093000000000154000', 551 | '000300000000000086300196042010020098000609000790040010850962001130000000000001000', 552 | '000300000000005060705090280208030001000487000400010308013040502050800000000001000', 553 | '000300000000005070109040008086900700900080006005002810800020401020700000000003000', 554 | '000300000000005403000001607010000706350080049607000080806400000403200000000006000', 555 | '000300000000020403024000007260003000070492080000800072100000940709050000000008000', 556 | '000300000509000710300058400000001060230000087010800000001780002043000508000006000', 557 | '000300000700060008000000562006908000059406180000702900137000000900020004000007000', 558 | '000300000740000500000071600600029350900050002057430009009560000008000026000002000', 559 | '000300004037600000000009081020000000005293700000000050390500000000007260400001000', 560 | '000300010905680000104000000003010060006408900020070300000000702000063108050002000', 561 | '000300048000074009029000000800006431000000000132900006000000170900830000640005000', 562 | '000300060500000000000605192792000005008000600300000219821907000000000001070008000', 563 | '000300071004000005000175000060010704300000009409060080000684000600000300250001000', 564 | '000300090200000038300024500007000600000715000002000800005840001140000003070006000', 565 | '000300280000100903000049060800000001009070500700000004010980000507004000084003000', 566 | '000300417700000000000502006020040079090000080510090030200401000000000001981003000', 567 | ]; 568 | 569 | var hard = [ 570 | '000070100000000300207830509700905230003000800089307005608053902004000000002090000', 571 | '000070300000500708800300090720800004900030007600002081010006002504003000006010000', 572 | '000070860000009001006580009695000000008000900000000513400015600700300000083060000', 573 | '000070900490200016630000002009600000300812007000007100900000084740005031001020000', 574 | '000070920000960005200043006750000000061000530000000062600710008500039000027050000', 575 | '000071050509000100060000000200008400004752900007900002000000030006000204080630000', 576 | '000071203802090600500060000000009070080000040090400000000040006003020408104650000', 577 | '000072000007308004200100000070020080081704520030080040000006008300805100000430000', 578 | '000073006049100005002090000005600900010000040007004500000080700900007820800320000', 579 | '000073600000200005009508200047009008390000056800700940004307800900001000006850000', 580 | '000074201082051060307000000003007004000000000500200300000000409020430670904710000', 581 | '000075080090000000700001209004058000605000403000360500109500006000000040070690000', 582 | '000080000000703900030060148050007000087902610000800020916020050005301000000070000', 583 | '000080000005006100080410709010000005400509001500000040203064070007800300000050000', 584 | '000080000279300000053490700900000400580000039004000001005043960000009572000070000', 585 | '000080003002006590507000068009100350000020000013005400490000207051200800700010000', 586 | '000080014900000000120094503000006030006809700030500000502370096000000007890040000', 587 | '000080043300040200760900500000038000001207800000650000003002057005010008490070000', 588 | '000080060000053402007100009030000048006090300410000020100009600803240000040010000', 589 | '000080064000451300000000120204100950000000000039005607027000000006514000340070000', 590 | '000080070080000050007001402861270900000000000004039861608700500040000020050060000', 591 | '000080090009400000000001058080210070001647300040098060310800000000003700050070000', 592 | '000080170800700040650120000020069000000302000000840020000036019060007002049010000', 593 | '000080200070060080500003710400020800000406000003010005094800001010070020007040000', 594 | '000080203020040000608200000006071508800000007103520600000002405000010060405060000', 595 | '000080730000072600000000528001046070080915040060230100173000000008350000045020000', 596 | '000080900000500004005600718406000300000739000001000207859001400100006000004020000', 597 | '000080900006700003950030041070003000003000800000200010280050037400001500005020000', 598 | '000081005080004209000000070209700000600803002000009406050000000702400010800260000', 599 | '000081073000054600000000054480200030019000720030009048790000000001840000350190000', 600 | '000081500020000000307006100002300069060020010910005200009100704000000090001840000', 601 | '000082407000000238000004010090500003100000002400007060030700000245000000709140000', 602 | '000082607700600000000509410219000500000000000007000238042806000000005002508120000', 603 | '000083065020004100405100030300000010200918003040000007030001804004500020150840000', 604 | '000083902300100000200007010020005090900218003060300070030700001000001009507820000', 605 | '000084037400000600012900000000070840000406000047090000000008160004000008680310000', 606 | '000085690000130048000006005005000032000318000890000400500600000470051000036470000', 607 | '000087000207000000004901260000000104040328090906000000071806400000000503000190000', 608 | '000089001048035097090000650200001000000070000000500004027000010560210740800750000', 609 | '000090000000007241000100076060050010000903000090080050640008000182700000000020000', 610 | '000090000003006280640700010912000000007000100000000936030001094024500700000080000', 611 | '000090000601840503002100008100000050020070040050000009200006400407021306000030000', 612 | '000090008005100700680507001540760000000000000000084027200403085001006900400020000', 613 | '000090008060430029095000000350008690000000000079300054000000210980075040100020000', 614 | '000090012000065000000100803200004730890000026067900001702009000000810000910070000', 615 | '000090027600000000090260140037000000000953000000000360065048090000000002940070000', 616 | '000090030608240000239800040900000620007000400063000009040008751000064302090050000', 617 | '000090034200508107000010080001850000003241700000079800060020000107405009850060000', 618 | '000090038009000060460700501200001300000030000003500004306009052010000800890010000', 619 | '000090040002006001015804600093000120000000000061000790006903870400100300030080000', 620 | '000090045090500100500008030000089000002703500000620000050800009003002080720060000', 621 | '000090100140060000000301602200000059070904010690000003907205000000010027006040000', 622 | '000090406070800050810006000060052300300000009007310020000600012090001030103070000', 623 | '000090630086504020000000000600048000004000100000930005000000000070201460051070000', 624 | '000090700006705000000000012030800095900241006610009020890000000000604200001080000', 625 | '000091005001000790064500000075010200000209000009080510000006320047000900600940000', 626 | '000092060010000000706000023204600000000000000000001409890000607000000080050360000', 627 | '000092100402510609000600005050000700000758000004000010700009000205061807001370000', 628 | '000093027000000300000700581900007000018906740000800006526008000003000000140250000', 629 | '000093600010000079900800000071500086000000000840009530000004008580000020004210000', 630 | '000094000840260000000000450093008620600000007024300980031000000000027043000530000', 631 | '000096050000078000005000871500000040013000290020000006731000900000910000050630000', 632 | '000100000005006008920000004060500070003627500050004020800000065700900200000003000', 633 | '000100000080050001500008923050000006916040285200000010195700008400090070000003000', 634 | '000100002023000608570020000000300025005902800780004000000060047207000130600001000', 635 | '000100005034000800006230700040000290000723000025000080007042600008000410400001000', 636 | '000100007900630800030097001059000603000000000304000250100320090008076002700001000', 637 | '000100008090030000000954600360000950800040001017000082006581000000070020700006000', 638 | '000100020031470000700000060000034106090000040406850000020000008000045670060002000', 639 | '000100080000004200000069143072305400000000000003901650489210000005400000010003000', 640 | '000100082300000040150000700000005009200736001600200000007000038020000004960004000', 641 | '000100900000209813000500060800000304490000082205000006080007000762408000001005000', 642 | '000102548000050000005038020043000107000000000608000490010280300000060000486309000', 643 | '000105320007040000200006500000080003080000040500060000004800002000070900093601000', 644 | '000105800680000000040000570700019300000302000003570001056000090000000012008904000', 645 | '000108000000030509700000040204000710980267054037000902040000006109020000000309000', 646 | '000109040000000260000036008400200100025070630001005009200350000089000000070802000', 647 | '000109702002630800000000050000000985035090670489000000070000000008016200203408000', 648 | '000130000009002400000000360084029053300501002520840690043000000002400900000015000', 649 | '000134000000080900208000003026000009800359002300000780700000805005010000000542000', 650 | '000140009000700430030006070070000500651080743004000090040900050013002000800064000', 651 | '000150062100000900300004008020300004407000803900008020200600009009000005530049000', 652 | '000160400000005902000002360050000618100000005298000030027300000809400000001029000', 653 | '000160904090000013000300870060000400079080250004000030038009000650000040901073000', 654 | '000170000090000034570002001300000920000208000024000003900700052760000040000024000', 655 | '000190007007600082400000900800010270000020000015080003003000006760005800100068000', 656 | '000190080000000009009800413864000000002050100000000347396005800400000000050036000', 657 | '000190870004000002700350000020000640009060300053000080000083005200000900078029000', 658 | '000198006903006000260000001005801007000070000600903800700000028000300509500687000', 659 | '000200000000049100600000028040002309032154870807900010710000003003470000000003000', 660 | '000200000003704050204900806041000703000000000507000680906007501010503400000009000', 661 | '000200003543000000009004160030052000006040800000160030057800300000000742600003000', 662 | '000200017000003200000010408200501006004000800300902004103020000002700000480009000', 663 | '000200040025060090000040605750820030800000002030059086207090000040070850080004000', 664 | '000200067045090002000061000006000075009147600420000100000310000500080730960005000', 665 | '000200079080040321000008400060003004300000008700800060004900000579080040810005000', 666 | '000200097010070600930100000090800025000000000180005070000002013003010060820004000', 667 | '000200300290000007763400008020030000008000400000040050900007836300000021006008000', 668 | '000203000064000103705000000020001600000726000008900050000000308902000460000107000', 669 | '000203001030409027000000000083000000270841093000000760000000000190602080600904000', 670 | '000203590820000000000900001070300480305407902014002070400005000000000034032108000', 671 | '000204700670000052002070100000047206000090000307860000003050600250000084006408000', 672 | '000205700705000040480000100900007000000020000000100006004000013010000802002609000', 673 | '000206010000008607500000009045060020008020100010040970100000005607300000050609000', 674 | '000207901040000030900040067000003008090476010300500000460010003080000070705304000', 675 | '000208000002040000600070015900000034030000080850000001710030009000080300000605000', 676 | '000209007002840005000060002060000530900050006013000040300010000200074900700302000', 677 | '000215000900800650010000007000050804000489000604020000500000090093002006000934000', 678 | '000218000000000000045670201607030005004020600200050903302049710000000000000162000', 679 | '000230500309580060050060090045000100100000004006000350090020010020097805008015000', 680 | '000240030020960107800000020760019000008000600000850071050000003603081090080094000', 681 | '000243081000600070000009003600000030073050260090000005700500000010006000860731000', 682 | '000248106900000000000000857020005003003000700700100040638000000000000009109673000', 683 | '000250803270008600000000000100002009040090020700500004000000000001800065806041000', 684 | '000270094000000003000004618050009100002040700007600030726300000400000000190028000', 685 | '000274090000300000300005100490000070850000062010000058006500007000002000020741000', 686 | '000275000030900870607000000405700000020010050000008203000000608043002090000597000', 687 | '000280090002000001305001000200008914400090005519300006000700509100000700090054000', 688 | '000280906000079040040500200500000000670000025000000003001003070080420000907061000', 689 | '000290370009300000000070008508000002070050060400000107100060000000003700063081000', 690 | '000290600000007940000003008050900021401030709980001050200600000098100000004079000', 691 | '000290700090000803500000029300076500000020000008350004280000007904000080003064000', 692 | '000300000000002065421900003936700080000000000040009356800007492690800000000003000', 693 | '000300000000050024002601503460000000030809040000000062701206900920010000000007000', 694 | '000300000000095604007200080030000008658000319900000070060007100204150000000004000', 695 | '000300000005800007849000050010050200600207005002030090050000978700008600000004000', 696 | '000300000041800900800000056020001008907000602100200030290000001005009270000006000', 697 | '000300000060045001103780000702000850090000010086000702000038904600910070000002000', 698 | '000300000065000070001070629009600001003958400600007800918040500030000210000003000', 699 | '000300000094000700500082000030070600780050034006010050000430002009000460000007000', 700 | '000300000200007000390006040001090620008000500059080700010200063000100009000003000', 701 | '000300000301050980580000004030040006000761000900020010700000029059070801000006000', 702 | '000300000902840000000020036006000027005090600820000400450070000000082304000005000', 703 | '000300001000508603007090408380000000000623000000000069708060100204805000600009000', 704 | '000300004046210080000000709680000200000192000009000047907000000060027950800004000', 705 | '000300006183000700000080002002058901600020008804970600300060000001000265500004000', 706 | '000300080000000320130000040010080407000517000903060010060000092094000000080001000', 707 | '000300094700040000064002300009000003005108200400000900001700860000080007280004000', 708 | '000300615000004230060000409004001060000829000050400700501000040047900000698003000', 709 | '000300807400020000009000600300400070605070901040009003001000700000060002904008000', 710 | '000302870285070000000009000010000004064090210900000030000800000000050621052907000', 711 | '000304502502000034030000000350048001006090300900630045000000050210000408809405000', 712 | '000305090074900000000001302007000038500294007160000400601400000000008670080603000', 713 | '000308000021004006007009405109000040400000008060000901703900100200100580000802000', 714 | '000308402001574000000000080008200070100687005030001800050000000000895700709106000', 715 | '000309100000005409000010038000000075070568090190000000360050000701900000009802000', 716 | '000310700401200080090000004000003001034060950600900000700000090050009103003085000', 717 | '000320000000050089001600000003000452040532090152000300000006200680070000000013000', 718 | '000320780007009001030000500105007800000050000003200605008000050600400300029013000', 719 | '000346900000001054300800001008004002070000080900700100800007009610200000005183000', 720 | '000350800593008000700000030850019000016000920000530081070000003000800249009061000', 721 | '000351760004600000000008050006700000210000086000006100040800000000003800082469000', 722 | '000370640000500002003002000020080010400090003010040050000400800500007000039021000', 723 | '000372600003000010005840020000004008080000040700600000030018500090000700002795000', 724 | '000375002000064000005000087350000000007493800000000036790000600000120000500746000', 725 | '000379000700006300003100006007000400350040018002000500100004800005800007000791000', 726 | '000382000000000100000570032060000074409030506820000090270046000001000000000823000', 727 | '000382460002500000000600075380000600490000052007000043740008000000006700028947000', 728 | '000390024002801006800000000750000000068030170000000032000000003600703400930046000', 729 | '000390070007020580100000009040000205075000310903000040300000001059030700020069000', 730 | '000398025200060087009000000406080000000209000000010802000000500170020006350976000', 731 | '000400000000000719009530800603000080750020043020000607005016300312000000000005000', 732 | '000400000046000970000007006007008263030070090264300700100800000023000480000001000', 733 | '000400000081095000402010000040068001070953040600140030000070908000580310000004000', 734 | '000400002056000070072965000001020000040000090000080100000832960020000480600001000', 735 | '000400007000000843200083050380000700005107400001000096090230004462000000800001000', 736 | '000400009034000750090730200002100090000849000010007400009078040073000180500004000', 737 | '000400017160050200000207800042001000900000005000700490005306000006070058480005000', 738 | '000400050510608000007000000709100400600080003001004702000000900000206087040001000', 739 | '000400060700065080004000700040100300500090001001008090002000800010930002090006000', 740 | '000400070006510020000927104403000000000801000000000402804759000020034800070008000', 741 | '000400095002901800000080100013005760200000008096800510008010000009304200530008000', 742 | '000400260000001008100000040400610020030040080090087004040000002600500000017009000', 743 | '000400300040000097800600000000790520700328001086045000000007006920000040001004000', 744 | '000400350000685000400000089703500100000010000004002907370000002000926000042007000', 745 | '000400500000029714700000062200040100000361000003090005530000009427980000009004000', 746 | '000400500089500061100600040000007803000386000803900000090004007740001290001005000', 747 | '000400930000030041040005000350001790600000008087200013000500020290060000036004000', 748 | '000408500000000014000020006570083040046209830030740095300070000420000000008302000', 749 | '000418900060390001900000040009080000052000190000050300030000004600035070005174000', 750 | '000437900000600340002000005700200410000703000021009003200000100013004000006198000', 751 | '000450000003007205700002080000000802007103600308000000090300008502700100000049000', 752 | '000450000570023000600000900000500140700010009012007000003000006000230058000075000', 753 | '000460010000008000080700064195000008002000100300000695930004070000900000060032000', 754 | '000460080007000010200700900000003460708246503064900000003009007020000100070054000', 755 | '000470310080051047000000002025036000000000000000290150200000000430520080058013000', 756 | '000490023000000000742600050507060090000000000090080207020001479000000000980043000', 757 | '000490500005803700090000000050600207100050003802009050000000040001207300006045000', 758 | '000490700000200060410600930000000650000807000025000000037006092050001000009082000', 759 | '000500000005002630069080000032050009078000120900070340000090870093600500000008000', 760 | '000500004200009560009100038050900000003401800000005040820003100076800009300007000', 761 | '000500014643000005000002900095003000038000450000900380006700000900000731570001000', 762 | '000500020000290608900004075000000039008000700610000000830900006201076000050008000', 763 | '000500049000007360070000000200870090760030018080015002000000030024700000890002000', 764 | '000500060600004238000000009000003600530000092004100000100000000298400001060002000', 765 | '000500070006010000080470610300000000095604130000000007052067040000040300060005000', 766 | '000500081200008070500007200000090000003205600000030000005100007090800004670004000', 767 | '000500200090000010500003804304100000700936002000004107901300006030000040005002000', 768 | '000500400050090003701600000210000080900030001080000064000001809100080040003002000', 769 | '000500806005083004700000000000002190260050078097800000000000009900160500108005000', 770 | '000500806070004300300900070800000000790080042000000005020005007007400060901006000', 771 | '000500964000000000000084005042091700003040200005260410500730000000000000381002000', 772 | '000503001701060200000000630007002009200709003900800400072000000008020904400601000', 773 | '000503941910600300000009680050800006000000000200001090095400000007006054462308000', 774 | '000504002030207400000061900000000704002609500108000000005920000003405080900106000', 775 | '000507000541000006039000000250600004064000130100004085000000410300000268000302000', 776 | '000510700009080605000047030000000308081000470703000000020360000607050900004079000', 777 | '000519020009240800000000049600000700500020003007000001370000000005087400040152000', 778 | '000520070008000000027009130102706090000000000030401208019300780000000900080057000', 779 | '000520308324000005000400000270000050001060400030000096000005000800000179603097000', 780 | '000520684070100005005089000090000150500000002026000070000470200900005040764092000', 781 | '000530000000000040358001002090000208027908510503000090900300851030000000000016000', 782 | '000530004001640950000000002870004200000000000004100093700000000029083700400015000', 783 | '000530400000000082500004310000040098007060100280050000054700006390000000001093000', 784 | '000536400000800020380200010007000004400090008100000900020001046060004000001965000', 785 | '000540037400000000839000000004005780600000004083400600000000971000000008150067000', 786 | '000548021800000000040920000085000006760000092900000380000034060000000008130865000', 787 | '000570040504000800900008050300004190000000000048200007020600005009000601010093000', 788 | '000573000090020008030900000610000970400050006025000034000005080300010090000639000', 789 | '000578000000000003020034750086002035002000800910800670073260010200000000000481000', 790 | '000580073050000200004603900003007000070408020000200700001804600006000010940016000', 791 | '000583000049000003108000000000600008490358017300004000000000905200000480000817000', 792 | '000590620000000005000408097302000000005941200000000501240107000800000000037029000', 793 | '000600000002009017490001560049700000000508000000003620051800096380900400000005000', 794 | '000600000100000500940075010000000069800509001320000000010240073003000002000008000', 795 | '000600000400003095750004030380070041000000000510020073070800019120300004000005000', 796 | '000600004028047000300800056003000090060704010040000500730008001000370840400006000', 797 | '000600004040783000002004009070000010001348900090000040200400300000539080700001000', 798 | '000600005005048000401000800008002096903050104540900200009000607000520900300009000', 799 | '000600009000001200601005040000080900047916580009020000010800307005700000800004000', 800 | '000600030034008602700000000800109246000000000621403005000000003206300150080007000', 801 | '000600034000100985704050600542000006000000000600000321005010403417009000230005000', 802 | '000600040000010200086200510578030000900000001000070935063007890009060000020001000', 803 | '000600070007010005000230690904000100080000040003000902049051000300060200060008000', 804 | '000600241000024069040000000000005030790060058030900000000000010460780000587003000', 805 | '000600304600000010017200900003070040800000001070090800009005170020000008108009000', 806 | '000600900000080200506007003700000080208040706030000001100200309003060000007004000', 807 | '000602340000000061000301702290006450000000000058400026805904000410000000062108000', 808 | '000609070000030064000000800012060408050708030803090720001000000920050000070806000', 809 | '000609358086003010000000000043200000008040500000005890000000000030900280792501000', 810 | '000610050060000109530004000470500000000030000000008027000900014206000070010053000', 811 | '000620010010304500006009040800000150001000700025000004030400900002106080040093000', 812 | '000620910500040200000801003400000700009507800007000001600208000003060002048053000', 813 | '000630000000400370480010600041000000230158046000000120006040093025003000000072000', 814 | '000630009003409120000000860000067400080040050004820000056000000038706200100082000', 815 | '000650003100038700080000960001000050003020400070000600016000070008570002700084000', 816 | '000680020000500807802040100000006900081000370006100000004070201108002000070013000', 817 | '000680093600000700592000600000900006065070210300005000004000137009000005170054000', 818 | '000687420000000009470000800608001000090248010000300508007000051500000000016825000', 819 | '000692000009000006100005030096000800204030107003000260030400001400000600000261000', 820 | '000697001300000586000050007001720090000000000040061800100030000537000009900276000', 821 | '000700000005000049204500006001007005407109203900200100700001802380000600000008000', 822 | '000700000173060000400093000005800019008010400390002700000120008000070962000006000', 823 | '000700001000026009200000740000170090018203450090048000056000008100860000300002000', 824 | '000700004600000000004213050003070008080549020500020700090487300000000005400001000', 825 | '000700006026000059100000000300041060049306510070250003000000004930000680700003000', 826 | '000700021003106900080000000072008000008000700000400650000000060009802400310009000', 827 | '000700030603400000040006500006007200700030005009200100008100040000004701070005000', 828 | '000700340000002007000008091038900054700000009420005670160300000300200000097001000', 829 | '000700450004000028000002307060370000007268100000014070201900000730000200059006000', 830 | '000700500084020060200000008000601940000000000027309000700000005040090310002008000', 831 | '000700600000001020000200301630090015010030070580010039304005000050300000001004000', 832 | '000702000000000034460009000080070005390010042500030010000100067950000000000405000', 833 | '000702930306051000000030007000000614000000000691000000800060000000320708035807000', 834 | '000704080000010905086059000000000642000431000849000000000190570605020000070506000', 835 | '000704200720106008000000007500200060001070900090001002600000000300609054009502000', 836 | '000705600005010090032000008051090000400000005000060340500000920020050700009603000', 837 | '000710000420000090006000003504031200010070080003250401900000700030000046000026000', 838 | '000715300000260010008090000020000560603000901089000030000080100030051000006347000', 839 | '000728300000000002000060597963004200500000003002500946218040000300000000009216000', 840 | '000730100090600400000009007080000691000000000357000020800900000002003050006018000', 841 | '000730405060500308000000000000000903230010047604000000000000000401003080506042000', 842 | '000745600000008100000000095100803047000000000620104003850000000007400000002657000', 843 | '000746800000000050004000007100007400690428015007900002800000500020000000005692000', 844 | '000750104900008000000006005020690000170000039000037020700800000000500001408069000', 845 | '000754210000100008000060400050000370780000061046000020001040000900001000074536000', 846 | '000760010905300000006090008360000700100000009009000041700040100000002804090051000', 847 | '000780050000000073002500008000048100840671092006290000500007900960000000020064000', 848 | '000790030200008905000000270040620000500000009000085060094000000102400008080031000', 849 | '000800000020005790980400006004060215000000000138050900800003059073500080000004000', 850 | '000800000270064000000003081100009060907010802080200004350700000000630048000001000', 851 | '000800000874600000006014070000000159080090030269000000010580700000001985000006000', 852 | '000800005500040090273000000000020780600703009097010000000000432010030008800006000', 853 | '000800010700093200000002900030000802200904003801000050004600000003410006010005000', 854 | '000800014000024307400000200200068000180050076000190003001000009304980000850001000', 855 | '000800020000006300015070000000008907038794260702600000000020630006400000040009000', 856 | '000800024206000190010000007000520700020701040008069000500000010039000402840007000', 857 | '000800030629501000800000506001000000083040260000000400308000005000706349040005000', 858 | '000800340000000008300025000002040037800902004130060800000210009600000000081004000', 859 | '000800407000200060300006000430000605067030280209000014000400008090001000601005000', 860 | '000800760000003800060072054035000000007090600000000580790250010001900000086007000', 861 | '000800769900200000001000800000000475040598010516000000003000900000005007128007000', 862 | '000801500300500000050070090200000084004237900960000003020060070000008005001709000', 863 | '000802000502000069730000000005008940070060080069400500000000097620000403000703000', 864 | '000802005080300200013000740030200900000080000004005080079000450001004090400706000', 865 | '000804032400000005005600001100000700000162000006000003700005300300000004510203000', 866 | '000804530000730802000050090006000300930000065004000200050040000403082000027903000', 867 | '000805040003070065040003008005700800100000006004006900400900010930010500060508000', 868 | '000806000000050090030000065004078900008000700003240100620000040010090000000604000', 869 | '000806074014090002007200900500000040040080050030000009005003800100020690290105000', 870 | '000807000243090000000000003650003200309020108002600034400000000000040356000702000', 871 | ]; 872 | 873 | function randomIntFromInterval(min, max) { 874 | return Math.floor(Math.random() * (max - min + 1) + min); 875 | } 876 | 877 | function getRamdomBoardFor(array) { 878 | var idx = randomIntFromInterval(0, array.length - 1); 879 | return array[idx]; 880 | } 881 | 882 | var Boards = { 883 | randomBoard: function(difficulty) { 884 | switch (difficulty) { 885 | case 'easy': 886 | return getRamdomBoardFor(easy); 887 | case 'medium': 888 | return getRamdomBoardFor(medium); 889 | case 'hard': 890 | return getRamdomBoardFor(hard); 891 | } 892 | } 893 | } 894 | 895 | module.exports = Boards; 896 | -------------------------------------------------------------------------------- /js/game.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var Store = require('./store'); 3 | var Sudoku = require('./sudoku'); 4 | var Boards = require('./boards'); 5 | import {Link} from 'react-router'; 6 | 7 | class Cell extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | this.onClick = this.onClick.bind(this); 12 | this.onChange = this.onChange.bind(this); 13 | } 14 | 15 | shouldComponentUpdate(newProps, newState) { 16 | var oldCell = this.props.cell; 17 | var newCell = newProps.cell; 18 | return ( 19 | oldCell.value !== newCell.value || 20 | oldCell.editable !== newCell.editable || 21 | oldCell.hasConflict !== newCell.hasConflict 22 | ); 23 | } 24 | 25 | render() { 26 | var cell = this.props.cell; 27 | 28 | var classes = []; 29 | classes.push('i'+cell.i); 30 | classes.push('j'+cell.j); 31 | classes.push(cell.editable ? 'editable' : 'not-editable'); 32 | classes.push(cell.hasConflict ? 'has-conflict' : 'no-conflict'); 33 | 34 | return ( 35 | 36 | 41 | 42 | ); 43 | } 44 | 45 | onClick(event) { 46 | event.preventDefault(); 47 | if (this.props.cell.editable) { 48 | event.target.select(); 49 | } else { 50 | event.target.blur(); 51 | } 52 | } 53 | 54 | onChange(event) { 55 | event.preventDefault(); 56 | var cell = this.props.cell; 57 | if (!cell.editable) { 58 | return; 59 | } 60 | var newValue = event.target.value; 61 | if (newValue !== '' && !/^[1-9]$/.test(newValue)) { 62 | event.target.value = cell.value; 63 | return; 64 | } 65 | Store.dispatch({ 66 | type: 'CHANGE_VALUE', 67 | i: cell.i, 68 | j: cell.j, 69 | value: newValue === '' ? null : parseInt(newValue) 70 | }); 71 | } 72 | } 73 | 74 | function GithubCorner() { 75 | return ( 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ); 84 | } 85 | 86 | class Controls extends React.Component { 87 | constructor(props) { 88 | super(props); 89 | this.state = Store.getState(); 90 | } 91 | 92 | componentDidMount() { 93 | var self = this; 94 | self.unsubscribe = Store.subscribe(function() { 95 | self.setState(Store.getState()); 96 | }); 97 | } 98 | 99 | componentWillUnmount() { 100 | this.unsubscribe(); 101 | } 102 | 103 | render() { 104 | var time = this.state.game.time; 105 | function f(num) { 106 | if (num < 10) { 107 | return '0'+num; 108 | } else { 109 | return ''+num; 110 | } 111 | } 112 | return ( 113 |
114 |

Back

115 | {Sudoku.isComplete(this.state.game.cells) 116 | ?

Congratulations!

117 | :

{f(time.getHours())+':'+f(time.getMinutes())+':'+f(time.getSeconds())}

} 118 |
119 | ) 120 | } 121 | } 122 | 123 | class DifficultyDialog extends React.Component { 124 | shouldComponentUpdate(newProps, newState) { 125 | return false; 126 | } 127 | 128 | constructor(props) { 129 | super(props); 130 | this.state = Store.getState(); 131 | 132 | this.difficultyClick = this.difficultyClick.bind(this); 133 | } 134 | 135 | componentDidMount() { 136 | var self = this; 137 | self.unsubscribe = Store.subscribe(function() { 138 | self.setState(Store.getState()); 139 | }); 140 | } 141 | 142 | componentWillUnmount() { 143 | this.unsubscribe(); 144 | } 145 | 146 | render() { 147 | return ( 148 |
149 | ✕ 150 |

Please, choose the difficulty:

151 | 152 | 153 | 154 |
155 | ); 156 | } 157 | 158 | difficultyClick(event) { 159 | event.preventDefault(); 160 | var difficulty = event.target.getAttribute('data-difficulty'); 161 | Store.dispatch({type: 'NEW_GAME', difficulty}); 162 | location.hash = 'play'; 163 | } 164 | } 165 | 166 | class Game extends React.Component { 167 | constructor(props) { 168 | super(props); 169 | this.state = Store.getState(); 170 | } 171 | 172 | componentDidMount() { 173 | var self = this; 174 | this.unsubscribe = Store.subscribe(function() { 175 | self.setState(Store.getState()); 176 | }); 177 | 178 | this.addSecond = setInterval(function() { 179 | Store.dispatch({type: 'ADD_SECOND'}); 180 | }, 1000); 181 | } 182 | 183 | componentWillUnmount() { 184 | clearInterval(this.addSecond); 185 | this.unsubscribe(); 186 | } 187 | 188 | render() { 189 | if (typeof localStorage.currentGame === 'undefined') { 190 | location.hash = '/'; 191 | return
; 192 | } 193 | 194 | return ( 195 |
196 | 197 | 198 | {this.state.game.cells.map(function(line, i) { 199 | return ( 200 | 201 | {line.map(function(cell) { 202 | return ; 203 | })} 204 | 205 | ); 206 | })} 207 | 208 |
209 | 210 | 211 |
212 | ); 213 | } 214 | } 215 | 216 | class Index extends React.Component { 217 | render() { 218 | return ( 219 |
220 |

Sudoku

221 |

Start a new game

222 | {this.hasExistingGame() 223 | ?

or resume the existing one

224 | : null} 225 |

The code of this game is on  226 | GitHub

227 |
228 | ); 229 | } 230 | 231 | hasExistingGame() { 232 | return (typeof localStorage.currentGame !== 'undefined'); 233 | } 234 | } 235 | 236 | function App(props) { 237 | return ( 238 |
239 | {props.children} 240 | 241 |
242 | ); 243 | } 244 | 245 | module.exports = {App, DifficultyDialog, Game, Index}; 246 | -------------------------------------------------------------------------------- /js/index.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | import {render} from 'react-dom'; 3 | var Store = require('./store'); 4 | var Game = require('./game'); 5 | import {Router, Route, IndexRoute, hashHistory} from 'react-router'; 6 | 7 | if (localStorage.currentGame) { 8 | Store.dispatch({type: 'RESUME_GAME'}); 9 | } 10 | 11 | render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | , document.getElementById('app')); 20 | -------------------------------------------------------------------------------- /js/store.js: -------------------------------------------------------------------------------- 1 | var Redux = require('redux'); 2 | var Boards = require('./boards'); 3 | var Sudoku = require('./sudoku'); 4 | var cloneDeep = require('lodash.clonedeep'); 5 | 6 | var Store = Redux.createStore(function(state, action) { 7 | if (!state) { 8 | state = {}; 9 | } else { 10 | state = cloneDeep(state); 11 | } 12 | switch (action.type) { 13 | case 'RESUME_GAME': 14 | state.game = JSON.parse(localStorage.currentGame); 15 | state.game.time = new Date(state.game.time); 16 | break; 17 | case 'NEW_GAME': 18 | state.game = Sudoku.boardToGame(Boards.randomBoard(action.difficulty)); 19 | break; 20 | case 'CHANGE_VALUE': 21 | state.game.cells[action.i][action.j].value = action.value; 22 | break; 23 | case 'ADD_SECOND': 24 | if (state.game) { 25 | state.game.time.setSeconds(state.game.time.getSeconds() + 1); 26 | } 27 | break; 28 | } 29 | if (state.game) { 30 | Sudoku.checkConflicts(state.game.cells); 31 | localStorage.currentGame = JSON.stringify(state.game); 32 | } 33 | return state; 34 | }); 35 | 36 | module.exports = Store; 37 | -------------------------------------------------------------------------------- /js/sudoku.jsx: -------------------------------------------------------------------------------- 1 | var chunk = require('lodash.chunk'); 2 | 3 | function newCell(i, j, value, editable) { 4 | return { 5 | value, 6 | editable, 7 | hasConflict: false, 8 | i, 9 | j 10 | } 11 | } 12 | 13 | function newGame(cells, time) { 14 | return { 15 | cells, 16 | time: time || new Date(0, 0, 0, 0, 0, 0, 0) 17 | } 18 | } 19 | 20 | function markAllWithoutConflict(cells) { 21 | for (var i = 0; i < 9; i++) { 22 | for (var j = 0; j < 9; j++) { 23 | cells[i][j].hasConflict = false; 24 | } 25 | } 26 | } 27 | 28 | function checkSubset(array) { 29 | var nums = {}; 30 | for (var i = 0; i < 9; i++) { 31 | if (array[i].value !== null && nums.hasOwnProperty(array[i].value)) { 32 | array[i].hasConflict = true; 33 | array[nums[array[i].value]].hasConflict = true; 34 | } 35 | nums[array[i].value] = i; 36 | } 37 | } 38 | 39 | function checkConflicts(cells) { 40 | markAllWithoutConflict(cells); 41 | 42 | // check horizontal lines 43 | for (var i = 0; i < 9; i++) { 44 | var arr = []; 45 | for (var j = 0; j < 9; j++) { 46 | arr.push(cells[i][j]); 47 | } 48 | checkSubset(arr); 49 | } 50 | 51 | // check vertical lines 52 | for (var j = 0; j < 9; j++) { 53 | var arr = []; 54 | for (var i = 0; i < 9; i++) { 55 | arr.push(cells[i][j]); 56 | } 57 | checkSubset(arr); 58 | } 59 | 60 | // check squares 61 | var c = cells; 62 | checkSubset([c[0][0], c[0][1], c[0][2], c[1][0], c[1][1], c[1][2], c[2][0], c[2][1], c[2][2]]); 63 | checkSubset([c[3][0], c[3][1], c[3][2], c[4][0], c[4][1], c[4][2], c[5][0], c[5][1], c[5][2]]); 64 | checkSubset([c[6][0], c[6][1], c[6][2], c[7][0], c[7][1], c[7][2], c[8][0], c[8][1], c[8][2]]); 65 | 66 | checkSubset([c[0][3], c[0][4], c[0][5], c[1][3], c[1][4], c[1][5], c[2][3], c[2][4], c[2][5]]); 67 | checkSubset([c[3][3], c[3][4], c[3][5], c[4][3], c[4][4], c[4][5], c[5][3], c[5][4], c[5][5]]); 68 | checkSubset([c[6][3], c[6][4], c[6][5], c[7][3], c[7][4], c[7][5], c[8][3], c[8][4], c[8][5]]); 69 | 70 | checkSubset([c[0][6], c[0][7], c[0][8], c[1][6], c[1][7], c[1][8], c[2][6], c[2][7], c[2][8]]); 71 | checkSubset([c[3][6], c[3][7], c[3][8], c[4][6], c[4][7], c[4][8], c[5][6], c[5][7], c[5][8]]); 72 | checkSubset([c[6][6], c[6][7], c[6][8], c[7][6], c[7][7], c[7][8], c[8][6], c[8][7], c[8][8]]); 73 | } 74 | 75 | // checkConflicts must run first 76 | function isComplete(cells) { 77 | for (var i = 0; i < 9; i++) { 78 | for (var j = 0; j < 9; j++) { 79 | var cell = cells[i][j]; 80 | if (cell.hasConflict || cell.value === null) { 81 | return false; 82 | } 83 | } 84 | } 85 | return true; 86 | } 87 | 88 | function boardToGame(board) { 89 | var array = []; 90 | for (var i = 0; i < 81; i++) { 91 | if (board[i] === '0') { 92 | array.push(null); 93 | } else { 94 | array.push(parseInt(board[i])); 95 | } 96 | } 97 | array = chunk(array, 9); 98 | 99 | var game = [] 100 | for (var i = 0; i < 9; i++) { 101 | var line = []; 102 | for (var j = 0; j < 9; j++) { 103 | line.push(newCell(i, j, array[i][j], array[i][j] === null)); 104 | } 105 | game.push(line); 106 | } 107 | return newGame(game, null); 108 | } 109 | 110 | var Sudoku = { 111 | newGame, 112 | newCell, 113 | checkConflicts, 114 | isComplete, 115 | boardToGame 116 | } 117 | 118 | module.exports = Sudoku; 119 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sudoku", 3 | "version": "0.0.0", 4 | "description": "A simple sudoku game", 5 | "main": "bundle.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "buildjs": "webpack", 9 | "buildcss": "lessc --clean-css ./css/main.less bundle.css" 10 | }, 11 | "author": { 12 | "name": "Andrey Nering", 13 | "email": "andrey@nering.com.br", 14 | "url": "https://andrey.nering.com.br" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/andreynering/sudoku.git" 19 | }, 20 | "homepage": "https://sudoku.js.org", 21 | "license": "MIT", 22 | "dependencies": { 23 | "babel-preset-react": "^6.5.0", 24 | "jsx-loader": "^0.13.2", 25 | "lodash.chunk": "^4.0.0", 26 | "lodash.clonedeep": "^4.0.1", 27 | "react": "^0.14.3", 28 | "react-dom": "^0.14.3", 29 | "react-router": "^2.0.0-rc5", 30 | "redux": "^3.0.5", 31 | "webpack": "^1.12.9", 32 | "babel-core": "^6.7.4", 33 | "babel-loader": "^6.2.4", 34 | "babel-preset-es2015": "^6.6.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | entry: "./js/index.jsx", 5 | output: { 6 | path: __dirname, 7 | filename: "bundle.js" 8 | }, 9 | module: { 10 | loaders: [ 11 | { test: /\.css$/, loader: "style!css" }, 12 | // tell webpack to use jsx-loader for all *.jsx files 13 | // { test: /\.jsx$/, loader: 'jsx-loader?insertPragma=React.DOM&harmony' }, 14 | { test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader" } 15 | ] 16 | }, 17 | resolve: { 18 | extensions: ['', '.js', '.jsx'] 19 | }, 20 | plugins: [ 21 | new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}}), 22 | new webpack.optimize.OccurenceOrderPlugin(), 23 | new webpack.optimize.DedupePlugin() 24 | ] 25 | }; 26 | --------------------------------------------------------------------------------