3

Currently I am trying to add a timer to count up when the start button is clicked. Currently when you click that start button I am getting Elapsed Time: undefined:NAN and I'm not sure what I have to change in my start_timer function to display the time while they are trying to solve the puzzle. Also when you click start again it resets the board but it does not reset the number of clicks and I would like everything to reset not just the board. Here is my current code.

table {
    border-collapse: collapse
}
 td {    
    border: 3px solid darkslategrey;
    width:25px;
}
<html>
    <head>
        <title>Game of 15</title>
        <script>
            var cells;
            var isSwap;
            var clicks = 0;
            function gameStart() {
                cells = new Array(
                                [
                                    document.getElementById("slot00"),
                                    document.getElementById("slot01"),
                                    document.getElementById("slot02"),
                                    document.getElementById("slot03")
                                ],
                                [
                                    document.getElementById("slot10"),
                                    document.getElementById("slot11"),
                                    document.getElementById("slot12"),
                                    document.getElementById("slot13")
                                ],
                                [
                                    document.getElementById("slot20"),
                                    document.getElementById("slot21"),
                                    document.getElementById("slot22"),
                                    document.getElementById("slot23")
                                ],
                                [
                                    document.getElementById("slot30"),
                                    document.getElementById("slot31"),
                                    document.getElementById("slot32"),
                                    document.getElementById("slot33")
                                ]
                            );

                numberPlace();
                start_timer();
            }

            function numberPlace() {
                var no = new Array();
                var randNo;
                var temp;
                for (var i = 0; i < 16; i++)
                    no[i] = i;
                    for (i = 0; i < 16; i++) {
                        randNo = Math.floor(Math.random() * 15 + 1);
                        temp = no[i];
                        no[i] = no[randNo];
                        no[randNo] = temp;
                    }
                    i = 0;
                    for (var rows = 0; rows < 4; rows++)
                        for (var cols = 0; cols < 4; cols++) {
                            if (no[i] != 0)
                                cells[rows][cols].innerHTML = no[i];
                            else
                                cells[rows][cols].innerHTML = "";
                            ++i;
                        }
            }
            function cellClicked(row, col) {
                var top = row - 1;
                var bottom = row + 1;
                var left = col - 1;
                var right = col + 1;
                isSwap = false;
                if (top != -1 && cells[top][col].innerHTML == "")
                    swapCell(cells[row][col], cells[top][col]);
                else if (right != 4 &&cells[row][right].innerHTML == "")
                    swapCell(cells[row][col], cells[row][right]);
                else if (bottom != 4 &&cells[bottom][col].innerHTML == "")
                    swapCell(cells[row][col], cells[bottom][col]);
                else if (left != -1 &&cells[row][left].innerHTML == "")
                    swapCell(cells[row][col], cells[row][left]);
                else
                    alert("You cannot move the number.");
                clickcounter();
                winCheck();
            }

            function swapCell(firstCell, secondCell) {
                isSwap = true;
                secondCell.innerHTML = firstCell.innerHTML;
                firstCell.innerHTML = "";
            }

            function clickcounter(){
                clicks += 1;
                document.getElementById("counter").innerHTML = clicks;
            }
            function winCheck() {
                var isWin = true;
                for (var i = 0; i < 4; i++)
                    for (var j = 0; j < 4; j++)
                        if (!(cells[i][j].innerHTML == i * 4 + j + 1))
                            if (!(i == 3 && j == 3))
                                isWin = false;
                            if (isWin){
                                alert("You Won !!");
                                stop_timer();
                            }
            }
            var active = true;
            function start_timer(){
                if (active){
                    var timer = document.getElementById("my_timer").innerHTML;
                    var arr = timer.split(":");
                    var hour = arr[0];
                    var min = arr[1];
                    var sec = arr[2];
                    if (sec == 59){
                        if (min == 59){
                            hour++;
                            min =0;
                            if (hour < 10) hour = "0" + hour;
                            }
                        else{
                            min++;
                        }
                        if (min < 10) min = "0" + min;
                            sec = 0;
                        }else{
                            sec++;
                            if (sec < 10) sec = "0" + sec;
                        }
                        document.getElementById("my_timer").innerHTML = hour + ":" + min + ":" + sec;
                        setTimeout(start_timer, 1000);
                }
            }
            function stop_timer(){
                if (active == true){
                    active = false;
                    start_timer();
                }
            }
            </script>
            </head>
            <body>
                <input id="startButton" type="button" value="Start" onclick="gameStart()"/>
                <p>Elapsed Time<label id="my_timer"></label></p>
                <p> Number of Clicks: <label id="counter"></label></p>
                <table width="400" height="400">
                    <tr>
                        <td onclick="cellClicked( 0, 0 )" align="center"><span id="slot00" /></td>
                        <td onclick="cellClicked( 0, 1 )" align="center"><span id="slot01" /></td>
                        <td onclick="cellClicked( 0, 2 )" align="center"><span id="slot02" /></td>
                        <td onclick="cellClicked( 0, 3 )" align="center"><span id="slot03" /></td>
                    </tr>

                    <tr>
                        <td onclick="cellClicked( 1, 0 )" align="center"><span id="slot10" /></td>
                        <td onclick="cellClicked( 1, 1 )" align="center"><span id="slot11" /></td>
                        <td onclick="cellClicked( 1, 2 )" align="center"><span id="slot12" /></td>
                        <td onclick="cellClicked( 1, 3 )" align="center"><span id="slot13" /></td>
                    </tr>

                    <tr>
                        <td onclick="cellClicked( 2, 0 )" align="center"><span id="slot20" /></td>
                        <td onclick="cellClicked( 2, 1 )" align="center"><span id="slot21" /></td>
                        <td onclick="cellClicked( 2, 2 )" align="center"><span id="slot22" /></td>
                        <td onclick="cellClicked( 2, 3 )" align="center"><span id="slot23" /></td>
                    </tr>

                    <tr>
                        <td onclick="cellClicked( 3, 0 )" align="center"><span id="slot30" /></td>
                        <td onclick="cellClicked( 3, 1 )" align="center"><span id="slot31" /></td>
                        <td onclick="cellClicked( 3, 2 )" align="center"><span id="slot32" /></td>
                        <td onclick="cellClicked( 3, 3 )" align="center"><span id="slot33" /></td>
                    </tr>
            </table>
        </body>
