patternjavascriptMinor
HTML5 Tic-Tac-Toe game
Viewed 0 times
toetictachtml5game
Problem
I created an HTML5/JS tic-tac-toe game as an exercise and wanted some advice on my js code.
A couple of questions:
Live demo: http://jsfiddle.net/mbtt53tt/
tictactoe.html
triplet.js
```
(function () {
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 || 3;
this.ROWS = r || 3;
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);
}
A couple of questions:
- How can I improve the reset method? (currently reloads the page/re-initializes the game)
- Anything advice on other improvements?
Live demo: http://jsfiddle.net/mbtt53tt/
tictactoe.html
Triple T's
* {box-sizing:border-box;}
body {width:100%;max-width:500px;padding: 0 20px;margin: 0 auto;font: 20px arial;text-align:center;}
h1 {font-size:32px;width:100%;margin:20px auto;}
#game,#reset {margin: 20px auto 0;display: block;width:100%;}
#scoreboard {border:2px solid #ccc;width:100%;margin:10px auto;padding:10px;}
ul {display:flex;list-style:none;margin:0;padding:0;width:100%;}
li {margin:0;padding:0;flex-grow:1;}
button {border:1px solid #ccc;background:#fefefe;padding:7px 14px;margin:10px 20px;}
Triple T's
X:
Ties:
O:
Reset score
New Game
This text is displayed if your browser does not support HTML5 Canvas.
triplet.js
```
(function () {
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 || 3;
this.ROWS = r || 3;
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);
}
Solution
This is not a complete review, just a couple of points that jumped out at me:
JavaScript
Naming
Short variable names are hard to understand.
While
Will you in six month still understand what
So my recommendation would be: find good variable names for the one character names, and write out the abbreviated names (
Some function names also do not express well what they do:
Bugs
If I set row and column count to a number different from 3, it seems that nobody can win.
Long functions
The
Saving fields in local variables
In your
Why are you doing this instead of using the fields directly? This seems unnecessary and confusing.
Functions of Board
Why are some functions not part of board?
Comments
Comments on functions are especially important when the variable names are not too good. But even if you change them, I would still like some comments.
For example: What is the acceptable range for tile width? If I use for example 50, the board does not look good anymore.
Another example: What happens if I set row and column to 4 instead of 3?
And one last example: What does
Reset
I extracted your init code in a function:
And changed your reset function like this:
And I removed
CSS
I would put this in an external css file, and format it properly (each attribute on its own line, etc.). If you care about performance, minify with a tool later instead of writing harder to read code.
JavaScript
Naming
Short variable names are hard to understand.
While
ctx, e, etc are somewhat standard, r, lineW, w, coor, b, t, c, b, s, p, mArr, ver, etc are not and it is very hard to understand what they represent.Will you in six month still understand what
gameBoard = function (t, c, r) is without searching in the code? I would guess not. But if you use gameBoard = function (tileWidth, columnCount, rowCount), it is immediately clear what it does.So my recommendation would be: find good variable names for the one character names, and write out the abbreviated names (
ver, hor, etc).Some function names also do not express well what they do:
draw might be better named drawGameField and moveO better drawO (same for moveX).Bugs
If I set row and column count to a number different from 3, it seems that nobody can win.
Long functions
The
move function is definitely too long. I would at least extract the two red redraws to their own function.Saving fields in local variables
In your
move method, you save fields in local variables:var width = this.TILEWIDTH,
ctx = this.CTX,
board = this.board,
blen = board.length;Why are you doing this instead of using the fields directly? This seems unnecessary and confusing.
Functions of Board
Why are some functions not part of board?
move is, but moveX and moveO are not, for example. This seems odd.Comments
Comments on functions are especially important when the variable names are not too good. But even if you change them, I would still like some comments.
For example: What is the acceptable range for tile width? If I use for example 50, the board does not look good anymore.
Another example: What happens if I set row and column to 4 instead of 3?
And one last example: What does
draw draw? Everything? Or only the game field, but not the players choices?Reset
I extracted your init code in a function:
var b;
// Initialize Game
function init() {
b = new Board("game", 3, 3),
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);
}
init();And changed your reset function like this:
Board.prototype.reset = function(x) {
this.CANVAS.width = this.CANVAS.width; // clear canvas
init();
};And I removed
this.reset(); from move. Now the reset works without reloading each time.CSS
I would put this in an external css file, and format it properly (each attribute on its own line, etc.). If you care about performance, minify with a tool later instead of writing harder to read code.
Code Snippets
var width = this.TILEWIDTH,
ctx = this.CTX,
board = this.board,
blen = board.length;var b;
// Initialize Game
function init() {
b = new Board("game", 3, 3),
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);
}
init();Board.prototype.reset = function(x) {
this.CANVAS.width = this.CANVAS.width; // clear canvas
init();
};Context
StackExchange Code Review Q#61260, answer score: 4
Revisions (0)
No revisions yet.