admin管理员组文章数量:1193799
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 within a table and using a function() to switch the img source (a blank image until clicked on) to an X or an O. It's just about done, but there's one thing I can't get.
The game is played, obviously, by two players. The last thing I need is to get it (a function) to detect when a player wins and kill the script when this happens. I just can't figure this out. I know it involves if statements, and I've attempted several different codes, but everything I code just breaks the game.
I do see that this question has been asked before, and I've tried clicking on several links in the 'similar questions' box to the right, but all of them are in languages I haven't learned anything about (such as C#).
Here is my script:
<script type="text/javascript" charset="ISO-8859-1">
function placeMove(value)
{
if (document.getElementById(value).src.indexOf("FC")!=-1) //"FC" because of the FC contained in the file name. I intended for it to stand for "free cell", for easy indentification.
{
var turn = document.getElementById("playerturn").innerHTML;
if (turn == "X")
{
document.getElementById(value).src="../Images/TicTacToeX.jpg";
document.getElementById("playerturn").innerHTML="O";
}
if (turn == "O")
{
document.getElementById(value).src="../Images/TicTacToeO.jpg";
document.getElementById("playerturn").innerHTML="X";
}
}
else
{
window.alert("Tile is in use. Please select another tile.");
}
}
function detectWin()
{
}
</script>
This is the table that the game takes place in, if it helps:
<table class="gametable" id="gametable" border="1">
<tr>
<td><img onclick="placeMove('r1c1')" id="r1c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r1c2')" id="r1c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r1c3')" id="r1c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
<td><img onclick="placeMove('r2c1')" id="r2c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r2c2')" id="r2c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r2c3')" id="r2c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
<td><img onclick="placeMove('r3c1')" id="r3c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r3c2')" id="r3c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r3c3')" id="r3c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
</table>
The assignment is due tomorrow, and all I need is this last little bit of code.
Any help is greatly appreciated. This is my last assignment of the semester.
Thanks,
Kyle
EDIT: After some suggestions, here is what I've been trying. Entering this code will not allow the game to be played. If it's just a matter of missing semicolons, please forgive me. It involves setting the img source in each cell to a variable, and checking to see if those variables match.
There are 9 variables I created, one for each cell/X or O image:
var pic1 = document.getElementById("r1c1").src;
var pic2 = document.getElementById("r1c2").src;
var pic3 = document.getElementById("r1c3").src;
var pic4 = document.getElementById("r2c1").src;
var pic5 = document.getElementById("r2c2").src;
var pic6 = document.getElementById("r2c3").src;
var pic7 = document.getElementById("r3c1").src;
var pic8 = document.getElementById("r3c2").src;
var pic9 = document.getElementById("r3c3").src;
This is at the very end of the first script:
function detectWin()
{
if (var pic1 == var pic2 && var pic3)
{
window.alert("Game won. Please reset the game.");
}
}
This obviously only detects a win for the first row. If I can get this to work, I'll know what the rest of the code will have to be. I still don't know how to kill the script, though.
Edited to remove some unnecessary remarks and grammatical errors.
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 within a table and using a function() to switch the img source (a blank image until clicked on) to an X or an O. It's just about done, but there's one thing I can't get.
The game is played, obviously, by two players. The last thing I need is to get it (a function) to detect when a player wins and kill the script when this happens. I just can't figure this out. I know it involves if statements, and I've attempted several different codes, but everything I code just breaks the game.
I do see that this question has been asked before, and I've tried clicking on several links in the 'similar questions' box to the right, but all of them are in languages I haven't learned anything about (such as C#).
Here is my script:
<script type="text/javascript" charset="ISO-8859-1">
function placeMove(value)
{
if (document.getElementById(value).src.indexOf("FC")!=-1) //"FC" because of the FC contained in the file name. I intended for it to stand for "free cell", for easy indentification.
{
var turn = document.getElementById("playerturn").innerHTML;
if (turn == "X")
{
document.getElementById(value).src="../Images/TicTacToeX.jpg";
document.getElementById("playerturn").innerHTML="O";
}
if (turn == "O")
{
document.getElementById(value).src="../Images/TicTacToeO.jpg";
document.getElementById("playerturn").innerHTML="X";
}
}
else
{
window.alert("Tile is in use. Please select another tile.");
}
}
function detectWin()
{
}
</script>
This is the table that the game takes place in, if it helps:
<table class="gametable" id="gametable" border="1">
<tr>
<td><img onclick="placeMove('r1c1')" id="r1c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r1c2')" id="r1c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r1c3')" id="r1c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
<td><img onclick="placeMove('r2c1')" id="r2c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r2c2')" id="r2c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r2c3')" id="r2c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
<td><img onclick="placeMove('r3c1')" id="r3c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r3c2')" id="r3c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
<td><img onclick="placeMove('r3c3')" id="r3c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
</table>
The assignment is due tomorrow, and all I need is this last little bit of code.
Any help is greatly appreciated. This is my last assignment of the semester.
Thanks,
Kyle
EDIT: After some suggestions, here is what I've been trying. Entering this code will not allow the game to be played. If it's just a matter of missing semicolons, please forgive me. It involves setting the img source in each cell to a variable, and checking to see if those variables match.
There are 9 variables I created, one for each cell/X or O image:
var pic1 = document.getElementById("r1c1").src;
var pic2 = document.getElementById("r1c2").src;
var pic3 = document.getElementById("r1c3").src;
var pic4 = document.getElementById("r2c1").src;
var pic5 = document.getElementById("r2c2").src;
var pic6 = document.getElementById("r2c3").src;
var pic7 = document.getElementById("r3c1").src;
var pic8 = document.getElementById("r3c2").src;
var pic9 = document.getElementById("r3c3").src;
This is at the very end of the first script:
function detectWin()
{
if (var pic1 == var pic2 && var pic3)
{
window.alert("Game won. Please reset the game.");
}
}
This obviously only detects a win for the first row. If I can get this to work, I'll know what the rest of the code will have to be. I still don't know how to kill the script, though.
Edited to remove some unnecessary remarks and grammatical errors.
Share Improve this question edited May 15, 2013 at 23:08 Jazzy663 asked May 15, 2013 at 17:05 Jazzy663Jazzy663 1051 gold badge1 silver badge7 bronze badges 12- 4 This question has little potential without any attempts you've made yourself. After you've tried something, we can point you along ;) Stackoverflow doesn't just do your homework – Joost Commented May 15, 2013 at 17:09
- Puts this images online so i can use in my fiddle jsfiddle.net/4Fjby – Vinícius Moraes Commented May 15, 2013 at 17:10
- you need to call js method after each move this method should get 8 propabilities of wining using the td ids you can calculate that. – Muhammad Bekette Commented May 15, 2013 at 17:11
- 1 @Jazzy663 I hate to burst your bubble, though, but checking who won is the major part of this game. You're hardly halfway there, I'm afraid. – Joost Commented May 15, 2013 at 17:11
- 4 @Joost no it ain't he did some work and he is stuck, stackoverflow is about helping – Muhammad Bekette Commented May 15, 2013 at 17:13
7 Answers
Reset to default 8I 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.
jsFiddle
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!");
};
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:
- All three cells in any row are the same
- All three cells in any column are the same
- All three cells traversing the board diagonally are the same.
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.
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
- 3 matches across
- 3 matches down
- 3 matches diagonal.
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:
- var 1, 5, 9 match
- var 3, 5, 7 match.
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 --
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;
}
Assume 'squares' is a Array of Arrays of square size (e.g. 3), where 0 for not filled , 1 for player 1 (x) and -1 for the other player (O).
e.g. for size 3 by 3
let squares= Array(3).fill(Array(3).fill(0))
would be the starting board.
The following works for board size 1 by 1 ,2 by 2, 3 by 3, 4 by 4 ...
where for a board of size n
, n
consecutive x
's or o
's need to be in a row, column or diagonal.
Returns 0
if nobody won yet and 1
for player 1 and -1
for the other player.
First defining two helper functions to make the code more readable.
const add = (a, b) => a + b
function sum(array){
return array.reduce(add);
}
function calculateWinner(squares) {
// check for horizontal wins along rows and diagonals
let winner = calculateWinnerInner(squares);
if (winner !== 0) return winner;
// check for possible vertical wins as well
const stranspose = squares.map((col, i) => squares.map(row => row[i]));
return calculateWinnerInner(stranspose);
}
function calculateWinnerInner(squares) {
for (let r = 0; r < squares.length; r++) {
if (squares[r].length === sum(squares[r])) {
return 1;
}
if (squares[r].length === - sum(squares[r])) {
return -1;
}
}
const diagonal = squares.map((row, r) => squares[r][r]);
if (squares[0].length === sum(diagonal)) {
return 1;
}
if (squares[0].length === -sum(diagonal)) {
return -1;
}
const len=squares.length;
const crossdiagonal = squares.map((row, r) => squares[r][len-r-1]);
if (squares[0].length === sum(crossdiagonal)) {
return 1;
}
if (squares[0].length === -sum(crossdiagonal)) {
return -1;
}
return 0;
}
A few more optimizations.
- Add mechanism to identify which "lines" on a board can never be winning because they contain at least 1 of both players' pieces. These are cached to prevent future checks of that line and improve speed.
- Ignore expensive win check if there are not enough pieces for a win to be possible (while following the rules). For example, the soonest a player could win on a 3x3 board is when marking the 5th square.
本文标签: JavaScript TicTacToe if Winner detectionStack Overflow
版权声明:本文标题:JavaScript TicTacToe if... Winner detection - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738425520a2086100.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论