当前位置: 首页 > news >正文

徐州网站制作如何定位大连企业自助建站

徐州网站制作如何定位,大连企业自助建站,上海企业网络营销推广服务,年终总结汇报ppt模板免费引言 在 Web 开发的世界里#xff0c;通过 HTML、CSS 和 JavaScript 可以创造出各种各样有趣的互动游戏。今天#xff0c;我们将深入探讨如何实现一个简单而又富有挑战性的五子棋人机对战游戏。这个游戏不仅能让你重温经典的五子棋玩法#xff0c;还能通过 AI 对战功能给你…引言 在 Web 开发的世界里通过 HTML、CSS 和 JavaScript 可以创造出各种各样有趣的互动游戏。今天我们将深入探讨如何实现一个简单而又富有挑战性的五子棋人机对战游戏。这个游戏不仅能让你重温经典的五子棋玩法还能通过 AI 对战功能给你带来全新的挑战。 项目概述 五子棋游戏将采用 HTML 构建页面结构CSS 进行样式设计JavaScript 实现游戏的逻辑和交互。整个游戏界面将包含一个棋盘、游戏状态信息、控制按钮以及胜利提示模态框等元素。 效果图  界面设计 开发中使用了 Tailwind CSS 框架来快速搭建界面。以下是界面的主要组成部分 游戏标题和描述在页面顶部显示游戏的标题和简单描述让玩家快速了解游戏内容。游戏区域使用 canvas 元素绘制棋盘玩家可以通过点击棋盘上的交叉点来落子。游戏信息面板显示当前回合、游戏时间、步数和游戏模式等信息方便玩家了解游戏状态。游戏规则说明列出五子棋的基本规则帮助新手玩家快速上手。控制按钮提供重新开始、悔棋、切换游戏模式等功能增强游戏的交互性。胜利提示模态框当游戏结束时显示获胜方信息并提供开始新游戏的按钮。 游戏逻辑实现 JavaScript 部分是游戏的核心负责处理游戏的各种逻辑包括棋盘绘制、落子处理、胜利判断和 AI 对战等功能。 棋盘绘制 使用 canvas 的绘图 API 绘制棋盘的网格线、天元和星位并根据游戏状态绘制棋子。以下是绘制棋盘的代码片段 // 绘制棋盘 function drawBoard() {ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制网格线ctx.strokeStyle #8B4513;ctx.lineWidth 1.5;for (let i 0; i BOARD_SIZE; i) {// 水平线ctx.beginPath();ctx.moveTo(0, i * CELL_SIZE);ctx.lineTo(canvas.width, i * CELL_SIZE);ctx.stroke();// 垂直线ctx.beginPath();ctx.moveTo(i * CELL_SIZE, 0);ctx.lineTo(i * CELL_SIZE, canvas.height);ctx.stroke();}// 绘制天元和星位const starPoints [{x: 3, y: 3}, {x: 3, y: 11}, {x: 7, y: 7}, {x: 11, y: 3}, {x: 11, y: 11}];starPoints.forEach(point {ctx.beginPath();ctx.arc(point.x * CELL_SIZE, point.y * CELL_SIZE, 4, 0, Math.PI * 2);ctx.fillStyle #8B4513;ctx.fill();});// 绘制棋子for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] ! 0) {drawPiece(i, j, gameBoard[i][j]);}}} } 落子处理 当玩家点击棋盘时程序会计算点击位置对应的格子坐标并检查该位置是否合法。如果合法则在该位置落子并更新游戏状态。以下是处理点击事件的代码片段 // 点击棋盘事件 function handleCanvasClick(e) {if (!gameActive) return;// 如果是AI模式且当前是AI回合不允许玩家落子if (isAiMode currentPlayer ! playerPiece) {return;}const rect canvas.getBoundingClientRect();const scaleX canvas.width / rect.width;const scaleY canvas.height / rect.height;// 计算点击的格子坐标const x (e.clientX - rect.left) * scaleX;const y (e.clientY - rect.top) * scaleY;const col Math.round(x / CELL_SIZE);const row Math.round(y / CELL_SIZE);// 检查坐标是否在棋盘内且为空if (row 0 row BOARD_SIZE col 0 col BOARD_SIZE gameBoard[row][col] 0) {// 落子gameBoard[row][col] currentPlayer;moveHistory.push({ row, col, player: currentPlayer });// 添加落子动画效果drawBoard();// 检查是否胜利if (checkWin(row, col, currentPlayer)) {showWinModal(currentPlayer);return;}// 检查是否平局if (checkDraw()) {gameActive false;stopTimer();statusText.textContent 游戏结束 - 平局!;return;}// 切换玩家currentPlayer currentPlayer 1 ? 2 : 1;updateGameStatus();// 如果是AI模式且现在是AI回合让AI落子if (isAiMode currentPlayer ! playerPiece) {setTimeout(makeAiMove, 500);}} } 胜利判断 在每次落子后程序会检查是否有一方在横、竖或斜方向形成五子连线。如果有则判定该方获胜。以下是检查胜利条件的代码片段 // 检查胜利条件 function checkWin(row, col, player) {const directions [[1, 0], // 水平[0, 1], // 垂直[1, 1], // 对角线[1, -1] // 反对角线];for (const [dx, dy] of directions) {let count 1; // 当前位置已经有一个棋子// 正向检查for (let i 1; i 5; i) {const newRow row i * dy;const newCol col i * dx;if (newRow 0 || newRow BOARD_SIZE || newCol 0 || newCol BOARD_SIZE) {break;}if (gameBoard[newRow][newCol] player) {count;} else {break;}}// 反向检查for (let i 1; i 5; i) {const newRow row - i * dy;const newCol col - i * dx;if (newRow 0 || newRow BOARD_SIZE || newCol 0 || newCol BOARD_SIZE) {break;}if (gameBoard[newRow][newCol] player) {count;} else {break;}}if (count 5) {return true;}}return false; } AI 对战 AI 对战是游戏的亮点之一。我们使用了一个简单的评估函数来评估棋盘状态并通过遍历所有可能的落子位置选择得分最高的位置作为最佳落子位置。以下是 AI 相关的代码片段 // AI落子 function makeAiMove() {if (!gameActive || !isAiMode || currentPlayer playerPiece) {return;}showAiThinking();// 模拟AI思考时间setTimeout(() {const aiPiece playerPiece 1 ? 2 : 1;const bestMove findBestMove(aiPiece);if (bestMove) {const { row, col } bestMove;// 落子gameBoard[row][col] aiPiece;moveHistory.push({ row, col, player: aiPiece });// 添加落子动画效果drawBoard();// 检查是否胜利if (checkWin(row, col, aiPiece)) {hideAiThinking();showWinModal(aiPiece);return;}// 检查是否平局if (checkDraw()) {gameActive false;stopTimer();statusText.textContent 游戏结束 - 平局!;hideAiThinking();return;}// 切换玩家currentPlayer playerPiece;updateGameStatus();hideAiThinking();}}, 800); }// AI评估函数 - 评估棋盘状态的分数 function evaluateBoard(player) {const opponent player 1 ? 2 : 1;let score 0;// 检查所有可能的5连位置for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] 0) {continue;}// 四个方向检查const directions [[1, 0], // 水平[0, 1], // 垂直[1, 1], // 对角线[1, -1] // 反对角线];for (const [dx, dy] of directions) {// 检查是否会超出边界if (i 4 * dy BOARD_SIZE || i 4 * dy 0 || j 4 * dx BOARD_SIZE || j 4 * dx 0) {continue;}// 计算当前方向的连子数let count 1;let emptySpaces 0;let blockedEnds 0;// 正向检查for (let k 1; k 5; k) {const row i k * dy;const col j k * dx;if (gameBoard[row][col] gameBoard[i][j]) {count;} else if (gameBoard[row][col] 0) {emptySpaces;break;} else {blockedEnds;break;}}// 反向检查for (let k 1; k 5; k) {const row i - k * dy;const col j - k * dx;if (gameBoard[row][col] gameBoard[i][j]) {count;} else if (gameBoard[row][col] 0) {emptySpaces;break;} else {blockedEnds;break;}}// 如果两端都被堵这条线无效if (blockedEnds 2) {continue;}// 根据连子数和开放端计算分数const isPlayerPiece gameBoard[i][j] player;let lineScore 0;if (count 5) {lineScore isPlayerPiece ? 10000 : -10000; // 胜利} else if (count 4) {if (emptySpaces 2) {lineScore isPlayerPiece ? 1000 : -1000; // 活四} else if (emptySpaces 1) {lineScore isPlayerPiece ? 100 : -100; // 冲四}} else if (count 3) {if (emptySpaces 2) {lineScore isPlayerPiece ? 100 : -100; // 活三} else if (emptySpaces 1) {lineScore isPlayerPiece ? 10 : -10; // 冲三}} else if (count 2) {if (emptySpaces 2) {lineScore isPlayerPiece ? 5 : -5; // 活二} else if (emptySpaces 1) {lineScore isPlayerPiece ? 1 : -1; // 冲二}}score lineScore;}}}return score; }// AI寻找最佳落子位置 function findBestMove(player) {const opponent player 1 ? 2 : 1;let bestScore -Infinity;let bestMove null;// 只考虑已有棋子周围的空位const possibleMoves getPossibleMoves();for (const { row, col } of possibleMoves) {// 尝试落子gameBoard[row][col] player;// 检查是否直接获胜if (checkWin(row, col, player)) {gameBoard[row][col] 0; // 恢复棋盘return { row, col };}// 评估这个位置的分数let score evaluateBoard(player);// 恢复棋盘gameBoard[row][col] 0;// 更新最佳移动if (score bestScore) {bestScore score;bestMove { row, col };}}// 如果没有找到最佳移动随机选择一个空位if (!bestMove possibleMoves.length 0) {const randomIndex Math.floor(Math.random() * possibleMoves.length);return possibleMoves[randomIndex];}// 如果棋盘为空选择中心点if (!bestMove) {return { row: Math.floor(BOARD_SIZE / 2), col: Math.floor(BOARD_SIZE / 2) };}return bestMove; } 完整代码 !DOCTYPE html html langzh-CN headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title五子棋游戏/titlescript srchttps://cdn.tailwindcss.com/scriptlink hrefhttps://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css relstylesheetscripttailwind.config {theme: {extend: {colors: {primary: #8B5A2B,secondary: #D2B48C,board: #DEB887,black: #000000,white: #FFFFFF,ai: #FF6B6B,},fontFamily: {sans: [Inter, system-ui, sans-serif],},}}}/scriptstyle typetext/tailwindcsslayer utilities {.content-auto {content-visibility: auto;}.board-grid {background-size: 100% 100%;background-image: linear-gradient(to right, rgba(0,0,0,0.6) 1px, transparent 1px),linear-gradient(to bottom, rgba(0,0,0,0.6) 1px, transparent 1px);}.piece-shadow {filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));}.piece-transition {transition: all 0.2s ease-out;}.btn-hover {transition: all 0.2s ease;}.btn-hover:hover {transform: translateY(-2px);box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);}.pulse-animation {animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;}keyframes pulse {0%, 100% {opacity: 1;}50% {opacity: 0.5;}}}/style /head body classbg-gray-100 min-h-screen flex flex-col items-center justify-center p-4 font-sansdiv classmax-w-4xl w-full bg-white rounded-2xl shadow-xl overflow-hiddendiv classbg-primary text-white p-6 text-centerh1 classtext-[clamp(1.5rem,3vw,2.5rem)] font-bold五子棋/h1p classtext-secondary mt-2经典对弈游戏/p/divdiv classp-6 md:p-8 flex flex-col md:flex-row gap-6!-- 游戏区域 --div classflex-1 relativediv classaspect-square bg-board rounded-lg shadow-lg overflow-hidden board-grid stylebackground-size: calc(100% / 14) calc(100% / 14);canvas idgameCanvas classw-full h-full cursor-pointer/canvas/divdiv idgameStatus classmt-4 p-3 bg-secondary/20 rounded-lg text-centerp idstatusText classfont-medium游戏开始! 黑棋先行/p/div/div!-- 游戏控制和信息 --div classw-full md:w-80 flex flex-col gap-6div classbg-gray-50 rounded-lg p-5 shadow-smh2 classtext-lg font-semibold mb-3 flex items-centeri classfa-solid fa-info-circle mr-2 text-primary/i游戏信息/h2div classspace-y-3div classflex items-center justify-betweenspan classtext-gray-600当前回合/spandiv classflex items-centerdiv idcurrentPlayer classw-6 h-6 rounded-full bg-black mr-2 piece-shadow/divspan idplayerText黑棋/span/div/divdiv classflex items-center justify-betweenspan classtext-gray-600游戏时间/spanspan idgameTime classfont-mono00:00/span/divdiv classflex items-center justify-betweenspan classtext-gray-600步数/spanspan idmoveCount0/span/divdiv classflex items-center justify-betweenspan classtext-gray-600游戏模式/spandiv idgameMode classflex items-centerdiv classw-3 h-3 rounded-full bg-green-500 mr-2/divspan idmodeText人机对战/span/div/div/div/divdiv classbg-gray-50 rounded-lg p-5 shadow-smh2 classtext-lg font-semibold mb-3 flex items-centeri classfa-solid fa-crown mr-2 text-primary/i游戏规则/h2ul classtext-sm text-gray-600 space-y-2li classflex items-starti classfa-solid fa-circle text-xs mt-1.5 mr-2 text-primary/ispan黑棋和白棋轮流在棋盘上落子/span/lili classflex items-starti classfa-solid fa-circle text-xs mt-1.5 mr-2 text-primary/ispan先在横、竖或斜方向形成五子连线者获胜/span/lili classflex items-starti classfa-solid fa-circle text-xs mt-1.5 mr-2 text-primary/ispan点击棋盘上的交叉点放置棋子/span/li/ul/divdiv classflex flex-col gap-3div classflex gap-3button idrestartBtn classflex-1 bg-primary hover:bg-primary/90 text-white py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-centeri classfa-solid fa-refresh mr-2/i重新开始/buttonbutton idundoBtn classflex-1 bg-gray-200 hover:bg-gray-300 text-gray-700 py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-centeri classfa-solid fa-undo mr-2/i悔棋/button/divdiv classflex gap-3button idhumanBtn classflex-1 bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-centeri classfa-solid fa-user mr-2/i人人对战/buttonbutton idaiBtn classflex-1 bg-green-500 hover:bg-green-600 text-white py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-centeri classfa-solid fa-robot mr-2/i人机对战/button/div/div/div/divdiv classbg-gray-50 p-4 text-center text-sm text-gray-500p© 2025 五子棋游戏 | 一个简单的 Web 游戏/p/div/div!-- 胜利提示模态框 --div idwinModal classfixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden opacity-0 transition-opacity duration-300div classbg-white rounded-xl p-8 max-w-md w-full mx-4 transform transition-transform duration-300 scale-95div classtext-centerdiv classw-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4i classfa-solid fa-trophy text-3xl text-yellow-500/i/divh2 classtext-2xl font-bold mb-2 idwinnerText黑棋获胜!/h2p classtext-gray-600 mb-6恭喜您赢得了这场精彩的比赛!/pbutton idnewGameBtn classbg-primary hover:bg-primary/90 text-white py-3 px-8 rounded-lg font-medium btn-hover开始新游戏/button/div/div/div!-- AI思考提示 --div idaiThinking classfixed inset-0 bg-black/30 flex items-center justify-center z-40 hiddendiv classbg-white rounded-xl p-6 max-w-xs w-full mx-4 flex items-centerdiv classmr-4i classfa-solid fa-circle-notch fa-spin text-2xl text-primary/i/divdivh3 classfont-bold text-lgAI思考中/h3p classtext-gray-600 text-sm电脑正在思考下一步.../p/div/div/divscriptdocument.addEventListener(DOMContentLoaded, () {// 游戏常量const BOARD_SIZE 15; // 15x15的棋盘const CELL_SIZE Math.min(window.innerWidth * 0.8 / BOARD_SIZE, window.innerHeight * 0.6 / BOARD_SIZE);const PIECE_SIZE CELL_SIZE * 0.8;// 游戏状态let gameBoard Array(BOARD_SIZE).fill().map(() Array(BOARD_SIZE).fill(0));let currentPlayer 1; // 1: 黑棋, 2: 白棋let gameActive true;let moveHistory [];let gameTime 0;let timerInterval;let isAiMode true; // 默认开启AI模式let playerPiece 1; // 玩家默认执黑// DOM元素const canvas document.getElementById(gameCanvas);const ctx canvas.getContext(2d);const statusText document.getElementById(statusText);const currentPlayerEl document.getElementById(currentPlayer);const playerText document.getElementById(playerText);const moveCountEl document.getElementById(moveCount);const gameTimeEl document.getElementById(gameTime);const restartBtn document.getElementById(restartBtn);const undoBtn document.getElementById(undoBtn);const winModal document.getElementById(winModal);const winnerText document.getElementById(winnerText);const newGameBtn document.getElementById(newGameBtn);const aiBtn document.getElementById(aiBtn);const humanBtn document.getElementById(humanBtn);const gameMode document.getElementById(gameMode);const modeText document.getElementById(modeText);const aiThinking document.getElementById(aiThinking);// 设置Canvas尺寸canvas.width CELL_SIZE * (BOARD_SIZE - 1);canvas.height CELL_SIZE * (BOARD_SIZE - 1);// 绘制棋盘function drawBoard() {ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制网格线ctx.strokeStyle #8B4513;ctx.lineWidth 1.5;for (let i 0; i BOARD_SIZE; i) {// 水平线ctx.beginPath();ctx.moveTo(0, i * CELL_SIZE);ctx.lineTo(canvas.width, i * CELL_SIZE);ctx.stroke();// 垂直线ctx.beginPath();ctx.moveTo(i * CELL_SIZE, 0);ctx.lineTo(i * CELL_SIZE, canvas.height);ctx.stroke();}// 绘制天元和星位const starPoints [{x: 3, y: 3}, {x: 3, y: 11}, {x: 7, y: 7}, {x: 11, y: 3}, {x: 11, y: 11}];starPoints.forEach(point {ctx.beginPath();ctx.arc(point.x * CELL_SIZE, point.y * CELL_SIZE, 4, 0, Math.PI * 2);ctx.fillStyle #8B4513;ctx.fill();});// 绘制棋子for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] ! 0) {drawPiece(i, j, gameBoard[i][j]);}}}}// 绘制棋子function drawPiece(row, col, player) {const x col * CELL_SIZE;const y row * CELL_SIZE;// 棋子阴影ctx.beginPath();ctx.arc(x, y, PIECE_SIZE / 2 2, 0, Math.PI * 2);ctx.fillStyle rgba(0, 0, 0, 0.2);ctx.fill();// 棋子本体ctx.beginPath();ctx.arc(x, y, PIECE_SIZE / 2, 0, Math.PI * 2);if (player 1) {// 黑棋 - 渐变效果const gradient ctx.createRadialGradient(x - PIECE_SIZE / 6, y - PIECE_SIZE / 6, PIECE_SIZE / 10,x, y, PIECE_SIZE / 2);gradient.addColorStop(0, #555);gradient.addColorStop(1, #000);ctx.fillStyle gradient;} else if (player 2) {// 白棋 - 渐变效果const gradient ctx.createRadialGradient(x - PIECE_SIZE / 6, y - PIECE_SIZE / 6, PIECE_SIZE / 10,x, y, PIECE_SIZE / 2);gradient.addColorStop(0, #fff);gradient.addColorStop(1, #ddd);ctx.fillStyle gradient;}ctx.fill();// 棋子边缘ctx.strokeStyle player 1 ? #333 : #ccc;ctx.lineWidth 1;ctx.stroke();}// 检查胜利条件function checkWin(row, col, player) {const directions [[1, 0], // 水平[0, 1], // 垂直[1, 1], // 对角线[1, -1] // 反对角线];for (const [dx, dy] of directions) {let count 1; // 当前位置已经有一个棋子// 正向检查for (let i 1; i 5; i) {const newRow row i * dy;const newCol col i * dx;if (newRow 0 || newRow BOARD_SIZE || newCol 0 || newCol BOARD_SIZE) {break;}if (gameBoard[newRow][newCol] player) {count;} else {break;}}// 反向检查for (let i 1; i 5; i) {const newRow row - i * dy;const newCol col - i * dx;if (newRow 0 || newRow BOARD_SIZE || newCol 0 || newCol BOARD_SIZE) {break;}if (gameBoard[newRow][newCol] player) {count;} else {break;}}if (count 5) {return true;}}return false;}// 检查平局function checkDraw() {for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] 0) {return false; // 还有空位不是平局}}}return true; // 棋盘已满平局}// 更新游戏状态显示function updateGameStatus() {if (gameActive) {if (isAiMode currentPlayer ! playerPiece) {statusText.textContent 游戏进行中 - AI思考中...;currentPlayerEl.className w-6 h-6 rounded-full ${currentPlayer 1 ? bg-black : bg-white border border-gray-300} mr-2 piece-shadow pulse-animation;playerText.textContent AI;} else {statusText.textContent 游戏进行中 - ${currentPlayer 1 ? 黑棋 : 白棋}回合;currentPlayerEl.className w-6 h-6 rounded-full ${currentPlayer 1 ? bg-black : bg-white border border-gray-300} mr-2 piece-shadow;playerText.textContent currentPlayer 1 ? 黑棋 : 白棋;}}moveCountEl.textContent moveHistory.length;}// 更新游戏时间function updateGameTime() {gameTime;const minutes Math.floor(gameTime / 60).toString().padStart(2, 0);const seconds (gameTime % 60).toString().padStart(2, 0);gameTimeEl.textContent ${minutes}:${seconds};}// 开始计时function startTimer() {clearInterval(timerInterval);timerInterval setInterval(updateGameTime, 1000);}// 停止计时function stopTimer() {clearInterval(timerInterval);}// 显示胜利模态框function showWinModal(winner) {gameActive false;stopTimer();let winnerTextContent ;if (isAiMode) {winnerTextContent winner playerPiece ? 恭喜您获胜! : AI获胜!;} else {winnerTextContent ${winner 1 ? 黑棋 : 白棋}获胜!;}winnerText.textContent winnerTextContent;winModal.classList.remove(hidden);// 添加动画效果setTimeout(() {winModal.classList.add(opacity-100);winModal.querySelector(div).classList.remove(scale-95);winModal.querySelector(div).classList.add(scale-100);}, 10);}// 隐藏胜利模态框function hideWinModal() {winModal.classList.remove(opacity-100);winModal.querySelector(div).classList.remove(scale-100);winModal.querySelector(div).classList.add(scale-95);setTimeout(() {winModal.classList.add(hidden);}, 300);}// 重置游戏function resetGame() {gameBoard Array(BOARD_SIZE).fill().map(() Array(BOARD_SIZE).fill(0));currentPlayer 1;gameActive true;moveHistory [];gameTime 0;drawBoard();updateGameStatus();gameTimeEl.textContent 00:00;stopTimer();startTimer();hideWinModal();// 如果是AI模式且玩家执白让AI先行if (isAiMode playerPiece 2) {setTimeout(makeAiMove, 500);}}// 悔棋function undoMove() {if (moveHistory.length 0 || !gameActive) {return;}// 如果是AI模式需要撤销两步玩家一步AI一步if (isAiMode moveHistory.length 2) {for (let i 0; i 2; i) {const lastMove moveHistory.pop();gameBoard[lastMove.row][lastMove.col] 0;currentPlayer lastMove.player; // 回到上一个玩家}} else if (!isAiMode) {const lastMove moveHistory.pop();gameBoard[lastMove.row][lastMove.col] 0;currentPlayer lastMove.player; // 回到上一个玩家}drawBoard();updateGameStatus();}// 显示AI思考提示function showAiThinking() {aiThinking.classList.remove(hidden);setTimeout(() {aiThinking.classList.add(opacity-100);}, 10);}// 隐藏AI思考提示function hideAiThinking() {aiThinking.classList.remove(opacity-100);setTimeout(() {aiThinking.classList.add(hidden);}, 300);}// AI落子function makeAiMove() {if (!gameActive || !isAiMode || currentPlayer playerPiece) {return;}showAiThinking();// 模拟AI思考时间setTimeout(() {const aiPiece playerPiece 1 ? 2 : 1;const bestMove findBestMove(aiPiece);if (bestMove) {const { row, col } bestMove;// 落子gameBoard[row][col] aiPiece;moveHistory.push({ row, col, player: aiPiece });// 添加落子动画效果drawBoard();// 检查是否胜利if (checkWin(row, col, aiPiece)) {hideAiThinking();showWinModal(aiPiece);return;}// 检查是否平局if (checkDraw()) {gameActive false;stopTimer();statusText.textContent 游戏结束 - 平局!;hideAiThinking();return;}// 切换玩家currentPlayer playerPiece;updateGameStatus();hideAiThinking();}}, 800);}// AI评估函数 - 评估棋盘状态的分数function evaluateBoard(player) {const opponent player 1 ? 2 : 1;let score 0;// 检查所有可能的5连位置for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] 0) {continue;}// 四个方向检查const directions [[1, 0], // 水平[0, 1], // 垂直[1, 1], // 对角线[1, -1] // 反对角线];for (const [dx, dy] of directions) {// 检查是否会超出边界if (i 4 * dy BOARD_SIZE || i 4 * dy 0 || j 4 * dx BOARD_SIZE || j 4 * dx 0) {continue;}// 计算当前方向的连子数let count 1;let emptySpaces 0;let blockedEnds 0;// 正向检查for (let k 1; k 5; k) {const row i k * dy;const col j k * dx;if (gameBoard[row][col] gameBoard[i][j]) {count;} else if (gameBoard[row][col] 0) {emptySpaces;break;} else {blockedEnds;break;}}// 反向检查for (let k 1; k 5; k) {const row i - k * dy;const col j - k * dx;if (gameBoard[row][col] gameBoard[i][j]) {count;} else if (gameBoard[row][col] 0) {emptySpaces;break;} else {blockedEnds;break;}}// 如果两端都被堵这条线无效if (blockedEnds 2) {continue;}// 根据连子数和开放端计算分数const isPlayerPiece gameBoard[i][j] player;let lineScore 0;if (count 5) {lineScore isPlayerPiece ? 10000 : -10000; // 胜利} else if (count 4) {if (emptySpaces 2) {lineScore isPlayerPiece ? 1000 : -1000; // 活四} else if (emptySpaces 1) {lineScore isPlayerPiece ? 100 : -100; // 冲四}} else if (count 3) {if (emptySpaces 2) {lineScore isPlayerPiece ? 100 : -100; // 活三} else if (emptySpaces 1) {lineScore isPlayerPiece ? 10 : -10; // 冲三}} else if (count 2) {if (emptySpaces 2) {lineScore isPlayerPiece ? 5 : -5; // 活二} else if (emptySpaces 1) {lineScore isPlayerPiece ? 1 : -1; // 冲二}}score lineScore;}}}return score;}// AI寻找最佳落子位置function findBestMove(player) {const opponent player 1 ? 2 : 1;let bestScore -Infinity;let bestMove null;// 只考虑已有棋子周围的空位const possibleMoves getPossibleMoves();for (const { row, col } of possibleMoves) {// 尝试落子gameBoard[row][col] player;// 检查是否直接获胜if (checkWin(row, col, player)) {gameBoard[row][col] 0; // 恢复棋盘return { row, col };}// 评估这个位置的分数let score evaluateBoard(player);// 恢复棋盘gameBoard[row][col] 0;// 更新最佳移动if (score bestScore) {bestScore score;bestMove { row, col };}}// 如果没有找到最佳移动随机选择一个空位if (!bestMove possibleMoves.length 0) {const randomIndex Math.floor(Math.random() * possibleMoves.length);return possibleMoves[randomIndex];}// 如果棋盘为空选择中心点if (!bestMove) {return { row: Math.floor(BOARD_SIZE / 2), col: Math.floor(BOARD_SIZE / 2) };}return bestMove;}// 获取所有可能的落子位置已有棋子周围的空位function getPossibleMoves() {const moves [];const directions [[0, 1], [1, 0], [1, 1], [1, -1],[0, -1], [-1, 0], [-1, -1], [-1, 1]];// 先检查是否有任何棋子let hasPieces false;for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] ! 0) {hasPieces true;break;}}if (hasPieces) break;}// 如果棋盘为空返回中心点if (!hasPieces) {return [{ row: Math.floor(BOARD_SIZE / 2), col: Math.floor(BOARD_SIZE / 2) }];}// 检查已有棋子周围的空位for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] ! 0) {// 检查周围8个方向for (const [dx, dy] of directions) {const newRow i dy;const newCol j dx;// 检查是否在棋盘内且为空if (newRow 0 newRow BOARD_SIZE newCol 0 newCol BOARD_SIZE gameBoard[newRow][newCol] 0) {// 避免重复添加const isDuplicate moves.some(move move.row newRow move.col newCol);if (!isDuplicate) {moves.push({ row: newRow, col: newCol });}}}}}}// 如果没有找到周围的空位返回所有空位if (moves.length 0) {for (let i 0; i BOARD_SIZE; i) {for (let j 0; j BOARD_SIZE; j) {if (gameBoard[i][j] 0) {moves.push({ row: i, col: j });}}}}return moves;}// 点击棋盘事件function handleCanvasClick(e) {if (!gameActive) return;// 如果是AI模式且当前是AI回合不允许玩家落子if (isAiMode currentPlayer ! playerPiece) {return;}const rect canvas.getBoundingClientRect();const scaleX canvas.width / rect.width;const scaleY canvas.height / rect.height;// 计算点击的格子坐标const x (e.clientX - rect.left) * scaleX;const y (e.clientY - rect.top) * scaleY;const col Math.round(x / CELL_SIZE);const row Math.round(y / CELL_SIZE);// 检查坐标是否在棋盘内且为空if (row 0 row BOARD_SIZE col 0 col BOARD_SIZE gameBoard[row][col] 0) {// 落子gameBoard[row][col] currentPlayer;moveHistory.push({ row, col, player: currentPlayer });// 添加落子动画效果drawBoard();// 检查是否胜利if (checkWin(row, col, currentPlayer)) {showWinModal(currentPlayer);return;}// 检查是否平局if (checkDraw()) {gameActive false;stopTimer();statusText.textContent 游戏结束 - 平局!;return;}// 切换玩家currentPlayer currentPlayer 1 ? 2 : 1;updateGameStatus();// 如果是AI模式且现在是AI回合让AI落子if (isAiMode currentPlayer ! playerPiece) {setTimeout(makeAiMove, 500);}}}// 切换到人机对战模式function switchToAiMode() {isAiMode true;playerPiece 1; // 默认玩家执黑modeText.textContent 人机对战;gameMode.querySelector(div).className w-3 h-3 rounded-full bg-green-500 mr-2;aiBtn.className flex-1 bg-green-500 hover:bg-green-600 text-white py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-center;humanBtn.className flex-1 bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-center;resetGame();}// 切换到人人对战模式function switchToHumanMode() {isAiMode false;modeText.textContent 人人对战;gameMode.querySelector(div).className w-3 h-3 rounded-full bg-blue-500 mr-2;aiBtn.className flex-1 bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-center;humanBtn.className flex-1 bg-blue-500 hover:bg-blue-600 text-white py-3 px-4 rounded-lg font-medium btn-hover flex items-center justify-center;resetGame();}// 事件监听canvas.addEventListener(click, handleCanvasClick);restartBtn.addEventListener(click, resetGame);undoBtn.addEventListener(click, undoMove);newGameBtn.addEventListener(click, resetGame);aiBtn.addEventListener(click, switchToAiMode);humanBtn.addEventListener(click, switchToHumanMode);// 鼠标悬停预览效果canvas.addEventListener(mousemove, (e) {if (!gameActive) return;// 如果是AI模式且当前是AI回合不显示预览if (isAiMode currentPlayer ! playerPiece) {return;}const rect canvas.getBoundingClientRect();const scaleX canvas.width / rect.width;const scaleY canvas.height / rect.height;// 计算鼠标所在的格子坐标const x (e.clientX - rect.left) * scaleX;const y (e.clientY - rect.top) * scaleY;const col Math.round(x / CELL_SIZE);const row Math.round(y / CELL_SIZE);// 清除之前的预览drawBoard();// 如果坐标在棋盘内且为空绘制预览棋子if (row 0 row BOARD_SIZE col 0 col BOARD_SIZE gameBoard[row][col] 0) {ctx.beginPath();ctx.arc(col * CELL_SIZE, row * CELL_SIZE, PIECE_SIZE / 2, 0, Math.PI * 2);if (currentPlayer 1) {ctx.fillStyle rgba(0, 0, 0, 0.3);} else {ctx.fillStyle rgba(255, 255, 255, 0.6);}ctx.fill();}});// 鼠标离开棋盘时重绘canvas.addEventListener(mouseleave, () {drawBoard();});// 初始化游戏drawBoard();updateGameStatus();startTimer();});/script /body /html 总结 通过 HTML、CSS 和 JavaScript 的组合实现了一个功能丰富的五子棋人机对战游戏。这个游戏不仅具有基本的五子棋玩法还通过 AI 对战功能增加了游戏的趣味性和挑战性。在开发过程中我们学习了如何使用 canvas 进行图形绘制如何处理用户交互事件以及如何实现简单的 AI 算法。希望这篇文章能对你有所帮助让你在 Web 开发的道路上更进一步。 你可以根据自己的需求对游戏进行扩展和优化例如添加更复杂的 AI 算法、改进界面设计、增加游戏音效等。祝你在开发过程中取得成功
http://www.dnsts.com.cn/news/28696.html

