Game: Tic Tac Toe
10/18/15
The game:
It's kinda cheating that I made a game I've made before, and that it's just Tic Tac Toe, but it's been a while and I want to get into the groove of it. To be fair, I made it completely differently this time.
In fact, I believe last time I didn't even know how arrays and for-loops properly worked in JavaScript. It might be good to compare.
Not now, though.
Good to compare eventually.
Post-Mortem
I'll probably want to do post-mortems in the future, so I might as well start now.
User-Side
The main thing here is there is no mouse-movement feedback. The only way to know if you can click on a thing is to click on it and see what happens.
There's also just this one page and that's it. I mean, it's Tic Tac Toe, so simple is reasonable, but there could be transitions and stuff still.
Construction-Side
Might as well lay out the code:
(function () {
var row,
col,
grid,
X = ' X',
O = ' O',
turn = X,
checkWinPossibility,
checkStalemate,
checkWin,
end;
end = function(winner) {
Crafty('End').text('Winner: ' + winner);
};
checkWinPossibility = function (squares) {
var check;
check = squares.filter(function (square) {
return square.text();
});
if (check.length !== 3) {
return;
}
check = squares.filter(function (square) {
return square.text() === X;
});
if (check.length === 0 || check.length === 3) {
end(squares[0].text());
}
};
checkStalemate = function (grid) {
var check;
check = grid.filter(function (row) {
var check;
check = row.filter(function (entity) {
return entity.text();
});
return check.length === 3;
});
if (check.length === 3) {
end('stalemate');
}
};
checkEnd = function (grid) {
var col;
checkStalemate(grid);
// Check each row for a win
grid.forEach(function (row) {
checkWinPossibility(row);
});
// Check each column for a win
for (col = 0; col < 3; col += 1) {
checkWinPossibility(
grid.map(function (row) {
return row[col];
})
);
}
// Check down-right diagonal
checkWinPossibility(
grid.map(function (row, index) {
return row[index];
})
);
// Check up-right diagonal
checkWinPossibility(
grid.map(function (row, index) {
return row[2 - index];
})
);
};
Crafty.init(600, 900, 'game');
Crafty.e('2D,DOM,Color')
.attr({
x: 0,
y: 50,
w: 600,
h: 600
})
.color('black');
Crafty.e('2D,DOM,Text,End')
.attr({
x: 0,
y: 650,
w: 600,
h: 200
})
.textFont('size', '100px');
Crafty.e('2D,DOM,Text,Mouse,Restart')
.attr({
x: 90,
y: 0,
w: 500,
h: 50
})
.text('Click Here to Restart')
.textFont('size', '50px')
.bind('Click', function () {
turn = X;
Crafty('End').text('');
Crafty('Square').each(function () {
this.text('');
});
});
grid = [];
for (row = 0; row < 3; row++) {
grid[row] = [];
for (col = 0; col < 3; col++) {
grid[row][col] = Crafty.e('2D,DOM,Color,Text,Mouse,Square')
.attr({
x: 202 * col,
y: 50 + 202 * row,
w: 196,
h: 196
})
.color('White')
.textFont('size', '150px')
.bind('Click', function () {
if (!Crafty('End').text() && !this.text()) {
this.text(turn);
checkEnd(grid);
turn = turn !== X ? X : O;
}
});
}
}
}());
I like how I make an array of each possible win-condition and send that array to a generic win-checker.
I don't know if I like the use of globals at all for a game as simple as this. I should probably just have everything know about everything it needs to know about.
Also, I don't really have to check all the win conditions, just the ones that touch the given updated square. Though, really, it's good that I just do that. Making something like that smarter is something I should do only after profiling and deciding I need to speed up the code. Something that will never be necessary for Tic Tac Toe.
Starting over should probably be done with scene transitions.
Overall
It occurs to me that there's a lot of development things I need to learn to do that could be well served by applying it to making this game better. Full-screen options, sound-effects, music, responsive of game objects. Stuff that other games would need, but stuff that isn't enough to know how to make those other games.
It may just well become a running gag that I keep making Tic Tac Toe every once in a while to explore some specific thing I want to implement.