<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic Tac Toe vs AI</title>
<style>
.board {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 5px;
width: 310px;
margin: 20px auto;
}
.cell {
width: 100px;
height: 100px;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
cursor: pointer;
user-select: none;
}
.cell:hover {
background: #e0e0e0;
}
.message {
text-align: center;
font-size: 24px;
margin: 20px;
}
button {
display: block;
margin: 10px auto;
padding: 10px 20px;
font-size: 16px;
}
</style>
</head>
<body>
<div class="message" id="message">Your turn (X)</div>
<div class="board" id="board"></div>
<button id="reset">Reset Game</button>
<script>
// Game Module: จัดการตรรกะของเกมและ AI
const Game = {
board: Array(9).fill(null),
humanPlayer: 'X',
aiPlayer: 'O',
gameOver: false,
init: function() {
this.board = Array(9).fill(null);
this.gameOver = false;
},
makeMove: function(index, player) {
if (!this.gameOver && !this.board[index]) {
this.board[index] = player;
if (this.checkWin()) {
this.gameOver = true;
return `${player} wins!`;
}
if (this.board.every(cell => cell)) {
this.gameOver = true;
return "It's a tie!";
}
return null;
}
return null;
},
checkWin: function() {
const winPatterns = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
[0, 4, 8], [2, 4, 6] // Diagonals
];
return winPatterns.some(pattern => {
const [a, b, c] = pattern;
return this.board[a] && this.board[a] === this.board[b] && this.board[a] === this.board[c];
});
},
getEmptyCells: function() {
return this.board.reduce((acc, val, idx) => {
if (!val) acc.push(idx);
return acc;
}, []);
},
minimax: function(depth, isMaximizing) {
if (this.checkWin()) {
return isMaximizing ? -10 + depth : 10 - depth;
}
if (this.board.every(cell => cell)) {
return 0;
}
if (isMaximizing) {
let bestScore = -Infinity;
const emptyCells = this.getEmptyCells();
for (let i of emptyCells) {
this.board[i] = this.aiPlayer;
const score = this.minimax(depth + 1, false);
this.board[i] = null;
bestScore = Math.max(score, bestScore);
}
return bestScore;
} else {
let bestScore = Infinity;
const emptyCells = this.getEmptyCells();
for (let i of emptyCells) {
this.board[i] = this.humanPlayer;
const score = this.minimax(depth + 1, true);
this.board[i] = null;
bestScore = Math.min(score, bestScore);
}
return bestScore;
}
},
aiMove: function() {
let bestScore = -Infinity;
let bestMove;
const emptyCells = this.getEmptyCells();
for (let i of emptyCells) {
this.board[i] = this.aiPlayer;
const score = this.minimax(0, false);
this.board[i] = null;
if (score > bestScore) {
bestScore = score;
bestMove = i;
}
}
return this.makeMove(bestMove, this.aiPlayer);
}
};
// UI Module: จัดการการแสดงผลและการโต้ตอบ
const UI = {
boardElement: document.getElementById('board'),
messageElement: document.getElementById('message'),
resetButton: document.getElementById('reset'),
init: function() {
this.renderBoard();
this.addEventListeners();
},
renderBoard: function() {
this.boardElement.innerHTML = '';
Game.board.forEach((value, index) => {
const cell = document.createElement('div');
cell.className = 'cell';
cell.textContent = value || '';
cell.dataset.index = index;
this.boardElement.appendChild(cell);
});
},
updateMessage: function(message) {
this.messageElement.textContent = message;
},
addEventListeners: function() {
this.boardElement.addEventListener('click', (e) => {
const index = e.target.dataset.index;
if (index !== undefined && !Game.gameOver) {
const humanResult = Game.makeMove(index, Game.humanPlayer);
if (humanResult) {
this.renderBoard();
this.updateMessage(humanResult);
} else if (!Game.gameOver) {
this.renderBoard();
this.updateMessage("AI's turn (O)");
setTimeout(() => {
const aiResult = Game.aiMove();
this.renderBoard();
this.updateMessage(aiResult || "Your turn (X)");
}, 500); // Delay เพื่อให้ดูเป็นธรรมชาติ
}
}
});
this.resetButton.addEventListener('click', () => {
Game.init();
this.renderBoard();
this.updateMessage("Your turn (X)");
});
}
};
// Initialize the game
Game.init();
UI.init();
</script>
</body>
</html>