</html>
Hitesh Tripathi
  • 856
  • 1
  • 11
  • 23
fahnz
  • 51
  • 4

4 Answers4

3

The code looks fine but the only issue is with the initial value, when the timer starts the document.getElementById("my_timer").innerHTML returns an empty string that's why your code is not working. Add some initial value in my_timer label.

e.g. Elapsed Time: 00:00:00

And add the below code in gameStart function to reset the game.

// To reset the timer and clicks
document.getElementById("my_timer").innerHTML = '00:00:00';
document.getElementById("counter").innerHTML = 0;

//To clear the interval
if (interval) {
    clearInterval(interval);
}
interval = setInterval(start_timer, 1000);

Working code.

 var cells;
        var isSwap;
        var clicks = 0;
        let interval = null;

        function gameStart() {

            cells = new Array([document.getElementById("slot00"), document.getElementById("slot01"), document.getElementById("slot02"), document.getElementById("slot03")], [document.getElementById("slot10"), document.getElementById("slot11"), document.getElementById("slot12"), document.getElementById("slot13")], [document.getElementById("slot20"), document.getElementById("slot21"), document.getElementById("slot22"), document.getElementById("slot23")], [document.getElementById("slot30"), document.getElementById("slot31"), document.getElementById("slot32"), document.getElementById("slot33")]);
            numberPlace();


            // To reset the timer and clicks
            document.getElementById("my_timer").innerHTML = '00:00:00';
            document.getElementById("counter").innerHTML = 0;

            //To clear the interval
            if (interval) {
                clearInterval(interval);
            }
            interval = setInterval(start_timer, 1000);
        }

        function numberPlace() {
            var no = new Array();
            var randNo;
            var temp;
            for (var i = 0; i < 16; i++) no[i] = i;
            for (i = 0; i < 16; i++) {
                randNo = Math.floor(Math.random() * 15 + 1);
                temp = no[i];
                no[i] = no[randNo];
                no[randNo] = temp;
            }
            i = 0;
            for (var rows = 0; rows < 4; rows++)
                for (var cols = 0; cols < 4; cols++) {
                    if (no[i] != 0) cells[rows][cols].innerHTML = no[i];
                    else cells[rows][cols].innerHTML = "";
                    ++i;
                }
        }

        function cellClicked(row, col) {
            var top = row - 1;
            var bottom = row + 1;
            var left = col - 1;
            var right = col + 1;
            isSwap = false;
            if (top != -1 && cells[top][col].innerHTML == "") swapCell(cells[row][col], cells[top][col]);
            else if (right != 4 && cells[row][right].innerHTML == "") swapCell(cells[row][col], cells[row][right]);
            else if (bottom != 4 && cells[bottom][col].innerHTML == "") swapCell(cells[row][col], cells[bottom][col]);
            else if (left != -1 && cells[row][left].innerHTML == "") swapCell(cells[row][col], cells[row][left]);
            else alert("You cannot move the number.");
            clickcounter();
            winCheck();
        }

        function swapCell(firstCell, secondCell) {
            isSwap = true;
            secondCell.innerHTML = firstCell.innerHTML;
            firstCell.innerHTML = "";
        }

        function clickcounter() {
            clicks += 1;
            document.getElementById("counter").innerHTML = clicks;
        }

        function winCheck() {
            var isWin = true;
            for (var i = 0; i < 4; i++)
                for (var j = 0; j < 4; j++)
                    if (!(cells[i][j].innerHTML == i * 4 + j + 1))
                        if (!(i == 3 && j == 3)) isWin = false;
            if (isWin) {
                alert("You Won !!");
                stop_timer();
            }
        }
        var active = true;


        function start_timer() {
            if (active) {
                var timer = document.getElementById("my_timer").innerHTML;
                var arr = timer.split(":");
                var hour = arr[0];
                var min = arr[1];
                var sec = arr[2];
                if (sec == 59) {
                    if (min == 59) {
                        hour++;
                        min = 0;
                        if (hour < 10) hour = "0" + hour;
                    } else {
                        min++;
                    }
                    if (min < 10) min = "0" + min;
                    sec = 0;
                } else {
                    sec++;
                    if (sec < 10) sec = "0" + sec;
                }
                document.getElementById("my_timer").innerHTML = hour + ":" + min + ":" + sec;
                //setTimeout(start_timer, 1000);
            }
        }

        function stop_timer() {
            if (active == true) {
                active = false;
                start_timer();
            }
        }
  table {
            border-collapse: collapse
        }
        
        td {
            border: 3px solid darkslategrey;
            width: 25px;
        }
  <input id="startButton" type="button" value="Start" onclick="gameStart()" />
    <p>Elapsed Time<label id="my_timer">00:00:00</label></p>
    <p> Number of Clicks: <label id="counter"></label></p>
    <table width="400" height="400">
        <tr>
            <td onclick="cellClicked( 0, 0 )" align="center"><span id="slot00" /></td>
            <td onclick="cellClicked( 0, 1 )" align="center"><span id="slot01" /></td>
            <td onclick="cellClicked( 0, 2 )" align="center"><span id="slot02" /></td>
            <td onclick="cellClicked( 0, 3 )" align="center"><span id="slot03" /></td>
        </tr>
        <tr>
            <td onclick="cellClicked( 1, 0 )" align="center"><span id="slot10" /></td>
            <td onclick="cellClicked( 1, 1 )" align="center"><span id="slot11" /></td>
            <td onclick="cellClicked( 1, 2 )" align="center"><span id="slot12" /></td>
            <td onclick="cellClicked( 1, 3 )" align="center"><span id="slot13" /></td>
        </tr>
        <tr>
            <td onclick="cellClicked( 2, 0 )" align="center"><span id="slot20" /></td>
            <td onclick="cellClicked( 2, 1 )" align="center"><span id="slot21" /></td>
            <td onclick="cellClicked( 2, 2 )" align="center"><span id="slot22" /></td>
            <td onclick="cellClicked( 2, 3 )" align="center"><span id="slot23" /></td>
        </tr>
        <tr>
            <td onclick="cellClicked( 3, 0 )" align="center"><span id="slot30" /></td>
            <td onclick="cellClicked( 3, 1 )" align="center"><span id="slot31" /></td>
            <td onclick="cellClicked( 3, 2 )" align="center"><span id="slot32" /></td>
            <td onclick="cellClicked( 3, 3 )" align="center"><span id="slot33" /></td>
        </tr>
    </table>
