Mam kod do gry w kółko i krzyżyk i jest już prawie gotowy. https://jsfiddle.net/mnc5ytp6/
Mam jeden problem, na który nie mogę znaleźć rozwiązania. Zasadniczo wszystko jest dobrze, dopóki ktoś nie wygra gry, po czym, jeśli bloki dla X i 0 pozostały niewypełnione, gracz nadal może je wypełnić, a jeśli osiągnie kolejne 3X lub 30, wynik rośnie.
Moje pytanie brzmi: jak mogę zablokować pola, które są niewypełnione, na wypadek, gdyby gracz wygrał wcześnie?
if(checkForWinner()){
if(currentTurn === 2){ // X player wins
alert(`${player1Name} won this round.`)
player1score++
document.querySelector('#player_one_score').innerText = player1score
}
else{
alert(`${player2Name} won this round.`)
player2score++
document.querySelector('#player_two_score').innerText = player2score
}
3 odpowiedzi
Użyj zmiennej game_ended
. Kiedy gra się zaczyna, jest false
. Kiedy ktoś wygrywa, staje się true
. Jeśli zmienna game_ended
jest prawdziwa, gdy ktoś kliknie komórkę, nic się nie dzieje. ;-)
Sprawdź ten przykład: https://jsfiddle.net/sye2anhr/1/
Kiedy resetujesz grę, resetujesz również tę zmienną z powrotem do stanu false
.
const positions = document.querySelectorAll('.col')
const winningCombo = [
[0,1,2],
[0,3,6],
[0,4,8],
[1,4,7],
[2,5,8],
[3,4,5],
[6,7,8],
[2,4,6]
]
let player1 = 'X';
let player2 = '0';
let player1score = 0;
let player2score = 0;
let currentTurn = 1;
let movesMade = 0;
let game_ended = false;
const player1NameAsk = prompt("First player's name: ").split('')
player1Name = player1NameAsk[0].toUpperCase() + player1NameAsk.slice(1).join('')
const player2NameAsk = prompt("Second player's name: ").split('');
player2Name = player2NameAsk[0].toUpperCase() + player2NameAsk.slice(1).join('')
function setPlayersNames(){
document.querySelector('#player_one').innerText = player1Name;
document.querySelector('#player_two').innerText = player2Name;
document.querySelector('#player_one_score').innerText = player1score;
document.querySelector('#player_two_score').innerText = player2score;
}
document.addEventListener('DOMContentLoaded', setPlayersNames)
document.querySelector('#reset').addEventListener('click', resetScore)
document.querySelector('#game').addEventListener('click', resetGame)
positions.forEach((position) =>{
position.addEventListener('click', (e) =>{
// If the game ended, ask the user if he wants another round
if (game_ended){
if(confirm('Game ended. Do you want to start another round?')){
resetGame();
}
return;
}
movesMade++;
if(currentTurn === 1){
if(e.currentTarget.innerHTML === ''){
e.currentTarget.style.color = 'red'
e.currentTarget.innerHTML = player1;
currentTurn += 1;
e.currentTarget.style.background = 'rgba(172,172,172,0.5)';
}
}else{
if(e.currentTarget.innerHTML === ''){
e.currentTarget.style.color = 'blue'
e.currentTarget.innerHTML = player2;
currentTurn -= 1;
e.currentTarget.style.background = 'rgba(76,76,76,0.8)';
}
}
if(checkForWinner()){
if(currentTurn === 2){ // X player wins
alert(`${player1Name} won this round.`)
player1score++
document.querySelector('#player_one_score').innerText = player1score
game_ended = true;
}
else{
alert(`${player2Name} won this round.`)
player2score++
document.querySelector('#player_two_score').innerText = player2score
game_ended = true;
}
}
})
function checkForWinner(){
if(movesMade > 4){
let moves = Array.prototype.slice.call(positions);
let results = moves.map((e)=>{
return e.innerHTML})
return winningCombo.find((combo) =>{
if (results[combo[0]] !== "" && results[combo[1]] !== "" && results[combo[2]] !== "" && results[combo[0]] === results[combo[1]] && results[combo[1]] === results[combo[2]]) {
return true;
} else {
return false;
}
})
}
}
})
function resetGame() {
game_ended = false;
currentTurn = 1;
positions.forEach((e) =>{
e.innerHTML = ''
e.style.background = 'white'
})
}
function resetScore(){
player1score = 0;
player2score = 0;
document.querySelector('#player_one_score').innerText = player1score;
document.querySelector('#player_two_score').innerText = player2score;
}
*{
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
}
h1{
text-align: center;
margin-bottom: 100px;
margin-top: 50px;
}
.container{
display: grid;
grid-template-columns: 60% 30%;
}
.main{
display: flex;
flex-direction: row;
justify-content: center;
}
.row{
width: 150px;
display:flex;
flex-direction: column;
border-collapse: collapse;
}
.col{
height: 150px;
border: 1px black solid;
border-collapse: collapse;
text-align: center;
line-height: 150px;
font-size: 4rem;
}
td{
border: 1px solid black;
}
#blank,
#reset_button,
#reset_game{
border:none;
}
#player_one,
#player_one_score,
#player_two_score,
#player_two,
#reset_button,
#reset_game{
text-align: center;
}
button{
padding: 5px 5px 5px 5px;
border-radius: 3px;
margin-top: 50px;
}
button:hover{
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<title>Tic-Tac-Toe</title>
</head>
<body>
<h1>Tic Tac Toe</h1>
<div class='container'>
<div class="main">
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</div>
<table>
<tr>
<td id='blank'></td>
<td id="player_one"></td>
<td id='player_two'></td>
</tr>
<tr>
<td>Score</td>
<td id='player_one_score'></td>
<td id='player_two_score'></td>
</tr>
<tr>
<td id='reset_button'><button id='reset'>Reset Score</button></td>
<td id='reset_game'><button id='game'>Reset Game</button></td>
</tr>
</table>
</div>
<script src='config.js'></script>
</body>
</html>
Możesz wyłączyć zdarzenia kliknięcia w tym konkretnym elemencie div za pomocą właściwości pointer-events.
Np. Możesz zrobić coś takiego
document.getElementById ("div"). style.pointerEvents = "none";
Możesz też usunąć moduł obsługi kliknięć. W swoim kodzie powyżej wspomnianego masz position.addEventListener('click', (e) =>{})
. Wyodrębnij tę funkcję strzałkową do normalnej nazwanej funkcji, np. clickHandler(){}
. Następnie, jeśli masz zwycięzcę (oznacza „koniec gry”), dla wszystkich pozycji zrób position.removeEventListener('click', clickHandler)
. W nowej grze możesz ponownie skonfigurować obsługę kliknięć. Oto dokumenty na to. https://developer.mozilla.org/ru/docs/Web/ API/EventTarget/removeEventListener