五子棋游戏完整项目文档

本文档包含一个完整的五子棋游戏实现,所有代码和说明都在文档内。您可以直接复制文档中的代码创建一个HTML文件并运行,无需其他文件支持。

项目概述

这是一个纯前端实现的五子棋游戏,具有以下特点:

  • 标准15×15棋盘布局
  • 黑白交替落子机制
  • 自动胜负判定功能
  • 响应式设计,适配各种设备
  • 无依赖,单文件即可运行
  • 内置QR码显示功能

游戏预览

以下是游戏界面的文本表示:

复制代码
+-------------------------------------------+
|              五子棋游戏                    |
+-------------------------------------------+
|  当前玩家: 黑棋     游戏状态: 进行中       |
+-------------------------------------------+
|                                           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . X . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . O . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|   . . . . . . . . . . . . . . .           |
|                                           |
+-------------------------------------------+
|  [重新开始]     [保存游戏]                 |
+-------------------------------------------+

完整代码实现

下面是完整的五子棋游戏HTML代码,包含所有必要的HTML结构、CSS样式和JavaScript逻辑:

html 复制代码
<!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>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
            flex-direction: column;
        }
        
        .game-container {
            background-color: #fff;
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.1);
            padding: 20px;
            max-width: 500px;
            width: 100%;
        }
        
        .game-title {
            text-align: center;
            color: #8B4513;
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 20px;
        }
        
        .game-info {
            display: flex;
            justify-content: space-between;
            margin-bottom: 20px;
            padding: 10px;
            background-color: #f9f9f9;
            border-radius: 5px;
        }
        
        .player-info, .game-status {
            font-weight: bold;
        }
        
        .board {
            display: grid;
            grid-template-columns: repeat(15, 1fr);
            grid-template-rows: repeat(15, 1fr);
            gap: 1px;
            background-color: #E5C100;
            border: 10px solid #E5C100;
            border-radius: 8px;
            margin-bottom: 20px;
            position: relative;
            width: 100%;
            aspect-ratio: 1/1;
            box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
        }
        
        .cell {
            background-color: transparent;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            position: relative;
        }
        
        .cell::before {
            content: '';
            position: absolute;
            width: 100%;
            height: 1px;
            background-color: rgba(0,0,0,0.3);
            top: 50%;
        }
        
        .cell::after {
            content: '';
            position: absolute;
            width: 1px;
            height: 100%;
            background-color: rgba(0,0,0,0.3);
            left: 50%;
        }
        
        .cell:first-child::before,
        .cell:nth-child(15n)::before,
        .cell:nth-child(-n+15)::after,
        .cell:nth-child(15n+1)::after {
            display: none;
        }
        
        .piece {
            width: 70%;
            height: 70%;
            border-radius: 50%;
            position: relative;
            z-index: 1;
            animation: fadeIn 0.3s ease-in-out;
        }
        
        .piece.black {
            background-color: #000;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
        }
        
        .piece.white {
            background-color: #fff;
            border: 1px solid #ddd;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
        }
        
        .controls {
            display: flex;
            justify-content: space-around;
            margin-bottom: 20px;
        }
        
        .btn {
            padding: 10px 20px;
            font-size: 16px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            background-color: #8B4513;
            color: white;
            font-weight: bold;
            transition: background-color 0.3s;
        }
        
        .btn:hover {
            background-color: #6B3411;
        }
        
        .qrcode-section {
            text-align: center;
            margin-top: 20px;
        }
        
        .qrcode-title {
            margin-bottom: 15px;
            color: #666;
        }
        
        .qrcode {
            width: 200px;
            height: 200px;
            margin: 0 auto;
            border: 1px solid #ddd;
            background-color: #fff;
            display: grid;
            grid-template-columns: repeat(25, 1fr);
            grid-template-rows: repeat(25, 1fr);
            gap: 0;
        }
        
        .qrcode-cell {
            width: 100%;
            height: 100%;
        }
        
        .qrcode-cell.black {
            background-color: #000;
        }
        
        .qrcode-cell.white {
            background-color: #fff;
        }
        
        .download-instructions {
            margin-top: 15px;
            font-size: 14px;
            color: #666;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: scale(0.5); }
            to { opacity: 1; transform: scale(1); }
        }
        
        /* 响应式设计 */
        @media (max-width: 500px) {
            .game-container {
                margin: 10px;
                padding: 15px;
            }
            
            .game-info {
                flex-direction: column;
                gap: 10px;
            }
            
            .qrcode {
                width: 150px;
                height: 150px;
            }
        }
        
        /* 胜利提示 */
        .win-message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 24px;
            font-weight: bold;
            z-index: 1000;
            display: none;
            animation: slideIn 0.3s ease-out;
        }
        
        @keyframes slideIn {
            from { 
                opacity: 0;
                transform: translate(-50%, -60%);
            }
            to { 
                opacity: 1;
                transform: translate(-50%, -50%);
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1 class="game-title">五子棋游戏</h1>
        
        <div class="game-info">
            <div class="player-info">当前玩家: <span id="current-player">黑棋</span></div>
            <div class="game-status">游戏状态: <span id="status">进行中</span></div>
        </div>
        
        <div class="board" id="board"></div>
        
        <div class="controls">
            <button class="btn" id="restart-btn">重新开始</button>
            <button class="btn" id="save-btn">保存游戏</button>
        </div>
        
        <div class="qrcode-section">
            <h3 class="qrcode-title">手机扫码下载游戏</h3>
            <div class="qrcode" id="qrcode"></div>
            <div class="download-instructions">
                提示:使用手机扫描左侧二维码即可在手机上下载并游玩此游戏。
                或直接保存此HTML文件到您的设备上,双击即可运行。
            </div>
        </div>
    </div>
    
    <div class="win-message" id="win-message"></div>
    
    <script>
        // 游戏核心变量
        const BOARD_SIZE = 15;
        let gameBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(0)); // 0: 空, 1: 黑, 2: 白
        let currentPlayer = 1; // 1: 黑, 2: 白
        let gameOver = false;
        
        // DOM 元素
        const boardElement = document.getElementById('board');
        const currentPlayerElement = document.getElementById('current-player');
        const statusElement = document.getElementById('status');
        const restartBtn = document.getElementById('restart-btn');
        const saveBtn = document.getElementById('save-btn');
        const winMessageElement = document.getElementById('win-message');
        const qrcodeElement = document.getElementById('qrcode');
        
        // 初始化棋盘
        function initializeBoard() {
            boardElement.innerHTML = '';
            
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    const cell = document.createElement('div');
                    cell.classList.add('cell');
                    cell.dataset.row = row;
                    cell.dataset.col = col;
                    cell.addEventListener('click', () => handleCellClick(row, col));
                    boardElement.appendChild(cell);
                }
            }
        }
        
        // 处理单元格点击
        function handleCellClick(row, col) {
            if (gameOver || gameBoard[row][col] !== 0) {
                return;
            }
            
            // 落子
            gameBoard[row][col] = currentPlayer;
            updateBoard();
            
            // 检查胜负
            if (checkWin(row, col)) {
                gameOver = true;
                const winner = currentPlayer === 1 ? '黑棋' : '白棋';
                statusElement.textContent = `${winner}获胜!`;
                showWinMessage(`${winner}获胜!`);
                return;
            }
            
            // 检查平局
            if (checkDraw()) {
                gameOver = true;
                statusElement.textContent = '平局!';
                showWinMessage('平局!');
                return;
            }
            
            // 切换玩家
            currentPlayer = currentPlayer === 1 ? 2 : 1;
            currentPlayerElement.textContent = currentPlayer === 1 ? '黑棋' : '白棋';
        }
        
        // 更新棋盘显示
        function updateBoard() {
            const cells = boardElement.querySelectorAll('.cell');
            
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    const index = row * BOARD_SIZE + col;
                    const cell = cells[index];
                    
                    // 清除现有棋子
                    const existingPiece = cell.querySelector('.piece');
                    if (existingPiece) {
                        cell.removeChild(existingPiece);
                    }
                    
                    // 添加新棋子
                    if (gameBoard[row][col] !== 0) {
                        const piece = document.createElement('div');
                        piece.classList.add('piece');
                        piece.classList.add(gameBoard[row][col] === 1 ? 'black' : 'white');
                        cell.appendChild(piece);
                    }
                }
            }
        }
        
        // 检查胜负
        function checkWin(row, col) {
            const directions = [
                [0, 1],  // 水平
                [1, 0],  // 垂直
                [1, 1],  // 对角线
                [1, -1]  // 反对角线
            ];
            
            const player = gameBoard[row][col];
            
            for (const [dx, dy] of directions) {
                let count = 1;
                
                // 正方向检查
                for (let i = 1; i < 5; i++) {
                    const newRow = row + i * dx;
                    const newCol = col + i * dy;
                    if (isValidPosition(newRow, newCol) && gameBoard[newRow][newCol] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                
                // 反方向检查
                for (let i = 1; i < 5; i++) {
                    const newRow = row - i * dx;
                    const newCol = col - i * dy;
                    if (isValidPosition(newRow, newCol) && gameBoard[newRow][newCol] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                
                // 五子连珠判定
                if (count >= 5) {
                    return true;
                }
            }
            
            return false;
        }
        
        // 检查位置是否有效
        function isValidPosition(row, col) {
            return row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE;
        }
        
        // 检查平局
        function checkDraw() {
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    if (gameBoard[row][col] === 0) {
                        return false; // 还有空位
                    }
                }
            }
            return true; // 棋盘已满
        }
        
        // 显示胜利消息
        function showWinMessage(message) {
            winMessageElement.textContent = message;
            winMessageElement.style.display = 'block';
            setTimeout(() => {
                winMessageElement.style.display = 'none';
            }, 3000);
        }
        
        // 重新开始游戏
        function restartGame() {
            gameBoard = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(0));
            currentPlayer = 1;
            gameOver = false;
            currentPlayerElement.textContent = '黑棋';
            statusElement.textContent = '进行中';
            updateBoard();
        }
        
        // 保存游戏(提示用户下载文件)
        function saveGame() {
            // 创建游戏数据
            const gameData = {
                gameBoard,
                currentPlayer,
                gameOver,
                timestamp: new Date().toISOString()
            };
            
            // 转换为HTML内容
            const htmlContent = `<!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>
        /* 这里放置与原页面相同的CSS样式 */
        ${document.querySelector('style').textContent}
    </style>
</head>
<body>
    <div class="game-container">
        <h1 class="game-title">五子棋游戏</h1>
        
        <div class="game-info">
            <div class="player-info">当前玩家: <span id="current-player">${currentPlayer === 1 ? '黑棋' : '白棋'}</span></div>
            <div class="game-status">游戏状态: <span id="status">${gameOver ? (currentPlayer === 1 ? '黑棋获胜!' : '白棋获胜!') : '进行中'}</span></div>
        </div>
        
        <div class="board" id="board"></div>
        
        <div class="controls">
            <button class="btn" id="restart-btn">重新开始</button>
            <button class="btn" id="save-btn">保存游戏</button>
        </div>
    </div>
    
    <div class="win-message" id="win-message"></div>
    
    <script>
        // 游戏数据
        const savedGameData = ${JSON.stringify(gameData)};
        
        // 这里放置与原页面相同的JavaScript代码
        ${document.querySelector('script').textContent.replace(/const gameBoard = .*?;\s*const currentPlayer = .*?;\s*const gameOver = .*?;/, 
            `let gameBoard = savedGameData.gameBoard;\n        let currentPlayer = savedGameData.currentPlayer;\n        let gameOver = savedGameData.gameOver;`
        )}
        
        // 初始化时恢复游戏状态
        document.addEventListener('DOMContentLoaded', () => {
            initializeBoard();
            updateBoard();
            currentPlayerElement.textContent = currentPlayer === 1 ? '黑棋' : '白棋';
            statusElement.textContent = gameOver ? (currentPlayer === 1 ? '黑棋获胜!' : '白棋获胜!') : '进行中';
            
            // 重新绑定事件
            restartBtn.addEventListener('click', restartGame);
            saveBtn.addEventListener('click', saveGame);
        });
    </script>
</body>
</html>`;
            
            // 创建下载链接
            const blob = new Blob([htmlContent], { type: 'text/html' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `五子棋游戏_${new Date().toLocaleDateString()}.html`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }
        
        // 生成模拟QR码
        function generateQRCode() {
            qrcodeElement.innerHTML = '';
            
            // 创建25x25的QR码网格
            for (let row = 0; row < 25; row++) {
                for (let col = 0; col < 25; col++) {
                    const cell = document.createElement('div');
                    cell.classList.add('qrcode-cell');
                    
                    // 创建QR码的三个定位图案
                    const isTopLeftFinder = row < 7 && col < 7 && !(row > 1 && row < 5 && col > 1 && col < 5);
                    const isTopRightFinder = row < 7 && col > 17 && !(row > 1 && row < 5 && col > 19 && col < 23);
                    const isBottomLeftFinder = row > 17 && col < 7 && !(row > 19 && row < 23 && col > 1 && col < 5);
                    
                    // 添加一些随机模式以模拟数据
                    const isRandomBlack = Math.random() > 0.6;
                    
                    if (isTopLeftFinder || isTopRightFinder || isBottomLeftFinder || 
                        (row === 0 || row === 24 || col === 0 || col === 24) || isRandomBlack) {
                        cell.classList.add('black');
                    } else {
                        cell.classList.add('white');
                    }
                    
                    qrcodeElement.appendChild(cell);
                }
            }
        }
        
        // 事件监听器
        restartBtn.addEventListener('click', restartGame);
        saveBtn.addEventListener('click', saveGame);
        
        // 初始化游戏
        document.addEventListener('DOMContentLoaded', () => {
            initializeBoard();
            generateQRCode();
        });
    </script>
</body>
</html>

代码解析

游戏核心逻辑

  1. 游戏状态管理 :使用二维数组 gameBoard 存储棋盘状态,0表示空位,1表示黑棋,2表示白棋。

  2. 胜负判定算法

    javascript 复制代码
    function checkWin(row, col) {
        const directions = [[0, 1], [1, 0], [1, 1], [1, -1]]; // 四个方向
        const player = gameBoard[row][col];
        
        for (const [dx, dy] of directions) {
            let count = 1;
            // 正方向检查
            for (let i = 1; i < 5; i++) {
                // 检查相邻格子
            }
            // 反方向检查
            for (let i = 1; i < 5; i++) {
                // 检查相邻格子
            }
            // 五子连珠判定
            if (count >= 5) {
                return true;
            }
        }
        return false;
    }
  3. 落子机制:当用户点击棋盘空位时,在对应位置放置当前玩家的棋子,并切换玩家。

用户界面设计

  1. 响应式布局:使用CSS Grid和媒体查询实现,确保在不同设备上都有良好的显示效果。

  2. 视觉效果

    • 木质棋盘背景
    • 棋子放置动画
    • 胜负提示动画
    • 清晰的游戏状态显示
  3. QR码显示:使用CSS Grid创建模拟的QR码图案,提供视觉上的扫码效果。

游戏功能扩展

  1. 游戏保存:将当前游戏状态保存为HTML文件,用户可以下载并在下次打开时恢复游戏。

  2. 重新开始:一键重置游戏状态,开始新游戏。

  3. 平局检测:当棋盘填满且无胜负时自动判定为平局。

使用说明

  1. 创建游戏文件

    • 复制上面的完整HTML代码
    • 粘贴到文本编辑器中
    • 保存为 .html 文件(例如:五子棋游戏.html
  2. 运行游戏

    • 双击保存的HTML文件,在浏览器中打开
    • 游戏会自动加载并准备就绪
  3. 游戏规则

    • 黑棋先行,点击棋盘交叉点放置棋子
    • 连成五子者获胜(横、竖、对角线均可)
    • 棋盘填满且无胜负时判定为平局
  4. 操作按钮

    • 「重新开始」:重置游戏状态
    • 「保存游戏」:下载当前游戏状态
  5. 分享与下载

    • 使用手机扫描页面中的QR码(视觉模拟)
    • 或直接保存HTML文件到设备

技术特点

  1. 纯前端实现:仅使用HTML、CSS和JavaScript,无需后端支持

  2. 无外部依赖:不依赖任何第三方库或框架,单文件即可运行

  3. 离线可用:下载后可在无网络环境下运行

  4. 响应式设计:适配桌面、平板和手机等各种设备

  5. 游戏状态持久化:通过保存HTML文件实现游戏进度保存

  6. 视觉反馈:提供丰富的动画和状态提示

项目总结

本五子棋游戏项目展示了如何使用基础的Web技术创建一个完整、功能丰富的游戏应用。项目的最大特点是独立性和可移植性,用户只需一个HTML文件即可在任何设备上运行游戏。

游戏实现了标准五子棋规则,包括黑白交替落子、胜负判定等核心功能,并通过精心设计的UI提供了良好的用户体验。同时,项目还展示了如何在不依赖外部库的情况下实现游戏状态保存和QR码模拟显示等功能。

这个项目不仅是一个简单的游戏,更是前端开发技术的综合应用示例,展示了HTML、CSS和JavaScript在游戏开发中的强大能力。

相关推荐
游了个戏1 小时前
微信小游戏 vs QQ小游戏:表面是兄弟,骨子里是两套完全不同的玩法
人工智能·游戏·微信
Swift社区2 小时前
鸿蒙游戏,会不会重演微信小游戏的爆发?
游戏·微信·harmonyos
前端不太难2 小时前
鸿蒙游戏的 CI/CD 方案
游戏·ci/cd·harmonyos
魔士于安14 小时前
unity urp材质球大全
游戏·unity·游戏引擎·材质·贴图·模型
Swift社区15 小时前
鸿蒙游戏 UI 怎么设计才不乱?
游戏·ui·harmonyos
Swift社区21 小时前
鸿蒙游戏中的“智能 NPC”架构设计
游戏·华为·harmonyos
王杨游戏养站系统1 天前
3分钟!玩转游戏下载站系统!蜘蛛池seo功能完善部署!
游戏·游戏下载站养站系统·游戏养站系统
魔士于安1 天前
unity 低多边形 无人小村 木质建筑 晾衣架 盆子手推车,桌子椅子,罐子,水井
游戏·unity·游戏引擎·贴图·模型
魔士于安1 天前
unity 骷髅人 连招 武器 刀光 扭曲空气
游戏·unity·游戏引擎·贴图·模型
前端不太难1 天前
为什么 AI 游戏更适合鸿蒙?
人工智能·游戏·harmonyos