Sohail Ashraf
  • 10,078
  • 2
  • 26
  • 42
0

I believe you can do something like this

let count = 0;
function startTimer(active) {
 if(active) {
  setInterval( e => count++, 1000)
 }
}
Floro Varela
  • 69
  • 1
  • 8
0

Here is a copy of this post from me.

This is the base of a millisecond timer with very good performances and stability overtime.

When using setInterval/setTimeout, if a loop task is taking more time than the interval, the browser will simply extend the interval loop, to continue the full rendering. This is creating issues. After minutes of setInterval/setTimeout overload, this can freeze the tab, the browser or the whole computer.

Instead, we can now safely use requestAnimationFrame for fast looping, instead of setInterval/setTimeout.

/* Seconds to (STRING)HH:MM:SS.MS ------------------------*/
/* This time format is compatible with FFMPEG ------------*/
function secToTimer(sec){
  const o = new Date(0), p =  new Date(sec * 1000)
  return new Date(p.getTime()-o.getTime()).toString().split(" ")[4] + "." + p.getMilliseconds()
}

/* Countdown loop ----------------------------------------*/
let job, origin = new Date().getTime()
const timer = () => {
  job = requestAnimationFrame(timer)
  OUT.textContent = secToTimer((new Date().getTime() - origin) / 1000)
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(timer)

/* Stop looping ------------------------------------------*/
// cancelAnimationFrame(job)

/* Reset the start date ----------------------------------*/
// origin = new Date().getTime()
span {font-size:4rem}
<span id="OUT"></span>
<br>
<button onclick="origin = new Date().getTime()">RESET</button>
<button onclick="requestAnimationFrame(timer)">RESTART</button>
<button onclick="cancelAnimationFrame(job)">STOP</button>
NVRM
  • 11,480
  • 1
  • 88
  • 87
0
// please see the following example

https://jsfiddle.net/Daniel_Hug/pvk6p/

Swift
  • 790
  • 1
  • 5
  • 19