0

I've been trying to work out this simple javascript tic tac toe game. I'm trying to make the board size a variable and number needed in a row a variable. I've created a global variable for board size and number in a row. However it doesn't seem to be working. It makes the board the size I want but only a few of the squares will actually result in a 'Win'. Could someone please help me out ;).

Here is an image of one of the issues: https://i.stack.imgur.com/FU3bF.jpg

I imagine the error occurs here:

function checkWinner(mArr) {
    var winner = [false, ""];
    for (var i = 0; i < mArr.length; i++) {
        var hor = [],
            ver = [],
            diag = [];
        if (mArr[i][3] !== "") {
            //horizontal
            if (i % 3 === 0) {
                for (var j = 0; j < 3; j++) {
                    hor.push([mArr[i + j][3], i + j]);
                }
                if (hor.length === numinrow) {
                    winner = isWinner(hor);
                    if (winner[0]) {
                        return winner;
                    }
                }
            }
            //vertical && diag/anti diag
            if (i < 3) {
                for (var j = 0; j + i < mArr.length; j += 3) {
                    ver.push([mArr[i + j][3], i + j]);
                }
                if (ver.length === numinrow) {
                    winner = isWinner(ver);
                    if (winner[0]) {
                        return winner;
                    }
                }
                if (i !== 1) {
                    for (var z = 0; z + i < mArr.length - i; z += (4 - i)) {
                        diag.push([mArr[i + z][3], i + z]);
                    }
                    if (diag.length === numinrow) {
                        winner = isWinner(diag);
                        if (winner[0]) {
                            return winner;
                        }
                    }
                }
            }
        }
    }
    return winner;
}

