之前学习目标写的一个数独游戏,用jquery模块模式、mvc模式实现的。
1. controller.sudoku.js
// Controller Sudoku.js(function ($) { $(function () { 'use strict'; // Get filled numbers from html tables var getTableNums = function () { var inputArr = [[], [], [], [], [], [], [], [], []]; var allowNums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; $('.sudoku_cell').each(function () { var data = $(this).data('val').split('-'); var val = $(this).val(); val = (val === '') ? null : parseInt(val); if (val !== null && allowNums.indexOf(val) === -1) { alert('Number allowed only between 0-9'); return null; } var r = parseInt(data[0]); var c = parseInt(data[1]); inputArr[r][c] = val; }); return inputArr; }; // Fill numbers to html tables var assignTableNums = function (solution) { $('.sudoku_cell').each(function () { var data = $(this).data('val').split('-'); var r = parseInt(data[0]); var c = parseInt(data[1]); $(this).val(solution[r][c]); }); }; // Reset $('#sudoku-reset-btn').click(function () { $('.sudoku_cell').val(null); }); // Start $('#sudoku-start-btn').click(function () { // Get numbers from HTML var inputArr = getTableNums(); if(inputArr === null) return; // Call module Sudoku var sudoku = new SOLEIL.Sudoku(inputArr); var solution = sudoku.Go(); if(solution === null) return; // Assign data to HTML assignTableNums(solution); }); // Examples data $('#sudoku-exp-btn').click(function () { // random number var min = Math.ceil(0); var max = Math.floor(1); var num = Math.floor(Math.random() * (max - min + 1)) + min; var inputArr = [ [ [null, 7, 6, null, 1, null, null, 4, 3], [null, null, null, 7, null, 2, 9, null, null], [null, 9, null, null, null, 6, null, null, null], [null, null, null, null, 6, 3, 2, null, 4], [4, 6, null, null, null, null, null, 1, 9], [1, null, 5, 4, 2, null, null, null, null], [null, null, null, 2, null, null, null, 9, null], [null, null, 4, 8, null, 7, null, null, 1], [9, 1, null, null, 5, null, 7, 2, null] ], [ [1, null, null, null, 3, null, 5, 9, null], [3, null, null, 5, null, null, null, 2, null], [null, 5, null, 9, null, 2, 6, 3, 8], [4, 3, null, null, null, null, null, null, null], [null, null, null, 6, null, 1, null, null, null], [null, null, null, null, null, null, null, 8, 7], [6, 4, 7, 3, null, 8, null, 5, null], [null, 1, null, null, null, 5, null, null, 9], [null, 9, 2, null, 7, null, null, null, 3] ] ]; // Assign data to HTML assignTableNums(inputArr[num]); }); })})(jQuery);
2. module.sudoku.js
// Module Sudoku .jsSOLEIL.Sudoku = function (inputArr) { "use strict"; // private var possiArr = []; /** * Remove an element form array * @param {Array} arr * @param elem * @returns {*} */ var removeElem = function (arr, elem) { var index = arr.indexOf(elem); if (index > -1) { arr.splice(index, 1); } return arr; }; /** * Return sum of filled numbers * @returns {number} */ var totalResult = function () { var total = 0; for (var i = 0; i < inputArr.length; i++) { for (var j = 0; j < inputArr[i].length; j++) { if (inputArr[i][j] !== null) { total++; } } } return total; }; /** * Create a shadow array to assist calculating */ var fillPossi = function () { for (var r = 0; r < inputArr.length; r++) { possiArr[r] = []; for (var c = 0; c < inputArr[r].length; c++) { possiArr[r][c] = (inputArr[r][c] === null) ? [1, 2, 3, 4, 5, 6, 7, 8, 9] : null; } } }; /** * Search possibilities of sudoku */ var searchPossi = function () { var rr, cc, r, c, blocR, blocC; for (r = 0; r < possiArr.length; r++) { for (c = 0; c < possiArr[r].length; c++) { if (possiArr[r][c] === null) { // row 1x9 for (cc = 0; cc < possiArr[r].length; cc++) { if (possiArr[r][cc] !== null) { // cell to resolve possiArr[r][cc] = removeElem(possiArr[r][cc], inputArr[r][c]); } } // column 9x1 for (rr = 0; rr < possiArr.length; rr++) { if (possiArr[rr][c] !== null) { // cell to resolve possiArr[rr][c] = removeElem(possiArr[rr][c], inputArr[r][c]); } } // block 3x3 blocR = Math.floor(r / 3); blocC = Math.floor(c / 3); for (rr = 3 * blocR; rr < 3 * (blocR + 1); rr++) { for (cc = 3 * blocC; cc < 3 * (blocC + 1); cc++) { if (rr !== r && cc !== c && possiArr[rr][cc] !== null) { // cell to resolve possiArr[rr][cc] = removeElem(possiArr[rr][cc], inputArr[r][c]); } } } } } } }; /** * Find the unique answer for one cell * @returns {boolean} */ var fillResult = function () { var r, c, found = false; for (r = 0; r < possiArr.length; r++) { for (c = 0; c < possiArr[r].length; c++) { if (possiArr[r][c] !== null && possiArr[r][c].length === 1) { // unique answer found = true; inputArr[r][c] = possiArr[r][c][0]; possiArr[r][c] = null; } } } return found; }; // public return { Go: function () { // Init an show array to calculate possibilities fillPossi(); // Recursive to find unique number while (totalResult() < 81) { searchPossi(); if (fillResult() === false) { alert('No found result'); inputArr = null; break; } } return inputArr; } };};
3. tpl.sudoku.html
<div class="sudoku table-responsive"> <table class="table table-bordered"> <?php for ($row = 0; $row < 9; $row++) { echo '<tr>'; for ($col = 0; $col < 9; $col++) { // Border style $styleTD = ''; if ($row === 0) { $styleTD .= 'border-top: 1px solid #000;'; } if ($row % 3 === 2) { $styleTD .= 'border-bottom: 1px solid #000;'; } if ($col === 0) { $styleTD .= 'border-left: 1px solid #000;'; } if ($col % 3 === 2) { $styleTD .= 'border-right: 1px solid #000;'; } echo '<td style="' . $styleTD . '"">'; echo '<input type="text" maxlength="1" data-val="' . $row . '-' . $col . '" class="sudoku_cell" autocomplete="false" />'; echo '</td>'; } echo '</tr>'; } ?> </table> <button id="sudoku-reset-btn" class="btn btn-danger">Reset</button> <button id="sudoku-start-btn" class="btn btn-success">Search solution</button> <button id="sudoku-exp-btn" class="btn btn-info">Generate sudoku</button></div>