Tic Tac Toe en JavaScript
El juego Tic Tac Toe o Tres en línea (Tres en raya) está diseñado para 2 jugadores, que de forma alternativa colocan sus fichas en un tablero de 3×3.
Ganará el jugador que logre colocar 3 de sus fichas formando una línea recta.
Hemos realizado este juego utilizando HTML, Css y JavaScript. A continuación mostramos el código:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tic Tac Toe</title>
</head>
<body>
<div class="content">
<h1>Tic Tac Toe</h1>
<div class="marker">
<div class="marker-item">
<div class="header">X</div>
<span id="marker-X">0</span>
</div>
<div class="marker-item">
<div class="header">O</div>
<span id="marker-O">0</span>
</div>
</div>
<table id="board">
<tr>
<td data-cell="0" class="cell"></td>
<td data-cell="1" class="cell"></td>
<td data-cell="2" class="cell"></td>
</tr>
<tr>
<td data-cell="3" class="cell"></td>
<td data-cell="4" class="cell"></td>
<td data-cell="5" class="cell"></td>
</tr>
<tr>
<td data-cell="6" class="cell"></td>
<td data-cell="7" class="cell"></td>
<td data-cell="8" class="cell"></td>
</tr>
</table>
<div id="result"></div>
<button id="restart">Restart</button>
</div>
<script type="text/javascript">
/* Definitions */
let clicked = [];
let boardBlocked = false;
let current_player = "X";
let player_clicked = [];
player_clicked["X"] = [];
player_clicked["O"] = [];
let player_counter = [];
player_counter["X"] = 0;
player_counter["O"] = 0;
const winningCombination = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
/* Listeners */
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', handleCellClick));
var restartBtn = document.getElementById('restart');
restartBtn.addEventListener('click', handleRestartClick);
/* Functions */
/*
* Check all the possible combinations according
* to the cells clicked by the player and see
* if any of them are valid to win
*/
function check(current_player){
if(player_clicked[current_player].length < 3){
return false
}
for(let i=0; i<player_clicked[current_player].length; i++) {
for(let j=0; j<player_clicked[current_player].length; j++) {
for(let z=0; z<player_clicked[current_player].length; z++) {
var combination = [
player_clicked[current_player][i],
player_clicked[current_player][j],
player_clicked[current_player][z]
];
for(let y=0; y<winningCombination.length; y++) {
if(JSON.stringify(winningCombination[y]) === JSON.stringify(combination)){
win();
return true;
}
}
}
}
}
}
/*
* Detect click in cell and check if it makes win the player. If not, change player.
*/
function handleCellClick(clickedCellEvent) {
if(!boardBlocked){
const clickedCell = clickedCellEvent.target;
const clickedCellIndex = clickedCell.getAttribute('data-cell');
if(!clicked.includes(clickedCellIndex)){
clicked.push(clickedCellIndex);
player_clicked[current_player].push(parseInt(clickedCellIndex));
clickedCell.innerHTML = '<span class="player-' + current_player + '">' + current_player + '</span>';
check(current_player);
changePlayer();
}
}
}
/*
* Define player
*/
function changePlayer() {
current_player = current_player === "X" ? "O" : "X";
}
/*
* Set win
*/
function win(){
boardBlocked = true;
document.getElementById('board').classList.add("boardBlocked");
document.getElementById('result').classList.add("visible");
document.getElementById('result').innerHTML = current_player + " WIN!";
updateMarker(current_player);
}
/*
* Reset all variables, and board for new game
*/
function handleRestartClick(){
clicked = [];
boardBlocked = false;
current_player = "X";
player_clicked["X"] = [];
player_clicked["O"] = [];
document.getElementById('result').innerHTML = "";
document.getElementById('board').classList.remove("boardBlocked");
document.getElementById('result').classList.remove("visible");
document.querySelectorAll('.cell').forEach(cell => cell.textContent='');
}
/*
* Update winner marker
*/
function updateMarker(current_player){
player_counter[current_player] ++;
document.getElementById('marker-' + current_player).innerHTML = player_counter[current_player];
}
</script>
<style type="text/css">
*{
font-family: 'Verdana';
padding: 0;
margin: 0;
}
body{
background-color: #f7f2f2;
padding-top: 60px;
}
.content{
width: 70%;
background-color: white;
display: block;
margin: 0 auto;
padding: 15px;
}
.marker{
float: left;
width: 100%;
margin-bottom: 30px;
}
.marker .marker-item{
float: left;
height: 100px;
width: 100px;
line-height: 25px;
text-align: center;
margin-right: 30px;
border: 2px solid gray;
background-color: white;
}
.marker .marker-item .header{
float: left;
width: 100%;
height: auto;
background-color: #f6f6f6;
font-size: 20px;
line-height: 40px;
text-align: center;
margin-bottom: 5px;
}
.marker .marker-item span{
float: left;
width: 100%;
height: auto;
font-size: 30px;
line-height: 40px;
text-align: center;
}
h1,
table{
margin-bottom: 30px;
}
table,
table tr,
table tr td{
border-collapse: collapse;
border: 1px solid lightgray;
}
table tr td{
padding: 10px;
width: 50px;
height: 50px;
text-align: center;
}
table tr td span{
width: 50px;
height: 50px;
display: block;
border-radius: 50%;
line-height: 50px;
color: white;
font-size: 30px;
}
table tr td span.player-O{
background-color: #f6a400;
}
table tr td span.player-X{
background-color: #04AA6D;
}
table.boardBlocked tr td{
opacity: 0.2;
}
div#result{
width: 100%;
background-color: #4bace6;
padding: 10px 20px;
margin-top: 30px;
margin-bottom: 30px;
color: white;
display: none;
}
div#result.visible{
display: inherit;
}
</style>
</body>
</html>