Добавить tic-tac-toe.html
This commit is contained in:
@@ -0,0 +1,192 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Крестики-нолики</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
background: #0f0f23;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
h1 { color: #7b68ee; margin-bottom: 10px; }
|
||||||
|
#status {
|
||||||
|
font-size: 1.3em;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
min-height: 35px;
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
.board {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 100px);
|
||||||
|
grid-template-rows: repeat(3, 100px);
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
.cell {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background: #1a1a3e;
|
||||||
|
border: 2px solid #7b68ee;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.cell:hover { background: #2a2a5e; transform: scale(1.05); }
|
||||||
|
.cell.x { color: #ff6b6b; }
|
||||||
|
.cell.o { color: #4ecdc4; }
|
||||||
|
.cell.win { background: #2a4a2a; border-color: #0f0; box-shadow: 0 0 15px #0f0; }
|
||||||
|
#scoreBoard {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
#restart {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px 30px;
|
||||||
|
font-size: 1em;
|
||||||
|
background: #7b68ee;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
#restart:hover { background: #6a5acd; transform: scale(1.05); }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>❌ Крестики-нолики</h1>
|
||||||
|
<div id="status">Ваш ход (X)</div>
|
||||||
|
<div class="board" id="board"></div>
|
||||||
|
<div id="scoreBoard">
|
||||||
|
<span>Вы (X): <b id="xs">0</b></span>
|
||||||
|
<span>НИЧЬЯ: <b id="ds">0</b></span>
|
||||||
|
<span>Компьютер (O): <b id="os">0</b></span>
|
||||||
|
</div>
|
||||||
|
<button id="restart">Новая игра</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const board = document.getElementById('board');
|
||||||
|
const status = document.getElementById('status');
|
||||||
|
let cells = Array(9).fill('');
|
||||||
|
let currentTurn = 'X';
|
||||||
|
let gameActive = true;
|
||||||
|
let scores = { X: 0, O: 0, D: 0 };
|
||||||
|
const wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
board.innerHTML = '';
|
||||||
|
cells.forEach((val, i) => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.className = 'cell' + (val === 'X' ? ' x' : val === 'O' ? ' o' : '');
|
||||||
|
div.textContent = val;
|
||||||
|
div.onclick = () => move(i);
|
||||||
|
board.appendChild(div);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkWin(player) {
|
||||||
|
return wins.find(w => w.every(i => cells[i] === player));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDraw() { return cells.every(c => c !== ''); }
|
||||||
|
|
||||||
|
function move(i) {
|
||||||
|
if (!gameActive || cells[i] || currentTurn !== 'X') return;
|
||||||
|
cells[i] = 'X';
|
||||||
|
render();
|
||||||
|
const w = checkWin('X');
|
||||||
|
if (w) { endGame('X', w); return; }
|
||||||
|
if (isDraw()) { endGame('D'); return; }
|
||||||
|
currentTurn = 'O';
|
||||||
|
status.textContent = 'Компьютер думает...';
|
||||||
|
setTimeout(aiMove, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
function aiMove() {
|
||||||
|
let best = -Infinity, bestMove = -1;
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
if (cells[i]) continue;
|
||||||
|
cells[i] = 'O';
|
||||||
|
let sc = minimax(false, 0);
|
||||||
|
cells[i] = '';
|
||||||
|
if (sc > best) { best = sc; bestMove = i; }
|
||||||
|
}
|
||||||
|
cells[bestMove] = 'O';
|
||||||
|
render();
|
||||||
|
const w = checkWin('O');
|
||||||
|
if (w) { endGame('O', w); return; }
|
||||||
|
if (isDraw()) { endGame('D'); return; }
|
||||||
|
currentTurn = 'X';
|
||||||
|
status.textContent = 'Ваш ход (X)';
|
||||||
|
}
|
||||||
|
|
||||||
|
function minimax(isMax, depth) {
|
||||||
|
if (checkWin('O')) return 10 - depth;
|
||||||
|
if (checkWin('X')) return depth - 10;
|
||||||
|
if (isDraw()) return 0;
|
||||||
|
if (isMax) {
|
||||||
|
let best = -Infinity;
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
if (cells[i]) continue;
|
||||||
|
cells[i] = 'O';
|
||||||
|
best = Math.max(best, minimax(false, depth + 1));
|
||||||
|
cells[i] = '';
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
} else {
|
||||||
|
let best = Infinity;
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
if (cells[i]) continue;
|
||||||
|
cells[i] = 'X';
|
||||||
|
best = Math.min(best, minimax(true, depth + 1));
|
||||||
|
cells[i] = '';
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endGame(result, wLine) {
|
||||||
|
gameActive = false;
|
||||||
|
if (result === 'D') {
|
||||||
|
status.textContent = '🤝 Ничья!';
|
||||||
|
scores.D++;
|
||||||
|
} else {
|
||||||
|
const name = result === 'X' ? 'Вы победили!' : 'Компьютер победил!';
|
||||||
|
status.textContent = (result === 'X' ? '🎉 ' : '😞 ') + name;
|
||||||
|
scores[result]++;
|
||||||
|
if (wLine) {
|
||||||
|
const allCells = board.children;
|
||||||
|
wLine.forEach(i => allCells[i].classList.add('win'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById('xs').textContent = scores.X;
|
||||||
|
document.getElementById('os').textContent = scores.O;
|
||||||
|
document.getElementById('ds').textContent = scores.D;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('restart').onclick = () => {
|
||||||
|
cells = Array(9).fill('');
|
||||||
|
currentTurn = 'X';
|
||||||
|
gameActive = true;
|
||||||
|
status.textContent = 'Ваш ход (X)';
|
||||||
|
render();
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user