Here is the entire .js

   (function () {
        var bsize = 5;
        var numinrow = 3;
        function Board(id, c, r) {
            if (this instanceof Board) {
                this.CANVAS = document.getElementById(id);
                this.CTX = this.CANVAS.getContext("2d");
                this.WIDTH = this.CANVAS.width || 0;
                this.HEIGHT = this.CANVAS.height || 0;
                this.COLS = c || bsize;
                this.ROWS = r || bsize;
                this.TILEWIDTH = (this.WIDTH / this.COLS);
                this.moveCount = 0;
                this.board = this.gameBoard(this.TILEWIDTH, this.COLS, this.ROWS);
                this.CANVAS.addEventListener('selectstart', function (e) {
                    e.preventDefault();
                    return false;
                }, false);
                this.winner = [false, ""];
                this.boardDisabled = false;
            } else {
                return new Board(id, c, r);
            }
        }
        Board.prototype.draw = function () {
            var ctx = this.CTX;
            ctx.beginPath();
            ctx.lineWidth = 5;
            ctx.strokeStyle = "#168dd9";
            // Draw column dividers
            for (var i = 1; i <= this.COLS - 1; i++) {
                ctx.moveTo(this.TILEWIDTH * i, 0);
                ctx.lineTo(this.TILEWIDTH * i, this.HEIGHT);
            }
            //Draw horizontal dividers
            for (var i = 1; i <= this.ROWS - 1; i++) {
                ctx.moveTo(0, this.TILEWIDTH * i);
                ctx.lineTo(this.WIDTH, this.TILEWIDTH * i);
            }
            ctx.stroke();
        };
        Board.prototype.gameBoard = function (t, c, r) {
            var b = [],
                count = 0;
            // Create gameboard array with the following data:
            // [x pos, y pos, tile count, empty string for move symbol (x or o)]
            for (var y = 0; y < r; y++) {
                for (var x = 0; x < c; x++) {
                    b.push([x * t, y * t, count++, ""]);
                }
            }
            return b;
        };
        Board.prototype.updateScore = function () {
            if (supports_html5_storage()) {
                var p = sessionStorage.score || {
                        "score_x": 0,
                        "score_o": 0,
                        "score_tie": 0
                    },
                    w = "score_" + (this.winner[1][0] || "tie");
                if (sessionStorage.score) {
                    p = JSON.parse(p);
                }
                p[w] ++;
                sessionStorage.score = JSON.stringify(p);
                this.updateScoreBoard();
            }
        };
        Board.prototype.updateScoreBoard = function () {
            if (supports_html5_storage()) {
                var p = sessionStorage.score ? JSON.parse(sessionStorage.score) : {
                    "score_x": 0,
                    "score_o": 0,
                    "score_tie": 0
                };
                for (var s in p) {
                    if (p.hasOwnProperty(s)) {
                        document.getElementById(s).innerHTML = p[s];
                    }
                }
            }
        };
        Board.prototype.reset = function (x) {
            var timer = x || 4000;
            window.setTimeout(function () {
                    window.location.reload(false);
                }, timer);
        };
        Board.prototype.resetScore = function () {
            if (supports_html5_storage()) {
                sessionStorage.removeItem("score");
                this.updateScoreBoard();
            }
        };
        Board.prototype.move = function (coor) {
            var width = this.TILEWIDTH,
                ctx = this.CTX,
                board = this.board,
                blen = board.length;
            //Loop through and find tile that click was detected on
            for (var i = 0; i < blen; i++) {
                if (coor.x > board[i][0] && coor.y > board[i][1] && coor.x < board[i][0] + width && coor.y < board[i][1] + width) {
                    var x = board[i][0],
                        y = board[i][1],
                        validTile = board[i][3] === "";
                    if (validTile) {
                        if (this.moveCount++ % 2 === 1) {
                            moveO(x, y, width, ctx);
                            board[i][3] = "o";
                        } else {
                            moveX(x, y, width, ctx);
                            board[i][3] = "x";
                        }
                    }
                    //Check board for winner if move count is 5 or more
                    if (this.moveCount > 4) {
                        this.winner = checkWinner(board);
                        var w = this.winner,
                            winner = w[0],
                            shape = w[1][0],
                            boardDisabled = this.boardDisabled;
                        //If there is a winner, redraw winning tiles in red
                        if (winner && !boardDisabled) {
                            if (shape === "o") {
                                for (var j = 1; j < 4; j++) {
                                    moveO(board[w[j][1]][0], board[w[j][1]]
                                        [1], width, ctx, "red", 5);
                                }
                            } else {
                                for (var j = 1; j < 4; j++) {
                                    moveX(board[w[j][1]][0], board[w[j][1]]
                                        [1], width, ctx, "red", 5);
                                }
                            }
                        }
                        if ((winner || this.moveCount === board.length) && !boardDisabled) {
                            if (!winner) {
                                //If tie, redraw all moves in red
                                for (var j = 0; j < board.length; j++) {
                                    if (board[j][3] === "o") {
                                        moveO(board[j][0], board[j][1], width, ctx, "red", 5);
                                    } else {
                                        moveX(board[j][0], board[j][1], width, ctx, "red", 5);
                                    }
                                }
                            }
                            this.boardDisabled = true;
                            this.updateScore();
                            this.reset();
                        }
                    }
                    break;
                }
            }
        };

        function checkWinner(mArr) {
            var winner = [false, ""];
            for (var i = 0; i < mArr.length; i++) {
                var hor = [],
                    ver = [],
                    diag = [];
                if (mArr[i][3] !== "") {
                    //horizontal
                    if (i % 3 === 0) {
                        for (var j = 0; j < 3; j++) {
                            hor.push([mArr[i + j][3], i + j]);
                        }
                        if (hor.length === numinrow) {
                            winner = isWinner(hor);
                            if (winner[0]) {
                                return winner;
                            }
                        }
                    }
                    //vertical && diag/anti diag
                    if (i < 3) {
                        for (var j = 0; j + i < mArr.length; j += 3) {
                            ver.push([mArr[i + j][3], i + j]);
                        }
                        if (ver.length === numinrow) {
                            winner = isWinner(ver);
                            if (winner[0]) {
                                return winner;
                            }
                        }
                        if (i !== 1) {
                            for (var z = 0; z + i < mArr.length - i; z += (4 - i)) {
                                diag.push([mArr[i + z][3], i + z]);
                            }
                            if (diag.length === numinrow) {
                                winner = isWinner(diag);
                                if (winner[0]) {
                                    return winner;
                                }
                            }
                        }
                    }
                }
            }
            return winner;
        }

        function isWinner(arr) {
            arr.sort();
            var w = arr[0][0] && arr[0][0] === arr[arr.length - 1][0] ? [true].concat(arr) : [false, ""];
            return w;
        }

        function moveO(x, y, r, ctx, fill, lineW) {
            var x = x + r / 2,
                y = y + r / 2,
                r = r / 2 - (r * 0.15);
            ctx.beginPath();
            ctx.lineWidth = lineW || 3;
            ctx.strokeStyle = fill || "#333";
            ctx.arc(x, y, r, 0, 2 * Math.PI);
            ctx.stroke();
        }

        function moveX(x, y, w, ctx, fill, lineW) {
            var pad = w * 0.15,
                lineCoor = [
                    [
                        [x + pad, y + pad], //line 1 start
                        [x + w - pad, y + w - pad] //line 1 end
                    ],
                    [
                        [x + pad, y + w - pad], //line 2 start
                        [x + w - pad, y + pad] //line 2 end
                    ]
                ];
            ctx.beginPath();
            ctx.lineWidth = lineW || 3;
            ctx.strokeStyle = fill || "#333";
            for (var i = 0; i < 2; i++) {
                ctx.moveTo(lineCoor[i][0][0], lineCoor[i][0][1]);
                ctx.lineTo(lineCoor[i][1][0], lineCoor[i][1][1]);
            }
            ctx.stroke();
        }

        function clickTouch(e) {
            var coor = b.CANVAS.relMouseCoords(e);
            if (!b.winner[0]) {
                b.move(coor);
            }
        }

        function clickTouchReset(e) {
                var target = e.target.id;
                if (target === "resetScore" && confirm("Are you sure you want to reset the score?")) {
                    b.resetScore();
                } else if (target === "resetGame") {
                    b.reset(1);
                }
            }
            // Initialize Game
            //BOARD SIZE
        var b = new Board("game", bsize, bsize),
            resetcon = document.getElementById("reset");
        b.draw();
        b.updateScoreBoard();
        //Add event listeners for click or touch
        window.addEventListener("click", clickTouch, false);
        window.addEventListener("touchstart", clickTouch, false);
        resetcon.addEventListener("click", clickTouchReset, false);
        resetcon.addEventListener("touchstart", clickTouchReset, false);
    })();
    /*****
    Get Mouse click coordinates within canvas
    Modified to include touch events
    Source: http://stackoverflow.com/a/9961416
    ******/
    HTMLCanvasElement.prototype.relMouseCoords = function (event) {
        var totalOffsetX = 0,
            totalOffsetY = 0,
            canvasX = 0,
            canvasY = 0,
            touch = event.touches,
            currentElement = this;
        do {
            totalOffsetX += currentElement.offsetLeft;
            totalOffsetY += currentElement.offsetTop;
        }
        while (currentElement = currentElement.offsetParent)
        canvasX = (touch ? touch[0].pageX : event.pageX) - totalOffsetX;
        canvasY = (touch ? touch[0].pageY : event.pageY) - totalOffsetY;
        canvasX = Math.round(canvasX * (this.width / this.offsetWidth));
        canvasY = Math.round(canvasY * (this.height / this.offsetHeight));
        return {
            x: canvasX,
            y: canvasY
        }
    }

    function supports_html5_storage() {
        try {
            return 'sessionStorage' in window && window.sessionStorage !== null;
        } catch (e) {
            return false;
        }
    }
Jake Reid
  • 95
  • 1
  • 7

0 Answers0