I just have a small problem.
The final assignment in my computer science class is to write a game of Tic-Tac-Toe in JavaScript. The game works by clicking on cells w
My version, but it lacks the tie game check:
var table = [
['','',''],
['','',''],
['','','']
]
function GameIsOver(player) {
var result = true;
for (var j = 0; j < 3; j++) { //first diagonal
result= result && (table[j][j] == player);
}
if (result) {
return gameResult = {
result: result,
player: player
};
}
result = true;
for (var j = 0; j < 3; j++) { //second diagonal
result= result && (table[2-j][j] == player);
}
if (result) {
return gameResult = {
result: result,
player: player
};
}
for (var k = 0; k < 3; k++) {
result = true;
for (var j = 0; j < 3; j++) { //lines
result = result && (table[k][j] == player);
}
if (result) {
return gameResult = {
result: result,
player: player
};
}
result = true;
for (var j = 0; j < 3; j++) { //colums
result = result && (table[j][k] == player);
}
if (result) {
return gameResult = {
result: result,
player: player
};
}
}
return false;
}
I see you said you have searched Stack Overflow for similar questions. I understand how being new to programming, it's not easy to read something in another language but the fundamental idea is there. Here is a link where this is already done: Algorithm for Determining Tic Tac Toe Game Over.
That being said, there are basically 3 ways to win in the game, and you are headed in the right direction with your vars.
The three ways to win are
The easy parts are the rows and columns, simply for loop through each row/column and see if you get three matches, if you do, then you can declare a winner.
Non-efficient Pseudo-code Example:
if pic1, pic2, and pic3 are the same
alert user X or O has won
end the game.
Repeat for row 2, and row 3.
if pic1, pic4, and pic7 are the same
alert user X or O has won
end the game.
Repeat for column 2 and 3.
The diagonal can be done in a simple fashion as well, without using the two dimensional array in the example. There are basically only two diagonal win possibilities:
Anything else you can end the game in a draw. I would recommend using the counter as shown in the link example.
Good luck! -- edit for clarity --
I write from begining code where you can check my version of checking who win game. Dont downvote if my version of game is another than you. I just want to show you how you can write code without knowledge of any algorithm.
You just need motivation. Don't give up next time so fast.
My version for checking who win:
var checkResult = function(){
$("table tr").each(function(i, val){
$(this).find('td').each(function(j, val2){
arr[i][j] = parseInt($(this).attr("data-points"));
});
});
for(var i = 0; i<3;i++){
var rowSum = 0;
for(var j = 0; j<3;j++){
rowSum += arr[i][j];
}
if(rowSum === 3)
alert("Circle WIN!");
else if(rowSum === -3)
alert("Cross WIN!");
}
for(var i = 0; i<3;i++){
var colSum = 0;
for(var j = 0; j<3;j++){
colSum += arr[j][i];
}
if(colSum === 3)
alert("Circle WIN!");
else if(colSum === -3)
alert("Cross WIN!");
}
if(arr[0][0] + arr[1][1] + arr[2][2] === 3)
alert("Circle WIN!");
else if(arr[0][0] + arr[1][1] + arr[2][2] === -3)
alert("Cross WIN!");
if(arr[2][0] + arr[1][1] + arr[0][2] === 3)
alert("Circle WIN!");
else if(arr[2][0] + arr[1][1] + arr[0][2] === -3)
alert("Cross WIN!");
};
A few more optimizations.
Depending on which way you prefer the board to be represented.
I've coded a Tic-Tac-Toe game (in React), and chose a flat array, because I believe it is easier to work with (also in other aspects of the game)
I've authored my win-detection code in a manner where all possible winning positions are pre-defined, and the Array representing the game board is converted into an array of two strings (one per player), so each of the strings has the cells indices of which this particular player had selected.
/**
*
* @param {Array} board - flat array representation of the board,
* from right to left, top to bottom, Ex.
* [1,2,2,1,1,2,1,2,1]
*/
function checkWin(board){
// all possible winning combinations (of cells filled by the same player)
const winMap = [123, 456, 789, 147, 258, 369, 357, 159]
// convert the board to array represening the filled cells, per player.
// each array item is a string of only the cells (indices) filled by a player
const moves = board.reduce((players, v, i) => {
if(v) players[v-1] += i+1
return players
}, ['', ''])
// console.log(JSON.stringify(moves))
// find & return the winning combination
const winningMove = winMap.find(comb =>
moves.some(m => // there are only 2 sets of moves, one for each player
// break down the current combination to array and check if every item exists
// also in the current set of moves. quit on first match.
comb.toString().split('').every(c => m.includes(c))
)
)
return winningMove ?
{ // get the first number of the winning-move,
// substract 1 from it, and use as index to find which
// player played that move from the board Array
player: board[winningMove.toString()[0] - 1],
move: winningMove
}
: false
}
// sample tests:
[
[1,1,1,2,2,2], // player 1 wins, horizontal, row 1
[1,2,2,1,,,1], // player 1 wins, vertical, col 1
[2,1,1,1,2,1,2,1,2], // player 2 wins, diagonal to right
[1,1,2,1,2,1,2,1,2], // player 2 wins, diagonal to left
[1,2,1,1,2,1,2,1,2] // no win
].forEach(board => console.log(
checkWin(board)
))
I can't in good faith give you the answer to this, but I can walk you through one way of thinking about this problem; by no means is it the best solution, but it could get you at least a start.
To detect a winner, it must be true that one of the following holds:
Fortunately, you can loop over your table elements to make this check easily.
The if statement you provided is flawed. You do not need to precede your variables with var after you have declared them already. Additionally, your use of && is wrong. What this will do is check to see if the left statement is true, which in this case is var pic1 == var pic2, then checks if the right statement is also true, which is simply var pic3. By itself, this is not a good statement, since it will be automatically cast to Javascript's best interpretation of a boolean, which in this case is true as long as pic3 is defined. Instead, you will need something like if(pic1 == pic2 && pic2 == pic3), but I would use something besides comparing the images, which is what you're doing. You could change the class of each cell to "X" or "O" depending on which piece goes there, which would be a little more elegant.
Class names can be accessed via the .className call:
<div id="foo" class="bar"></div>
<script>
document.getElementById("foo").className; //returns "bar"
</script>
Here is a more in-depth description of how to change an element's class.