相关文章:

  • 建站快车加盟wordpress主题升级文件
  • 宁波网站制作公司有哪些公司
  • 个人备案用作资讯网站网站框架优化
  • 黄页推广网站下载山东青岛网站设计
  • 网站内链工作做足佛山网站建设与设计
  • seo网站优化价格找人做网站需要问哪些问题
  • wordpress去除谷歌字体北京网优化seo公司
  • 色块网站北京网络营销公司网页
  • 音乐网站开发思路flash网站怎么做音乐停止
  • 做搜狗pc网站企业网站的建设对于网络品牌的塑造作用
  • 中山建站青岛建设工程信息网站
  • 阆中网站建设01hl南宁网站设计多少钱
  • 建站 赚钱关键词全网搜索指数
  • t型布局网站的样子网站排名top排行榜
  • 天水网站seowordpress 极简 模板
  • 电影推荐算法 网站开发响应式布局怎么实现
  • 有没有帮忙做推广的网站dede网站文章同步
  • 对网站的界面设计分析关注公众号赚钱
  • 广东水利建设与管理信息网站凡科的网站做seo比较难
  • 北京企业建站模板北京企业名录大全
  • 怎样做号网站优化鲜花网站建设企划书
  • 济南网站建设与优化上海房产网最新楼盘
  • 有专门做ppt的网站怎么做推广和宣传
  • 做耳标网站画册设计1p一般多少钱
  • dw做的网站如何使用制作企业宣传片的厂家
  • 网站建设建设公司是干嘛的网站模板红黑
  • 浙江金顶建设公司网站网站买空间
  • 仿珠宝首饰网站开发深圳营销网站有限公司
  • 手机微网站开发的目的和意义最全磁力搜索引擎
  • 南通专业网站排名推广卢松松wordpress模板