window.onerror = function(){return true}; /** /// Constants /// */ var SUDOKU_SCRIPT = "/script/getsudoku.php"; // where to get sudokus?? var SUDOKU_PREFIX = "_sudoku"; // div id prefix var DEFAULT_RATING = "easy"; // default rating var WAIT_INTERVAL = 100; // time to wait for mutex in microseconds /** COLORS */ var FIELD_SIZE = 24; // number fields will be FIELD_SIZE x FIELD_SIZE pixels var FIELD_COLOR = "#f0f0f0"; // background color of fields without hints var FIELD_COLOR_FOCUS = "#cccccc"; var FIELD_COLOR_HINTS = "#9bd5e6"; // background color of fields with hints var FIELD_COLOR_HINTS_FOCUS = "#adc0f0"; var FIELD_COLOR_ERROR = "#ff9999"; // background color of fields in errorzone var FIELD_COLOR_ERROR_FOCUS = "#e87474"; var FIELD_COLOR_ERROR_LOCKED = "#ff0000"; // background color of locked fields in errorzone var FIELD_COLOR_ERROR_LOCKED_FOCUS = "#ea0000"; var FONT_SIZE = 17; // font size in fields var SECTION_SIZE = 4; // space between sections (3x3) var LOADING_TIMEOUT = 10000; // how long to wait before asuming timeout var LOADING_CODE = // code to display when loading sudoku '
loading..
'; var ERROR_CODE = // code to display when an error occures '
an error occured!
click here to refresh the webpage.
'; var ERROR_AJAX = // no ajax! :( '
Your browser is too old for this sudoku game :(
Please upgrade your browser and come back.
'; var ERROR_DB = '
we are currently updating the sudoku database..
please check back later :)
'; var RATING_EASY = 'Easy'; var RATING_MEDIUM = 'Medium'; var RATING_HARD = 'Hard'; var RATING_EVIL = 'Evil'; var ERROR_X = 0; var ERROR_Y = 1; var ERROR_B = 2; // MOVEMENT var KEY_UP = 38; var KEY_DOWN = 40; var KEY_LEFT = 37; var KEY_RIGHT = 39; /** /// Globals /// */ var hasBoard = false; var boardHTML = ""; var isDownloading = false; var sudokuId = ""; var sudokuString = ""; var sudokuSolved = ""; var sudokuRating = ""; var sudokuPerm = ""; var sudokuBoard = new Array(9); var sudokuLocked = new Array(9); var sudokuBlock = new Array(9); var sudokuError = new Array(3); // does the row, column or block contain an error? var ajaxLoading = false; var CURRENT_X = -1; var CURRENT_Y = -1; /** /// Convenient Functions /// */ function CurrencyFormatted(amount) { var i = parseInt(amount); t = ''+amount; output = (t.substr(t.length-3)); i = Math.floor(i/1000); while(i > 1000) { t = ''+i; output = (t.substr(t.length-3)) + '.' + output; i = Math.floor(i/1000); } if (i > 0) { output = i + '.' + output; } return output; } function getElement(id) { return document.getElementById(id); } function setElement(id, str) { getElement(id).innerHTML = str; } function setValue(id, val) { getElement(id).value = val; } function checkLock(elem) { var v = elem.id; var x = v.charAt(7); var y = v.charAt(8); if (sudokuLocked[x][y]) { elem.blur(); } } /** extern */ function openwindow() { window.open("http://sudokus2go.com/showsudoku.php?id=" + sudokuId, "_sudoku"); } function printsudoku() { window.open("http://sudokus2go.com/printsudoku.php?id=" + sudokuId, "_printsudoku"); } /** check for sudoku logic */ function checkLogic(checkx, checky) { /** check x */ var solved = true; var error = false; var numbers = new Array(9); for (var x = 0; x < 10; x++) { numbers[x] = false; } for (var x = 0; x < 9; x++) { var n = sudokuBoard[x][checky]; if (n > 0) { if (numbers[n]) { error = true; break; } numbers[n] = true; if (!(sudokuError[ERROR_B][ sudokuBlock[x][checky] ] || sudokuError[ERROR_Y][ x ])) { if (sudokuLocked[x][checky]) { getElement(SUDOKU_PREFIX + x + checky).style.background = FIELD_COLOR_HINTS; } else { getElement(SUDOKU_PREFIX + x + checky).style.background = FIELD_COLOR; } } } else { solved = false; if (!sudokuError[ERROR_B][ sudokuBlock[x][checky] ] && !sudokuError[ERROR_Y][ x ]) { getElement(SUDOKU_PREFIX + x + checky).style.background = FIELD_COLOR; } } } sudokuError[ERROR_X][checky] = error; if (error) { solved = false; for (var x = 0; x < 9; x++) { if (sudokuLocked[x][checky]) { getElement(SUDOKU_PREFIX + x + checky).style.background = FIELD_COLOR_ERROR_LOCKED; } else { getElement(SUDOKU_PREFIX + x + checky).style.background = FIELD_COLOR_ERROR; } } } /** check y */ error = false; for (var y = 0; y < 10; y++) { numbers[y] = false; } for (var y = 0; y < 9; y++) { var n = sudokuBoard[checkx][y]; if (n > 0) { if (numbers[n]) { error = true; break; } numbers[n] = true; if (!(sudokuError[ERROR_B][ sudokuBlock[checkx][y] ] || sudokuError[ERROR_X][ y ])) { if (sudokuLocked[checkx][y]) { getElement(SUDOKU_PREFIX + checkx + y).style.background = FIELD_COLOR_HINTS; } else { getElement(SUDOKU_PREFIX + checkx + y).style.background = FIELD_COLOR; } } } else { solved = false; if (!(sudokuError[ERROR_B][ sudokuBlock[checkx][y] ] || sudokuError[ERROR_X][ y ])) { getElement(SUDOKU_PREFIX + checkx + y).style.background = FIELD_COLOR; } } } sudokuError[ERROR_Y][checkx] = error; if (error) { solved = false; for (var y = 0; y < 9; y++) { if (sudokuLocked[checkx][y]) { getElement(SUDOKU_PREFIX + checkx + y).style.background = FIELD_COLOR_ERROR_LOCKED; } else { getElement(SUDOKU_PREFIX + checkx + y).style.background = FIELD_COLOR_ERROR; } } } /** check block */ error = false; var blockx = Math.floor(checkx / 3) * 3; var blocky = Math.floor(checky / 3) * 3; var breaking = false; for (var y = 0; y < 10; y++) { numbers[y] = false; } for (var y = 0; y < 3; y++) { var thisy = blocky + y; for (var x = 0; x < 3; x++) { var thisx = blockx + x; var n = sudokuBoard[thisx][thisy]; if (n > 0) { if (numbers[n]) { error = true; breaking = true; break; } numbers[n] = true; if (!(sudokuError[ERROR_X][ thisy ] || sudokuError[ERROR_Y][ thisx ])) { if (sudokuLocked[thisx][thisy]) { getElement(SUDOKU_PREFIX + thisx + thisy).style.background = FIELD_COLOR_HINTS; } else { getElement(SUDOKU_PREFIX + thisx + thisy).style.background = FIELD_COLOR; } } } else { solved = false; if (!(sudokuError[ERROR_X][ thisy ] || sudokuError[ERROR_Y][ thisx ])) { getElement(SUDOKU_PREFIX + thisx + thisy).style.background = FIELD_COLOR; } } } if (breaking) { break; } } var blockn = sudokuBlock[blockx][blocky]; sudokuError[ERROR_B][blockn] = error; if (error) { solved = false; for (var y = 0; y < 3; y++) { var thisy = blocky + y; for (var x = 0; x < 3; x++) { var thisx = blockx + x; if (sudokuLocked[thisx][thisy]) { getElement(SUDOKU_PREFIX + thisx + thisy).style.background = FIELD_COLOR_ERROR_LOCKED; } else { getElement(SUDOKU_PREFIX + thisx + thisy).style.background = FIELD_COLOR_ERROR; } } } } if (solved) { var really_solved = true; for(var x = 0; x < 9; x++) { for(var y = 0; y < 9; y++) { if(sudokuBoard[x][y] == 0) { really_solved = false; break; } } } if(really_solved) { alert('Congratulations! You solved the Sudoku! :)'); } } } /** /// Sudoku Functions /// */ /** get sudoku */ function loadSudokuRandomExt(rating, symmetric) { if (rating == null) { rating = DEFAULT_RATING; } if (symmetric == null) { symmetric = (Math.random() * 2 < 1) ? "true" : "false"; } sudokuRating = rating; setElement("sudokuBoard", LOADING_CODE); sudokuId = ""; sudokuString = ""; sudokuSolved = ""; ajaxLoading = true; downloadSudoku(null, rating, symmetric, loadSudokuRandomExtCallback); } function loadSudokuById(sid) { if (sid == null) { sid = 0; } setElement("sudokuBoard", LOADING_CODE); sudokuId = ""; sudokuString = ""; sudokuSolved = ""; ajaxLoading = true; downloadSudoku(sid, null, null, loadSudokuRandomExtCallback); } function loadSudokuRandom() { loadSudokuRandomExt(null, null); } function loadSudokuRandomExtCallback(responseText) { if (responseText) { ajaxLoading = false; sudokuString = responseText.substring(0,81); sudokuSolved = responseText.substring(81); sudokuPerm = responseText.substring(162,171); sudokuId = responseText.substring(171); setElement("sudokuLink", "open sudoku #"+CurrencyFormatted(sudokuId)+" in a new window"); if (!parseSudoku()) { getElement("sudokuBoard").innerHTML = ERROR_DB; return false; } showSudoku(false); if (getElement("rating")) { switch(sudokuRating) { case "easy": getElement("rating").innerHTML = RATING_EASY; break; case "medium": getElement("rating").innerHTML = RATING_MEDIUM; break; case "hard": getElement("rating").innerHTML = RATING_HARD; break; case "evil": getElement("rating").innerHTML = RATING_EVIL; break; } } } else { ajaxLoading = false; setElement("sudokuBoard", ERROR_CODE); } } /** download sudoku */ function downloadSudoku(sid, rating, symmetric, callback) { isDownloading = true; if (sid == null) { sudokuString = xml_request(SUDOKU_SCRIPT + "?rating=" + rating + "&symmetric=" + symmetric, callback); } else { sudokuString = xml_request(SUDOKU_SCRIPT + "?id=" + sid, callback); } isDownloading = false; } /** convert sudoku string to array */ function parseSudoku(isResetting) { var sudokuSolvedPerm = ""; var i = 0; var zero = "0".charCodeAt(0); for (var y = 0; y < 9; y++) { for (var x = 0; x < 9; x++) { var c = sudokuString.charCodeAt(i) - zero; if (c < 10 && c > 0) { sudokuBoard[x][y] = sudokuPerm.charAt(c-1); sudokuSolvedPerm += sudokuPerm.charAt(c-1); } else if(c == 0) { sudokuBoard[x][y] = 0; var sc = sudokuSolved.charCodeAt(i) - zero; sudokuSolvedPerm += sudokuPerm[sc-1]; } else { return false; } ++i; } } sudokuSolved = isResetting ? sudokuSolved : sudokuSolvedPerm; return true; } /** generate HTML code for sudoku */ function showSudoku(isResetting) { /** check if html code for sudokuBoard has already been generated */ if (hasBoard) { setElement("sudokuBoard", boardHTML); for (var y = 0; y < 9; y++) { for (var x = 0; x < 9; x++) { if(sudokuBoard[x][y] > 0) { var elem = getElement(SUDOKU_PREFIX + x + y); elem.value = sudokuBoard[x][y]; elem.style.background = FIELD_COLOR_HINTS; sudokuLocked[x][y] = true; } else { var elem = getElement(SUDOKU_PREFIX + x + y); elem.value = ""; elem.style.background = FIELD_COLOR; sudokuLocked[x][y] = false; } } } boardHTML = getElement("sudokuBoard").innerHTML; getElement(SUDOKU_PREFIX + "44").focus(); } else { var FORMAT = "border: 1px solid #000000; text-align: center; font-size: " + FONT_SIZE + "px; width: " + FIELD_SIZE + "px; height: " + FIELD_SIZE + "px;"; var PREFIX = ''; var TDSPACE = ''; var html = ''; for (var y = 0; y < 9; y++) { /** space */ if (y % 3 == 0 && y != 0) { html = html + TRSPACE; } html = html + ''; for (var x = 0; x < 9; x++) { if (x % 3 == 0 && x != 0) { html = html + TDSPACE; } if (sudokuBoard[x][y] > 0) { html = html + PREFIX + x + y + MIDDLE + sudokuBoard[x][y] + STYLE0 + SUFFIX; sudokuLocked[x][y] = true; } else { html = html + PREFIX + x + y + MIDDLE + STYLE1 + SUFFIX; sudokuLocked[x][y] = false; } } html = html + ''; } html = html + '
'; boardHTML = html; setElement("sudokuBoard", html); hasBoard = true; } } /** hint */ /** hint */ function getHint() { var sx = 0; var sy = 0; if (CURRENT_X != -1 && CURRENT_Y != -1 && sudokuBoard[CURRENT_X][CURRENT_Y] == 0) { sx = CURRENT_X; sy = CURRENT_Y; } else { sx = Math.floor(Math.random()*9); sy = Math.floor(Math.random()*9); } var x; var y; if (sudokuBoard[sx][sy] > 0) { x = (sx == 8) ? 0 : sx + 1; y = (sy == 8) ? 0 : sy + 1; while (x != sx || y != sy) { if (sudokuBoard[x][y] == 0) { break; } x++; if (x == 9) { x = 0; y = (y == 8) ? 0 : y + 1; } } } else { x = sx; y = sy; } if (sudokuBoard[x][y] == 0) { var n = sudokuSolved.charAt(x*1 + y*9); sudokuBoard[x][y] = n; getElement(SUDOKU_PREFIX + x + y).value = n; checkLogic(x, y); } } /** reset */ function reset() { var agree = confirm("Reset Sudoku??"); if (agree) { for (var i = 0; i < 3; i++) { for (var j = 0; j < 9; j++) { sudokuError[i][j] = false; } } parseSudoku(); showSudoku(true); } } /** /// EVENTS /// */ function _focus(elem) { var v = elem.id; var checkx = v.charAt(7); var checky = v.charAt(8); CURRENT_X = parseInt(checkx); CURRENT_Y = parseInt(checky); var error = sudokuError[ERROR_X][ checky ] || sudokuError[ERROR_Y][ checkx ] || sudokuError[ERROR_B][ sudokuBlock[checkx][checky] ]; if (sudokuLocked[checkx][checky]) { getElement(v).style.background = (error) ? FIELD_COLOR_ERROR_LOCKED_FOCUS : FIELD_COLOR_HINTS_FOCUS; } else { getElement(v).style.background = (error) ? FIELD_COLOR_ERROR_FOCUS : FIELD_COLOR_FOCUS; } return true; } function _blur(elem) { var v = elem.id; var checkx = v.charAt(7); var checky = v.charAt(8); var error = sudokuError[ERROR_X][ checky ] || sudokuError[ERROR_Y][ checkx ] || sudokuError[ERROR_B][ sudokuBlock[checkx][checky] ]; if (sudokuLocked[checkx][checky]) { getElement(v).style.background = (error) ? FIELD_COLOR_ERROR_LOCKED : FIELD_COLOR_HINTS; } else { getElement(v).style.background = (error) ? FIELD_COLOR_ERROR : FIELD_COLOR; } return true; } function _keydown(event, elem) { var v = elem.id; var checkx = v.charAt(7); var checky = v.charAt(8); var n = event.keyCode ? event.keyCode : event.charCode; //sudokuBoard[checkx][checky]; if (n >= 49 && n <= 57) { if (!sudokuLocked[checkx][checky]) { var v = n - 48; sudokuBoard[checkx][checky] = v; checkLogic(checkx, checky); elem.value = v; } getElement(SUDOKU_PREFIX + checkx + checky).blur(); getElement(SUDOKU_PREFIX + checkx + checky).focus(); return false; } else if (n >= 97 && n <= 105) { if (!sudokuLocked[checkx][checky]) { var v = n - 96; sudokuBoard[checkx][checky] = v; checkLogic(checkx, checky); elem.value = v; } getElement(SUDOKU_PREFIX + checkx + checky).blur(); getElement(SUDOKU_PREFIX + checkx + checky).focus(); return false; } else if (n >= KEY_LEFT && n <= KEY_DOWN) { switch (n) { case KEY_UP: checky = (checky > 0) ? checky - 1 : 8; break; case KEY_DOWN: checky = (checky < 8) ? checky - 0 + 1 : 0; break; case KEY_LEFT: checkx = (checkx > 0) ? checkx - 1 : 8; break; case KEY_RIGHT: checkx = (checkx < 8) ? checkx - 0 + 1 : 0; break; } getElement(SUDOKU_PREFIX + checkx + checky).blur(); getElement(SUDOKU_PREFIX + checkx + checky).focus(); return false; } else if (n == 48 || n == 96 || n == 32 || n == 13 || n == 8 || n == 46 || n == 12) { if (!sudokuLocked[checkx][checky]) { sudokuBoard[checkx][checky] = 0; checkLogic(checkx, checky); elem.value = ""; elem.focus(); } getElement(SUDOKU_PREFIX + checkx + checky).blur(); getElement(SUDOKU_PREFIX + checkx + checky).focus(); return false; } else { getElement(SUDOKU_PREFIX + checkx + checky).blur(); elem.focus(); return false; } } /** /// INIT /// */ for (var i = 0; i < 9; i++) { sudokuBoard[i] = new Array(9); sudokuLocked[i] = new Array(9); sudokuBlock[i] = new Array(9); for (var j = 0; j < 9; j++) { sudokuBlock[i][j] = Math.floor(i / 3) + Math.floor(j / 3) * 3; } } for (var i = 0; i < 3; i++) { sudokuError[i] = new Array(9); for (var j = 0; j < 9; j++) { sudokuError[i][j] = false; } }