|
|
<!DOCTYPE html> |
|
|
<html lang="ko"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>์ค๋ชฉ ๊ฒ์</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<style> |
|
|
.board { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(15, 1fr); |
|
|
grid-template-rows: repeat(15, 1fr); |
|
|
width: 600px; |
|
|
height: 600px; |
|
|
background-color: #e6c88c; |
|
|
position: relative; |
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); |
|
|
} |
|
|
|
|
|
.cell { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
position: relative; |
|
|
cursor: pointer; |
|
|
} |
|
|
|
|
|
.cell::before, .cell::after { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
background-color: #333; |
|
|
} |
|
|
|
|
|
.cell::before { |
|
|
width: 100%; |
|
|
height: 1px; |
|
|
top: 50%; |
|
|
} |
|
|
|
|
|
.cell::after { |
|
|
width: 1px; |
|
|
height: 100%; |
|
|
left: 50%; |
|
|
} |
|
|
|
|
|
.stone { |
|
|
width: 80%; |
|
|
height: 80%; |
|
|
border-radius: 50%; |
|
|
z-index: 1; |
|
|
transition: transform 0.2s; |
|
|
} |
|
|
|
|
|
.stone.black { |
|
|
background: radial-gradient(circle at 30% 30%, #666, #000); |
|
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.5); |
|
|
} |
|
|
|
|
|
.stone.white { |
|
|
background: radial-gradient(circle at 30% 30%, #fff, #ddd); |
|
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3); |
|
|
} |
|
|
|
|
|
.star-point { |
|
|
position: absolute; |
|
|
width: 10px; |
|
|
height: 10px; |
|
|
background-color: #333; |
|
|
border-radius: 50%; |
|
|
transform: translate(-50%, -50%); |
|
|
z-index: 1; |
|
|
} |
|
|
|
|
|
.modal { |
|
|
display: none; |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
background-color: rgba(0, 0, 0, 0.7); |
|
|
z-index: 100; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
} |
|
|
|
|
|
.modal-content { |
|
|
background-color: white; |
|
|
padding: 2rem; |
|
|
border-radius: 10px; |
|
|
text-align: center; |
|
|
max-width: 80%; |
|
|
animation: modalFadeIn 0.3s; |
|
|
} |
|
|
|
|
|
@keyframes modalFadeIn { |
|
|
from { opacity: 0; transform: translateY(-50px); } |
|
|
to { opacity: 1; transform: translateY(0); } |
|
|
} |
|
|
|
|
|
.highlight { |
|
|
animation: highlight 1s infinite; |
|
|
} |
|
|
|
|
|
@keyframes highlight { |
|
|
0% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7); } |
|
|
50% { box-shadow: 0 0 0 10px rgba(255, 215, 0, 0); } |
|
|
100% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0); } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-100 min-h-screen flex flex-col items-center justify-center p-4"> |
|
|
<div class="text-center mb-8"> |
|
|
<h1 class="text-4xl font-bold text-gray-800 mb-2">์ค๋ชฉ ๊ฒ์</h1> |
|
|
<p class="text-gray-600">ํ๋๊ณผ ๋ฐฑ๋ ์ค ๋จผ์ 5๊ฐ๋ฅผ ์ฐ์์ผ๋ก ๋๋ ์ฌ๋์ด ์น๋ฆฌํฉ๋๋ค!</p> |
|
|
</div> |
|
|
|
|
|
<div class="flex items-center justify-center gap-8 mb-6"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-8 h-8 rounded-full bg-black mr-2"></div> |
|
|
<span class="font-medium">ํ๋</span> |
|
|
</div> |
|
|
|
|
|
<div class="text-center"> |
|
|
<div class="text-xl font-bold mb-1" id="turn-indicator">ํ๋ ์ฐจ๋ก</div> |
|
|
<button id="restart-btn" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition"> |
|
|
๊ฒ์ ๋ค์ ์์ |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
<div class="flex items-center"> |
|
|
<div class="w-8 h-8 rounded-full bg-white border border-gray-300 mr-2"></div> |
|
|
<span class="font-medium">๋ฐฑ๋</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="board" id="board"> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="modal" id="result-modal"> |
|
|
<div class="modal-content"> |
|
|
<h2 class="text-2xl font-bold mb-4" id="result-text">ํ๋ ์น๋ฆฌ!</h2> |
|
|
<button id="close-modal" class="px-6 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition"> |
|
|
๋ซ๊ธฐ |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mt-8 text-gray-600 text-sm"> |
|
|
<p>๊ท์น: ํ๋์ด ๋จผ์ ์์ํ๋ฉฐ, 3-3, 4-4, ์ฅ๋ชฉ(6๊ฐ ์ด์)์ ๊ธ์์
๋๋ค.</p> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
const board = document.getElementById('board'); |
|
|
const turnIndicator = document.getElementById('turn-indicator'); |
|
|
const restartBtn = document.getElementById('restart-btn'); |
|
|
const resultModal = document.getElementById('result-modal'); |
|
|
const resultText = document.getElementById('result-text'); |
|
|
const closeModal = document.getElementById('close-modal'); |
|
|
|
|
|
const BOARD_SIZE = 15; |
|
|
let currentPlayer = 'black'; |
|
|
let gameOver = false; |
|
|
let boardState = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(null)); |
|
|
|
|
|
|
|
|
function createBoard() { |
|
|
board.innerHTML = ''; |
|
|
|
|
|
|
|
|
for (let i = 0; i < BOARD_SIZE; i++) { |
|
|
for (let j = 0; j < BOARD_SIZE; j++) { |
|
|
const cell = document.createElement('div'); |
|
|
cell.className = 'cell'; |
|
|
cell.dataset.row = i; |
|
|
cell.dataset.col = j; |
|
|
|
|
|
|
|
|
if ((i === 3 || i === 7 || i === 11) && (j === 3 || j === 7 || j === 11)) { |
|
|
const starPoint = document.createElement('div'); |
|
|
starPoint.className = 'star-point'; |
|
|
cell.appendChild(starPoint); |
|
|
} |
|
|
|
|
|
cell.addEventListener('click', () => handleCellClick(i, j)); |
|
|
board.appendChild(cell); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function handleCellClick(row, col) { |
|
|
if (gameOver || boardState[row][col] !== null) return; |
|
|
|
|
|
|
|
|
boardState[row][col] = currentPlayer; |
|
|
renderStone(row, col, currentPlayer); |
|
|
|
|
|
|
|
|
if (checkWin(row, col)) { |
|
|
showResult(`${currentPlayer === 'black' ? 'ํ๋' : '๋ฐฑ๋'} ์น๋ฆฌ!`); |
|
|
highlightWinningStones(); |
|
|
gameOver = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
if (checkDraw()) { |
|
|
showResult('๋ฌด์น๋ถ!'); |
|
|
gameOver = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
currentPlayer = currentPlayer === 'black' ? 'white' : 'black'; |
|
|
updateTurnIndicator(); |
|
|
} |
|
|
|
|
|
|
|
|
function renderStone(row, col, player) { |
|
|
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`); |
|
|
const stone = document.createElement('div'); |
|
|
stone.className = `stone ${player}`; |
|
|
cell.appendChild(stone); |
|
|
} |
|
|
|
|
|
|
|
|
function checkWin(row, col) { |
|
|
const directions = [ |
|
|
[0, 1], |
|
|
[1, 0], |
|
|
[1, 1], |
|
|
[1, -1] |
|
|
]; |
|
|
|
|
|
for (const [dx, dy] of directions) { |
|
|
let count = 1; |
|
|
|
|
|
|
|
|
count += countStonesInDirection(row, col, dx, dy); |
|
|
|
|
|
count += countStonesInDirection(row, col, -dx, -dy); |
|
|
|
|
|
if (count >= 5) { |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
|
|
|
function countStonesInDirection(row, col, dx, dy) { |
|
|
let count = 0; |
|
|
let r = row + dx; |
|
|
let c = col + dy; |
|
|
|
|
|
while ( |
|
|
r >= 0 && r < BOARD_SIZE && |
|
|
c >= 0 && c < BOARD_SIZE && |
|
|
boardState[r][c] === currentPlayer |
|
|
) { |
|
|
count++; |
|
|
r += dx; |
|
|
c += dy; |
|
|
} |
|
|
|
|
|
return count; |
|
|
} |
|
|
|
|
|
|
|
|
function checkDraw() { |
|
|
for (let i = 0; i < BOARD_SIZE; i++) { |
|
|
for (let j = 0; j < BOARD_SIZE; j++) { |
|
|
if (boardState[i][j] === null) { |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
function highlightWinningStones() { |
|
|
|
|
|
document.querySelectorAll('.stone').forEach(stone => { |
|
|
stone.classList.add('highlight'); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
function updateTurnIndicator() { |
|
|
turnIndicator.textContent = `${currentPlayer === 'black' ? 'ํ๋' : '๋ฐฑ๋'} ์ฐจ๋ก`; |
|
|
turnIndicator.className = `text-xl font-bold mb-1 ${currentPlayer === 'black' ? 'text-gray-900' : 'text-gray-100 bg-gray-800 px-2 py-1 rounded'}`; |
|
|
} |
|
|
|
|
|
|
|
|
function showResult(message) { |
|
|
resultText.textContent = message; |
|
|
resultModal.style.display = 'flex'; |
|
|
} |
|
|
|
|
|
|
|
|
function resetGame() { |
|
|
boardState = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(null)); |
|
|
currentPlayer = 'black'; |
|
|
gameOver = false; |
|
|
createBoard(); |
|
|
updateTurnIndicator(); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.stone').forEach(stone => { |
|
|
stone.classList.remove('highlight'); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
restartBtn.addEventListener('click', resetGame); |
|
|
closeModal.addEventListener('click', () => { |
|
|
resultModal.style.display = 'none'; |
|
|
}); |
|
|
|
|
|
|
|
|
createBoard(); |
|
|
updateTurnIndicator(); |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - ๐งฌ <a href="https://enzostvs-deepsite.hf.space?remix=joung/t-t" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |