컴퓨터와 대전할 수 있는 아주 세지 않고 약간 상대가 되어주는 오목입니다.
은근히 잘 둔다니까요.
chatGPT에게 시켜서 제작된 코드인데 꽤 괜찮네요 ㅎ
티스토리에서는 아쉽게도 게임오버 후 재시작 버튼이 작동이 안되네요 ㅎ
아래 화면에서 직접 플레이 가능합니다.
오목 게임 (플레이어 vs AI)
단일코드인데 소스코드 공유 드려요~
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>오목 게임 vs AI</title>
<style>
body {
margin: 0;
font-family: sans-serif;
background-color: #f9f9f9;
}
canvas {
display: block;
margin: 30px auto;
border: 2px solid #000;
background-color: #fff;
}
#result-message {
display: none;
position: fixed;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 64px;
font-weight: bold;
color: #fff;
background: rgba(0, 0, 0, 0.7);
padding: 30px 60px;
border-radius: 20px;
z-index: 10;
text-align: center;
}
#restart-btn {
display: none;
position: fixed;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24px;
padding: 15px 30px;
background-color: #28a745;
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
z-index: 10;
}
#restart-btn:hover {
background-color: #218838;
}
#particles-js {
position: fixed;
top: 0; left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
</style>
</head>
<body>
<h2 style="text-align: center;">오목 게임 (플레이어 vs AI)</h2>
<canvas id="board" width="600" height="600"></canvas>
<div id="result-message"></div>
<button id="restart-btn" onclick="restartGame()">다시 시작</button>
<div id="particles-js"></div>
<!-- particles.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
<script>
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
const size = 15;
const cell = canvas.width / size;
let board = Array.from({ length: size }, () => Array(size).fill(0));
let gameEnded = false;
drawBoard();
canvas.addEventListener("click", (e) => {
if (gameEnded) return;
const x = Math.floor(e.offsetX / cell);
const y = Math.floor(e.offsetY / cell);
if (board[y][x] === 0) {
placeStone(x, y, 1);
if (checkWin(x, y, 1)) {
showResult("🎉 플레이어 승리!");
return;
}
setTimeout(() => {
aiMove();
}, 300);
}
});
function drawBoard() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < size; i++) {
ctx.beginPath();
ctx.moveTo(cell / 2, cell / 2 + i * cell);
ctx.lineTo(canvas.width - cell / 2, cell / 2 + i * cell);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(cell / 2 + i * cell, cell / 2);
ctx.lineTo(cell / 2 + i * cell, canvas.height - cell / 2);
ctx.stroke();
}
}
function placeStone(x, y, player) {
board[y][x] = player;
ctx.beginPath();
ctx.arc(x * cell + cell / 2, y * cell + cell / 2, cell / 2.5, 0, Math.PI * 2);
ctx.fillStyle = player === 1 ? "black" : "white";
ctx.fill();
ctx.stroke();
}
function checkWin(x, y, player) {
const directions = [[1,0],[0,1],[1,1],[1,-1]];
for (let [dx, dy] of directions) {
let count = 1;
for (let dir of [-1, 1]) {
let nx = x, ny = y;
while (true) {
nx += dx * dir;
ny += dy * dir;
if (nx < 0 || ny < 0 || nx >= size || ny >= size || board[ny][nx] !== player) break;
count++;
}
}
if (count >= 5) return true;
}
return false;
}
function aiMove() {
let maxScore = 0;
let bestMove = null;
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
if (board[y][x] !== 0) continue;
const attackScore = evaluate(x, y, 2);
const defenseScore = evaluate(x, y, 1);
const score = Math.max(attackScore, defenseScore * 0.9);
if (score > maxScore) {
maxScore = score;
bestMove = [x, y];
}
}
}
if (bestMove) {
const [x, y] = bestMove;
placeStone(x, y, 2);
if (checkWin(x, y, 2)) {
showResult("💥 AI 승리!");
}
} else {
showResult("무승부!");
}
}
function evaluate(x, y, player) {
let score = 0;
const directions = [[1,0],[0,1],[1,1],[1,-1]];
for (let [dx, dy] of directions) {
let count = 1;
let block = 0;
for (let i = 1; i < 5; i++) {
const nx = x + dx * i, ny = y + dy * i;
if (nx < 0 || ny < 0 || nx >= size || ny >= size) break;
if (board[ny][nx] === player) count++;
else if (board[ny][nx] !== 0) { block++; break; }
else break;
}
for (let i = 1; i < 5; i++) {
const nx = x - dx * i, ny = y - dy * i;
if (nx < 0 || ny < 0 || nx >= size || ny >= size) break;
if (board[ny][nx] === player) count++;
else if (board[ny][nx] !== 0) { block++; break; }
else break;
}
if (count >= 5) return 1000000;
if (block === 0) {
if (count === 4) score += 100000;
else if (count === 3) score += 1000;
else if (count === 2) score += 100;
else if (count === 1) score += 10;
} else if (block === 1) {
if (count === 4) score += 10000;
else if (count === 3) score += 500;
else if (count === 2) score += 50;
else if (count === 1) score += 5;
}
}
return score;
}
function showResult(message) {
gameEnded = true;
const resultDiv = document.getElementById("result-message");
const restartBtn = document.getElementById("restart-btn");
resultDiv.innerText = message;
resultDiv.style.display = "block";
restartBtn.style.display = "block";
particlesJS("particles-js", {
"particles": {
"number": { "value": 100 },
"color": { "value": "#ffffff" },
"shape": { "type": "circle" },
"opacity": { "value": 0.6 },
"size": { "value": 4 },
"move": { "enable": true, "speed": 3, "out_mode": "out" }
},
"interactivity": { "detect_on": "canvas" },
"retina_detect": true
});
}
function restartGame() {
board = Array.from({ length: size }, () => Array(size).fill(0));
gameEnded = false;
drawBoard();
// Clear overlays
document.getElementById("result-message").style.display = "none";
document.getElementById("restart-btn").style.display = "none";
document.getElementById("particles-js").innerHTML = "";
}
</script>
</body>
</html>
오늘도 방문해주신 모든 분들께 감~솨드립니다!
'chatGPT와 인공지능AI' 카테고리의 다른 글
AI코딩, 추억 속으로, 3D미로 게임 (0) | 2025.05.18 |
---|---|
AI코딩, 말귀를 알아듣네? (2) | 2025.05.18 |
윈드서프 AI로 실시간 오목 대전 게임 만들기 ( Node.js + SOCKET.IO ) (2) | 2025.05.13 |
윈드서프 AI로 교회 홈페이지 만들기 (10) | 2025.05.11 |
윈드서프 AI로 홈페이지 만들기 (2) | 2025.05.11 |