news 2026/5/30 18:52:07

脚本网页 三人四字棋

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
脚本网页 三人四字棋

博主闲得无聊,自己摸鱼做了一个游戏

<!DOCTYPE html> <html lang="zh-CN"> <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 { font-family: 'Microsoft YaHei', sans-serif; background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%); min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 10px; } header { text-align: center; margin-bottom: 15px; width: 100%; max-width: 500px; } .stats { background: rgba(255,255,255,0.9); padding: 10px 20px; border-radius: 20px; display: inline-block; margin-bottom: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .stats span { margin: 0 10px; font-weight: bold; color: #2c3e50; } h1 { color: white; font-size: 2em; text-shadow: 2px 2px 4px rgba(0,0,0,0.2); } .players-info { display: flex; gap: 20px; margin-bottom: 15px; background: rgba(255,255,255,0.9); padding: 10px 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .player { display: flex; align-items: center; gap: 8px; font-size: 0.9em; font-weight: bold; } .player-indicator { width: 25px; height: 25px; border-radius: 50%; transition: all 0.3s; } .player1 { background: linear-gradient(135deg, #667eea, #764ba2); } .player2 { background: linear-gradient(135deg, #f093fb, #f5576c); } .player3 { background: linear-gradient(135deg, #4facfe, #00f2fe); } .current-turn { transform: scale(1.3); box-shadow: 0 0 15px rgba(255,215,0,0.8); } main { background: rgba(255,255,255,0.95); padding: 15px; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.1); max-width: 500px; width: 100%; } #board { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; background: #34495e; padding: 8px; border-radius: 10px; aspect-ratio: 1; } .cell { background: #ecf0f1; cursor: pointer; position: relative; border-radius: 3px; aspect-ratio: 1; } .cell:hover:not(.occupied) { background: #bdc3c7; transform: scale(1.05); } .piece { width: 80%; height: 80%; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); animation: dropIn 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.3); } @keyframes dropIn { from { transform: translate(-50%, -50%) scale(0); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } } .winning-piece { animation: pulse 1s infinite; } @keyframes pulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(1.2); } } .controls { margin-top: 15px; text-align: center; } button { padding: 10px 20px; font-size: 14px; font-weight: bold; border: none; border-radius: 8px; cursor: pointer; background: linear-gradient(135deg, #667eea, #764ba2); color: white; transition: all 0.3s; } button:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.2); } .status { margin-top: 15px; text-align: center; font-size: 1.1em; font-weight: bold; color: #2c3e50; min-height: 25px; } .winner { color: #27ae60; animation: celebrate 0.5s ease; } @keyframes celebrate { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } @media (max-width: 500px) { #board { max-width: 90vw; } } </style> </head> <body> <header> <div class="stats"> <span>胜: <span id="wins">0</span></span> <span>负: <span id="losses">0</span></span> <span>平: <span id="draws">0</span></span> </div> <h1>三人四子棋</h1> </header> <div class="players-info"> <div class="player"> <div class="player-indicator player1" id="indicator1"></div> <span>你</span> </div> <div class="player"> <div class="player-indicator player2" id="indicator2"></div> <span>凤九歌</span> </div> <div class="player"> <div class="player-indicator player3" id="indicator3"></div> <span>凉安</span> </div> </div> <main> <div id="board"></div> <div class="controls"> <button onclick="resetGame()">重新开始</button> </div> <div class="status" id="status"></div> </main> <script> const BOARD_SIZE = 10; const WIN_COUNT = 4; let board, currentPlayer, gameOver; const players = { 1: { name: '你', class: 'player1' }, 2: { name: '凤九歌', class: 'player2' }, 3: { name: '凉安', class: 'player3' } }; function initGame() { board = Array(BOARD_SIZE).fill(null).map(() => Array(BOARD_SIZE).fill(null)); currentPlayer = 1; gameOver = false; createBoard(); updateStatus(''); updateTurnIndicator(); } function createBoard() { const boardEl = document.getElementById('board'); boardEl.innerHTML = ''; for (let row = 0; row < BOARD_SIZE; row++) { for (let col = 0; col < BOARD_SIZE; col++) { const cell = document.createElement('div'); cell.className = 'cell'; cell.dataset.row = row; cell.dataset.col = col; cell.onclick = () => handleCellClick(row, col); boardEl.appendChild(cell); } } } function handleCellClick(row, col) { if (gameOver || currentPlayer !== 1 || board[row][col]) return; makeMove(row, col, 1); if (!gameOver) setTimeout(aiTurn, 500); } function makeMove(row, col, player) { board[row][col] = player; const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`); cell.classList.add('occupied'); cell.innerHTML = `<div class="piece ${players[player].class}"></div>`; if (checkWin(row, col, player)) { gameOver = true; highlightWinning(row, col, player); updateStatus(`${players[player].name} 获胜!`, true); updateStats(player); } else if (isBoardFull()) { gameOver = true; updateStatus('平局!', true); updateStats(0); } else { currentPlayer = currentPlayer % 3 + 1; updateTurnIndicator(); } } function checkWin(row, col, player) { const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]]; for (const dir of dirs) { let count = 1; for (const [dr, dc] of dir) { let r = row + dr, c = col + dc; while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) { count++; r += dr; c += dc; } } if (count >= WIN_COUNT) return true; } return false; } function highlightWinning(row, col, player) { const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]]; for (const dir of dirs) { let pieces = [{row, col}]; let count = 1; for (const [dr, dc] of dir) { let r = row + dr, c = col + dc; while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) { pieces.push({row: r, col: c}); count++; r += dr; c += dc; } } if (count >= WIN_COUNT) { pieces.forEach(pos => { const piece = document.querySelector(`[data-row="${pos.row}"][data-col="${pos.col}"] .piece`); if (piece) piece.classList.add('winning-piece'); }); return; } } } function isBoardFull() { return board.every(row => row.every(cell => cell !== null)); } function aiTurn() { if (gameOver) return; const move = currentPlayer === 2 ? findBestMove(2, true) : findBestMove(3, false); if (move) { makeMove(move.row, move.col, currentPlayer); if (!gameOver && currentPlayer !== 1) setTimeout(aiTurn, 500); } } function findBestMove(player, aggressive) { let move = findWinningMove(player); if (move) return move; if (aggressive) { for (let p of [1, 3]) { move = findWinningMove(p); if (move) return move; } } else { for (let p of [1, 2]) { move = findWinningMove(p); if (move) return move; } } let bestScore = -1, bestMove = null; for (let row = 0; row < BOARD_SIZE; row++) { for (let col = 0; col < BOARD_SIZE; col++) { if (!board[row][col]) { const score = evaluatePosition(row, col, player); if (score > bestScore) { bestScore = score; bestMove = {row, col}; } } } } return bestMove; } function findWinningMove(player) { for (let row = 0; row < BOARD_SIZE; row++) { for (let col = 0; col < BOARD_SIZE; col++) { if (!board[row][col]) { board[row][col] = player; if (checkWin(row, col, player)) { board[row][col] = null; return {row, col}; } board[row][col] = null; } } } return null; } function evaluatePosition(row, col, player) { let score = 0; const dirs = [[0,1], [1,0], [1,1], [1,-1]]; for (const [dr, dc] of dirs) { let count = 0, open = 0; for (const [rDir, cDir] of [[dr, dc], [-dr, -dc]]) { let r = row + rDir, c = col + cDir; while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) { if (board[r][c] === player) count++; else if (!board[r][c]) { open++; break; } else break; r += rDir; c += cDir; } } if (count >= 3) score += 100; else if (count === 2 && open >= 1) score += 10; else if (count === 1 && open >= 2) score += 1; } const center = BOARD_SIZE / 2; score += Math.max(0, 5 - (Math.abs(row - center) + Math.abs(col - center))); return score; } function updateTurnIndicator() { document.querySelectorAll('.player-indicator').forEach(el => el.classList.remove('current-turn')); document.getElementById(`indicator${currentPlayer}`).classList.add('current-turn'); } function updateStatus(msg, isWinner = false) { const status = document.getElementById('status'); status.textContent = msg; status.className = isWinner ? 'status winner' : 'status'; } function updateStats(winner) { const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}'); if (winner === 1) stats.wins++; else if (winner === 0) stats.draws++; else stats.losses++; localStorage.setItem('gameStats', JSON.stringify(stats)); document.getElementById('wins').textContent = stats.wins; document.getElementById('losses').textContent = stats.losses; document.getElementById('draws').textContent = stats.draws; } function loadStats() { const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}'); document.getElementById('wins').textContent = stats.wins; document.getElementById('losses').textContent = stats.losses; document.getElementById('draws').textContent = stats.draws; } function resetGame() { initGame(); } loadStats(); initGame(); </script> </body> </html>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/29 21:09:09

循环队列:出队

参考视频 5.双向链表_栈_队列_哔哩哔哩_bilibili1小时15分钟到最后&#xff08;顺序队列的知识&#xff09; 6.循环队列_讲题_递归_哔哩哔哩_bilibili前20分钟 题目 #include <stdio.h> #include <string.h> #include <stdlib.h>#define ElemType char #…

作者头像 李华
网站建设 2026/5/30 15:41:41

孩子的这些“小动作”,其实是近视前的信号灯!

在学业压力日益加剧的当下&#xff0c;“每天户外活动2小时”“减少连续近距离用眼时间”等儿童青少年近视防控建议&#xff0c;虽在理论层面无懈可击&#xff0c;却往往难以落地。孩子每天大部分时间处于室内学习状态&#xff0c;传统防控手段难以兼顾“有效”与“易于应用”的…

作者头像 李华
网站建设 2026/5/30 10:09:48

Langchain-Chatchat金融欺诈识别知识查询平台

Langchain-Chatchat金融欺诈识别知识查询平台 在金融风控一线&#xff0c;一个常见的场景是&#xff1a;客服接到客户咨询&#xff0c;“某企业法人突然频繁支取大额现金&#xff0c;是否需要上报&#xff1f;” 翻找内部手册、比对监管文件、确认历史案例……整个过程可能耗时…

作者头像 李华
网站建设 2026/5/30 15:47:44

昇腾CANN算子生成与融合深度解析:从原理到实战

在AI模型部署过程中&#xff0c;算子作为NPU执行计算的最小单元&#xff0c;其效率直接决定了模型的整体性能。昇腾CANN&#xff08;Compute Architecture for Neural Networks&#xff09;作为连接AI框架与昇腾NPU的核心桥梁&#xff0c;提供了强大的算子生成与融合能力&#…

作者头像 李华
网站建设 2026/5/28 19:33:23

Langchain-Chatchat GDPR数据主体权利问答系统

Langchain-Chatchat GDPR数据主体权利问答系统 在当今全球隐私监管日益严格的背景下&#xff0c;企业面对的合规压力正以前所未有的速度增长。以《通用数据保护条例》&#xff08;GDPR&#xff09;为代表的数据保护法规&#xff0c;不仅要求组织妥善处理个人数据&#xff0c;更…

作者头像 李华
网站建设 2026/5/30 16:29:41

Langchain-Chatchat银行柜面操作知识查询平台

Langchain-Chatchat银行柜面操作知识查询平台 在银行一线柜台&#xff0c;每天都会面对大量高频、专业且容错率极低的业务咨询&#xff1a;客户问“定期存款提前支取要带什么材料&#xff1f;”、“一类账户开户是否需要工作证明&#xff1f;”……传统方式下&#xff0c;柜员需…

作者头像 李华