mirror of
https://codeberg.org/ashley/poke
synced 2025-05-30 02:59:43 +00:00
Update html/gamehub.ejs
This commit is contained in:
parent
b8ce39698a
commit
38094732ba
137
html/gamehub.ejs
137
html/gamehub.ejs
@ -175,13 +175,36 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link href="/css/yt-ukraine.svg?v=4" rel="icon">
|
<link href="/css/yt-ukraine.svg?v=4" rel="icon">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Tic-Tac-Toe</title>
|
<title>Tic-Tac-Toe</title>
|
||||||
<style>
|
<style>
|
||||||
body{margin:0;font-family:'PokeTube Flex';display:flex;align-items:center;justify-content:center;height:100vh;background:linear-gradient(135deg,#2c3e50,#34495e);color:#fff;}
|
body {
|
||||||
#board{display:grid;grid-template:repeat(3,100px)/repeat(3,100px);gap:5px;}
|
margin: 0;
|
||||||
.cell{display:flex;align-items:center;justify-content:center;font-size:2em;background:#fff2;cursor:pointer;}
|
font-family: 'PokeTube Flex', sans-serif;
|
||||||
#message{text-align:center;margin-bottom:1rem;}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
background: linear-gradient(135deg, #2c3e50, #34495e);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#board {
|
||||||
|
display: grid;
|
||||||
|
grid-template: repeat(3, 100px) / repeat(3, 100px);
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
.cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 2em;
|
||||||
|
background: rgba(255,255,255,0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#message {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -191,34 +214,90 @@
|
|||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
// GPL header omitted—see top of file
|
// GPL header omitted—see top of file
|
||||||
const boardEl=document.getElementById('board'), msgEl=document.getElementById('message');
|
const boardEl = document.getElementById('board');
|
||||||
let board=Array(9).fill(''), player='X';
|
const msgEl = document.getElementById('message');
|
||||||
function render(){
|
|
||||||
boardEl.innerHTML='';
|
let board = Array(9).fill('');
|
||||||
board.forEach((v,i)=>{
|
let currentPlayer = 'X';
|
||||||
const c=document.createElement('div');
|
|
||||||
c.className='cell'; c.textContent=v;
|
function checkWin() {
|
||||||
c.onclick=()=>move(i);
|
const lines = [
|
||||||
boardEl.append(c);
|
[0,1,2],[3,4,5],[6,7,8],
|
||||||
|
[0,3,6],[1,4,7],[2,5,8],
|
||||||
|
[0,4,8],[2,4,6]
|
||||||
|
];
|
||||||
|
return lines.some(l => l.every(i => board[i] && board[i] === board[l[0]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkDraw() {
|
||||||
|
return board.every(cell => cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBoard() {
|
||||||
|
boardEl.innerHTML = '';
|
||||||
|
board.forEach((val, idx) => {
|
||||||
|
const cell = document.createElement('div');
|
||||||
|
cell.className = 'cell';
|
||||||
|
cell.textContent = val;
|
||||||
|
cell.onclick = () => handleMove(idx);
|
||||||
|
boardEl.append(cell);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function move(i){
|
|
||||||
if(board[i]||win()||draw())return;
|
function handleMove(idx) {
|
||||||
board[i]=player;
|
if (board[idx] || checkWin() || checkDraw()) return;
|
||||||
if(win()){ msgEl.textContent=`Player ${player} won!!!!!! woaah`; }
|
|
||||||
else if(draw()){ msgEl.textContent="It's a draw! oh welp >~<"; }
|
board[idx] = currentPlayer;
|
||||||
else{ player=player==='X'?'O':'X'; msgEl.textContent=`Player ${player}’s turn :3`; if(player==='O')setTimeout(ai,300); }
|
renderBoard();
|
||||||
render();
|
|
||||||
|
if (checkWin()) {
|
||||||
|
msgEl.textContent = `Player ${currentPlayer} won!!!!!! woaah`;
|
||||||
|
} else if (checkDraw()) {
|
||||||
|
msgEl.textContent = "It's a draw! oh welp >~<";
|
||||||
|
} else {
|
||||||
|
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
|
||||||
|
msgEl.textContent = `Player ${currentPlayer}’s turn :3`;
|
||||||
|
|
||||||
|
if (currentPlayer === 'O') {
|
||||||
|
setTimeout(aiMove, 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function win(){ return [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]].some(l=>l.every(i=>board[i]&&board[i]===board[l[0]])); }
|
|
||||||
function draw(){ return board.every(v=>v); }
|
function aiMove() {
|
||||||
function ai(){
|
// 1) Try to win
|
||||||
const tryMv=p=>board.findIndex((v,i)=>!v&&(board[i]=p,win())&&(board[i]='',true));
|
for (let i = 0; i < 9; i++) {
|
||||||
let idx=tryMv('O')||tryMv('X');
|
if (!board[i]) {
|
||||||
if(idx<0) idx=board.map((v,i)=>v?'':i).filter(i=>i)[0];
|
board[i] = 'O';
|
||||||
move(idx);
|
if (checkWin()) {
|
||||||
|
handleMove(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
board[i] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2) Block X
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
if (!board[i]) {
|
||||||
|
board[i] = 'X';
|
||||||
|
if (checkWin()) {
|
||||||
|
board[i] = 'O';
|
||||||
|
handleMove(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
board[i] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3) Random
|
||||||
|
const empties = board
|
||||||
|
.map((v,i) => v === '' ? i : null)
|
||||||
|
.filter(i => i !== null);
|
||||||
|
const choice = empties[Math.floor(Math.random() * empties.length)];
|
||||||
|
handleMove(choice);
|
||||||
}
|
}
|
||||||
render();
|
|
||||||
|
// Initial render
|
||||||
|
renderBoard();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user