Newer
Older
Import / web / www.xiaofrog.com / games / sudoku / sudoku.js
/*
    Sudoku Puzzle Javascript Frontend 
    (C) Copyright 2007
    John Ryland <jryland@invertedlogic.com>

    ALL RIGHTS RESERVED
*/
var pauseBackup = new Array;
var puzzle = new Array;
var solution = new Array;
var initRequest = null;
var checkCount = 0;
var solved = false;
var startTime = 0;
var startPausedTime = 0;
var pausedTime = 0;
var updateTimerId = 0;

function currentMilliSecond()
{
    var d = new Date();
    return d.getTime();
}

function totalTime()
{
    return Math.round((currentMilliSecond() - startTime - pausedTime) / 1000);
}

function newGame()
{
    document.getElementById("inProgress").style.display = "block";
    initRequest = null;
    if (window.XMLHttpRequest)
        initRequest = new XMLHttpRequest();
    else if (window.ActiveXObject)
        initRequest = new ActiveXObject("Microsoft.XMLHTTP");
    if (initRequest != null) {
        initRequest.onreadystatechange = requestStateChanged;
        initRequest.open("GET","sudoku.php",true);
        initRequest.send(null);
    } else
        alert("Your browser doesn't support AJAX.")
}

function requestStateChanged()
{
    if (initRequest.readyState == 4) { // Loaded
        if (initRequest.status == 200) { // Okay
            initBoard();
        } else {
            alert("There was a problem getting a new game. Try again later.")
        }
    }
}

function initBoard()
{
    document.getElementById("inProgress").style.display = "none";
    for (var i = 1; i < 82; i++) {
        solution[i] = initRequest.responseText.charAt(i-1).toUpperCase();
        puzzle[i] = initRequest.responseText.charAt(i+82-1).toUpperCase();
        if ( puzzle[i] != '0' ) {
            document.getElementById(i.toString()).value = puzzle[i];
            document.getElementById(i.toString()).readOnly = true;
            document.getElementById(i.toString()).className = "ClueNumber";
        }
    }
    resetGame();
}

function solveGame()
{
    if ( !confirm("Do you really want to see the answers?\n" +
                "You will not be allowed to continue after this.\n" +
                "Are you sure you want to proceed?") )
        return;
    for (var i = 1; i < 82; i++) {
        document.getElementById(i.toString()).value = solution[i];
        document.getElementById(i.toString()).readOnly = true;
    }
    document.getElementById("resetButton").disabled = true;
    document.getElementById("pauseButton").disabled = true;
    document.getElementById("printButton").disabled = true;
    document.getElementById("checkButton").disabled = true;
    document.getElementById("solveButton").disabled = true;
    document.getElementById("status").innerHTML = "TOO HARD?" +
        "<br>Answers checked " + checkCount + " time(s)." +
        "<br>Gave up after " + totalTime() + " seconds";
    clearTimeout( updateTimerId );
    updateTimerId = 0;
    document.getElementById("time").innerHTML = "";
}

function pauseGame()
{
//    alert("Pause not implemented");
    if ( startPausedTime ) {
        clearTimeout( updateTimerId );
        updateTimerId = setTimeout( "updateTime()", 10 );
        pausedTime += currentMilliSecond() - startPausedTime;
        startPausedTime = 0;
        document.getElementById("pauseButton").value = "Pause";
        for (var i = 1; i < 82; i++) {
            document.getElementById(i.toString()).value = pauseBackup[i];
            if ( puzzle[i] == '0' ) {
                document.getElementById(i.toString()).className = "EnteredNumber";
            } else {
                document.getElementById(i.toString()).className = "ClueNumber";
            }
        }
        document.getElementById("newButton").disabled = false;
        document.getElementById("resetButton").disabled = false;
        document.getElementById("printButton").disabled = false;
        document.getElementById("checkButton").disabled = false;
        document.getElementById("solveButton").disabled = false;
        document.getElementById("status").innerHTML = "";
    } else {
        clearTimeout( updateTimerId );
        updateTimerId = 0;
        startPausedTime = currentMilliSecond();
        document.getElementById("pauseButton").value = "Resume";
        for (var i = 1; i < 82; i++) {
            pauseBackup[i] = document.getElementById(i.toString()).value;
            document.getElementById(i.toString()).value = "";
            document.getElementById(i.toString()).className = "PausedNumber";
        }
        document.getElementById("39").value = "P";
        document.getElementById("40").value = "A";
        document.getElementById("41").value = "U";
        document.getElementById("42").value = "S";
        document.getElementById("43").value = "E";
        document.getElementById("newButton").disabled = true;
        document.getElementById("resetButton").disabled = true;
        document.getElementById("printButton").disabled = true;
        document.getElementById("checkButton").disabled = true;
        document.getElementById("solveButton").disabled = true;
        document.getElementById("status").innerHTML = "PAUSED - Click resume to continue";
    }
}

function resetGame()
{
    startTime = currentMilliSecond();
    pausedTime = 0;
    checkCount = 0;
    clearTimeout( updateTimerId );
    updateTimerId = setTimeout( "updateTime()", 10 );
    solved = false;
    for (var i = 1; i < 82; i++) {
        if ( puzzle[i] == '0' ) {
            document.getElementById(i.toString()).value = "";
            document.getElementById(i.toString()).readOnly = false;
            document.getElementById(i.toString()).className = "EnteredNumber";
        }
    }
    document.getElementById("resetButton").disabled = false;
    document.getElementById("pauseButton").disabled = false;
    document.getElementById("printButton").disabled = false;
    document.getElementById("checkButton").disabled = false;
    document.getElementById("solveButton").disabled = false;
    document.getElementById("status").innerHTML = "";
    for (var i = 1; i < 82; i++) 
        document.getElementById(i.toString()).disabled = false;

    document.onkeydown = keyEventHandler;
}

function updateTime()
{
    clearTimeout( updateTimerId );
    updateTimerId = setTimeout( "updateTime()", 1000 );
    document.getElementById("time").innerHTML = totalTime() + " seconds";
}

function printGame()
{
    alert("Print not implemented");
}

function resetItem(item)
{
    if ( !document.getElementById(item.toString()).readOnly )
        document.getElementById(item).value = "";
    document.getElementById("status").innerHTML = "";
    for (var i = 1; i < 82; i++) {
        if ( puzzle[i] == '0' ) {
            document.getElementById(i.toString()).className = "EnteredNumber";
        }
    }
}

function checkAnswers()
{
    //alert("Check not implemented");
    var clues = 0;
    var correct = 0;
    var wrong = 0;
    var empty = 0;
    for (var i = 1; i < 82; i++) {
        if ( puzzle[i] == '0' ) {
            var val = document.getElementById(i.toString()).value;
            if ( val == "" || val == " " ) {
                document.getElementById(i.toString()).className = "EnteredNumber";
                empty++;
            } else if ( val != solution[i] ) {
                document.getElementById(i.toString()).className = "WrongNumber";
                wrong++;
            } else {
                document.getElementById(i.toString()).className = "CorrectNumber";
                correct++;
            }
        } else {
            clues++;
        }
    }
    checkCount++;
    document.getElementById("status").innerHTML = "Clues: " + clues + " Correct: " + correct +
                                        " Wrong: " + wrong + " Empty: " + empty +
                                        "<br>Answers checked " + checkCount + " time(s).";
    if ( wrong == 0 && empty == 0 ) {
        document.getElementById("pauseButton").disabled = true;
        document.getElementById("printButton").disabled = true;
        document.getElementById("checkButton").disabled = true;
        document.getElementById("solveButton").disabled = true;
        document.getElementById("status").innerHTML = "CONGRATULATIONS - PUZZLE SOLVED" +
            "<br>Answers checked " + checkCount + " time(s)." +
            "<br>Solved in " + totalTime() + " seconds";
        for (var i = 1; i < 82; i++) 
            document.getElementById(i.toString()).disabled = true;
        clearTimeout( updateTimerId );
        updateTimerId = 0;
        document.getElementById("time").innerHTML = "";
    }
}

function keyEventHandler(event)
{
    var k;
    if (window.event)
        k = window.event.keyCode;
    else if (event)
        k = event.which;

    if (!event)
        event = window.event;
    target = event.target ? event.target : event.srcElement;
    if (target) {
//        k = event.keyCode;
        ch = String.fromCharCode(k);
        i = parseInt(target.id);
        if ( i == NaN || i < 1 || i > 81)
            return false;
        if ( !document.getElementById(i.toString()).readOnly ) {
            if ( k == 8 || ch <= ' ' )
                document.getElementById(i.toString()).value = "";
            if ( ch > '0' && ch <= '9' )
                document.getElementById(i.toString()).value = ch;
        }
        if ( k < 37 || k > 40 )
            return false;
        if ((k == 37 && (i % 9) == 1) || (k == 38 && (i - 9) <= 0))
            return false;
        if ((k == 39 && (i % 9) == 0) || (k == 40 && (i + 9) > 81))
            return false;
        if ( puzzle[i] == '0' )
            document.getElementById(i.toString()).className = "EnteredNumber";
        else
            document.getElementById(i.toString()).className = "ClueNumber";
        if ( k == 37 ) i--;       // Left
        if ( k == 38 ) i -= 9;    // Up
        if ( k == 39 ) i++;       // Right
        if ( k == 40 ) i += 9;    // Down
        document.getElementById(i.toString()).focus();
        if ( puzzle[i] == '0' )
            document.getElementById(i.toString()).className = "EnteredNumberFocused";
        else
            document.getElementById(i.toString()).className = "ClueNumberFocused";
    }
    return false;
}