HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Tic-Tac-Toe game with HTML5 canvas

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withtoetictacgamehtml5canvas

Problem

I know it is a simple game, but what I am doing here is practice what I took in an AI course. I'm also playing a little with the canvas and trying to improve the readability of my code and using JavaScript as an object oriented language.

I divided my code into 3 main classes (objects).

  • Board class which represents the board object and contain its properties like width and height and the canvas to draw with.



  • Cell class which represents the individual cell object and contain its properties also.



-
The app script. This is not a class, it is just a the script that makes use of the other scripts and runs the game.

  • Is what I'm doing by dividing my code into these classes reasonable or it can be done in a simpler way?



  • Is making these classes affecting the performance or not?



  • Does my work need to be divided into more classes(objects)?



  • What I can do better?



Note: I have not implemented the minimax algorithm yet.

index.html


  
    Tic
    
    
    
    
    
    
  

  
    
        
            
                
                    Tic Tac Toc
                
            
        
        
            
                
                    
                
            
        
    

  


app.js

$(document).ready(function(){
    var canvas = $("#canvas").get(0);
    var ctx = canvas.getContext('2d');
    var data = 
        {
            canvas : canvas,
            ctx : ctx,
            x : canvas.width/2-150,
            y : canvas.height/2-150,
            width : 300,
            height : 300,
            playerX: "Abdulaziz",
            playerY: "salmaaa"
        };
    var board = new Board(data);
    board.drawBoard();
    $("#canvas").click({board: board, canvasId: "canvas"}, board.click);
});


Board.js

```
function Board(data){
data = (data === 'undefined') ? {} : data;
if(data){
this.canvas = data.canvas;
this.ctx = data.ctx;
this.cell = [];
this.isXTurn = true;
this

Solution

Dead Code

else{
        //undefined data object
    }


This isn't doing anything, so just delete it.

Enums

Right here, you are using a string literal to specify the player who needs to move:

this.player = "x";


Typically, you would use a player enum to specify the player.

Spacing

If you put spaces around your operators, your code is easier to read, debug (especially when finding order-of-operations bugs), and maintain:

this.ctx.moveTo((this.x+2*this.width/3), this.y);


Early Returns

Right here, you have some unnecessarily deep indentation:

if(Board.isInBounds(coord) && board.gameStatus == "turn"){
    var cell = board.getCell(coord);
    if(board.cell[cell.v][cell.h].player == ""){
        board.moves++;
        if(board.isXTurn){
            board.cell[cell.v][cell.h].drawX();
            board.isXTurn = !board.isXTurn;
        }else{
            board.cell[cell.v][cell.h].drawO();
            board.isXTurn = !board.isXTurn;
        }
        board.gameStatus = board.checkStatus(board);
        if(board.gameStatus == "turn"){
            board.drawStatusBar(board, "Player "+((board.isXTurn)?"X":"O")+" Turn!!");
        }else if(board.gameStatus == "win"){
            board.drawStatusBar(board, "Player "+((board.isXTurn)?"O":"X")+" Won!!");
        }else if(board.gameStatus == "tie"){
            board.drawStatusBar(board, "It is a Tie :D");
        }    
    }
}


If I wrote this, I would use early returns at the top to use less indentation:

if (!Board.isInBounds(coord) || board.gameStatus != "turn") {
    return;
}

var cell = board.getCell(coord);

if (board.cell[cell.v][cell.h].player != "") {
    return;
}

board.moves++;

if (board.isXTurn) {
    board.cell[cell.v][cell.h].drawX();
    board.isXTurn = !board.isXTurn;
} else {
    board.cell[cell.v][cell.h].drawO();
    board.isXTurn = !board.isXTurn;
}

board.gameStatus = board.checkStatus(board);
if (board.gameStatus == "turn") {
    board.drawStatusBar(board, "Player "+((board.isXTurn)?"X":"O")+" Turn!!");
} else if (board.gameStatus == "win"){
    board.drawStatusBar(board, "Player "+((board.isXTurn)?"O":"X")+" Won!!");
} else if (board.gameStatus == "tie"){
    board.drawStatusBar(board, "It is a Tie :D");
}

Code Snippets

else{
        //undefined data object
    }
this.player = "x";
this.ctx.moveTo((this.x+2*this.width/3), this.y);
if(Board.isInBounds(coord) && board.gameStatus == "turn"){
    var cell = board.getCell(coord);
    if(board.cell[cell.v][cell.h].player == ""){
        board.moves++;
        if(board.isXTurn){
            board.cell[cell.v][cell.h].drawX();
            board.isXTurn = !board.isXTurn;
        }else{
            board.cell[cell.v][cell.h].drawO();
            board.isXTurn = !board.isXTurn;
        }
        board.gameStatus = board.checkStatus(board);
        if(board.gameStatus == "turn"){
            board.drawStatusBar(board, "Player "+((board.isXTurn)?"X":"O")+" Turn!!");
        }else if(board.gameStatus == "win"){
            board.drawStatusBar(board, "Player "+((board.isXTurn)?"O":"X")+" Won!!");
        }else if(board.gameStatus == "tie"){
            board.drawStatusBar(board, "It is a Tie :D");
        }    
    }
}
if (!Board.isInBounds(coord) || board.gameStatus != "turn") {
    return;
}

var cell = board.getCell(coord);

if (board.cell[cell.v][cell.h].player != "") {
    return;
}

board.moves++;

if (board.isXTurn) {
    board.cell[cell.v][cell.h].drawX();
    board.isXTurn = !board.isXTurn;
} else {
    board.cell[cell.v][cell.h].drawO();
    board.isXTurn = !board.isXTurn;
}

board.gameStatus = board.checkStatus(board);
if (board.gameStatus == "turn") {
    board.drawStatusBar(board, "Player "+((board.isXTurn)?"X":"O")+" Turn!!");
} else if (board.gameStatus == "win"){
    board.drawStatusBar(board, "Player "+((board.isXTurn)?"O":"X")+" Won!!");
} else if (board.gameStatus == "tie"){
    board.drawStatusBar(board, "It is a Tie :D");
}

Context

StackExchange Code Review Q#92272, answer score: 5

Revisions (0)

No revisions yet.