欢迎光临
我们一直在努力

(文后附完整代码)html+css+javascript 五子棋项目分析报告

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎 点赞 + 收藏 + 关注 哦 💕

(文后附完整代码)html+css+javascript 五子棋项目分析报告

📚 效果展示

标题图片

📚 本文简介

本文介绍了一个使用HTML、CSS和JavaScript实现的五子棋游戏项目。该项目采用纯原生技术实现,包含15×15标准棋盘、三级AI难度、音效系统和现代化视觉效果。文章详细分析了项目的技术架构、核心功能模块、HTML结构、CSS样式设计以及JavaScript游戏逻辑实现。重点讲解了胜负判定算法、AI系统设计、Web Audio API音效实现等关键技术点。项目具有模块化设计、响应式布局、丰富的交互体验等特点,并提供了完整的代码实现。同时,文章还总结了项目的技术亮点,并提出了改进建议,如优化AI算法、增加多人模式等。该五子棋游戏是一个优秀的前端学习案例,展示了原生JavaScript开发复杂游戏的能力。

目录

  • (文后附完整代码)html+css+javascript 五子棋项目分析报告
    • 📚 效果展示
    • 📚 本文简介
    • 📚 一、项目架构概述
      • 📘 1.1 项目文件结构
      • 📘 1.2 技术栈分析
      • 📘 1.3 核心功能模块
    • 📚 二、HTML结构分析:语义化与模块化的界面搭建
      • 📘 2.1 整体布局设计
      • 📘 2.2 关键元素解析
        • 📖 2.2.1 游戏容器设计
        • 📖 2.2.2 棋盘结构
        • 📖 2.2.3 游戏信息区
        • 📖 2.2.4 控制面板
    • 📚 三、CSS样式设计:现代化视觉效果与交互体验
      • 📘 3.1 整体视觉风格
      • 📘 3.2 关键样式解析
        • 📖 3.2.1 响应式布局
        • 📖 3.2.2 棋盘样式
        • 📖 3.2.3 棋子样式
        • 📖 3.2.4 动画效果
      • 📘 3.3 视觉反馈设计
    • 📚 四、JavaScript核心逻辑:游戏引擎与AI实现
      • 📘 4.1 游戏状态管理
      • 📘 4.2 棋盘初始化与管理
        • 📖 4.2.1 棋盘创建
        • 📖 4.2.2 落子处理
      • 📘 4.3 胜负判定系统
        • 📖 4.3.1 核心算法
        • 📖 4.3.2 位置验证
      • 📘 4.4 AI系统设计
        • 📖 4.4.1 难度等级
        • 📖 4.4.2 困难AI实现
      • 📘 4.5 音效与特效系统
        • 📖 4.5.1 音效实现
        • 📖 4.5.2 视觉特效
      • 📘 4.6 背景音乐系统
        • 📖 4.6.1 音乐生成
        • 📖 4.6.2 音乐控制
    • 📚 五、技术特点与创新点
      • 📘 5.1 技术亮点
      • 📘 5.2 游戏体验优化
      • 📘 5.3 代码质量分析
    • 📚 六、总结与建议
      • 📘 6.1 项目价值
      • 📘 6.2 改进建议
      • 📘 6.3 技术拓展可能
    • 📚 七、结论
    • 📚 完整代码(可直接使用)
      • 📘 项目目录
      • 📘 项目代码
        • 📖 html代码
        • 📖 javascript代码

 

———— ⬇️·`正文开始`·⬇️————

 

📚 一、项目架构概述

📘 1.1 项目文件结构

项目采用简洁的文件组织结构,仅包含两个核心文件:

  • index.html:主页面文件,包含游戏的完整HTML结构、CSS样式和JavaScript逻辑
  • backgroundMusic.js:背景音乐模块,负责生成和管理游戏背景音乐

📘 1.2 技术栈分析

  • 前端技术:纯HTML5 + CSS3 + JavaScript
  • 音频处理:Web Audio API
  • 布局技术:Flexbox布局
  • 交互方式:DOM事件监听
  • 动画效果:CSS3动画

📘 1.3 核心功能模块

  • 棋盘系统:15×15标准五子棋棋盘
  • 落子系统:玩家与电脑交替落子
  • 胜负判定:基于规则的胜负检测
  • AI系统:三级难度的电脑AI
  • 音效系统:落子、胜利、重置等音效
  • 背景音乐系统:基于Web Audio API的动态音乐生成
  • 📚 二、HTML结构分析:语义化与模块化的界面搭建

    📘 2.1 整体布局设计

    项目采用响应式居中布局,通过Flexbox实现页面元素的垂直和水平居中。整体结构分为三个主要部分:

    • 游戏标题:位于页面顶部,显示游戏名称
    • 游戏信息区:包含玩家信息和难度选择
    • 棋盘区域:核心游戏区域
    • 控制区域:包含重新开始和音效控制按钮

    📘 2.2 关键元素解析

    📖 2.2.1 游戏容器设计

    使用.game-container作为主容器,采用半透明背景和阴影效果,营造出层次感和现代感。

    📖 2.2.2 棋盘结构

    棋盘采用动态生成的方式,通过JavaScript在#board容器中创建15×15的单元格网格。每个单元格使用.cell类,通过data-row和data-col属性存储坐标信息。

    📖 2.2.3 游戏信息区

    包含玩家状态显示和难度选择按钮,通过.player-info类标记玩家状态,.current-player类高亮当前回合的玩家。

    📖 2.2.4 控制面板

    提供游戏控制功能,包括重新开始和音效开关按钮,使用语义化的按钮元素和图标增强用户体验。

    📚 三、CSS样式设计:现代化视觉效果与交互体验

    📘 3.1 整体视觉风格

    采用现代简约风格,结合渐变背景、半透明效果和阴影,营造出层次感和深度。色彩方案以绿色为主色调,象征胜利和活力,搭配中性色增强可读性。

    📘 3.2 关键样式解析

    📖 3.2.1 响应式布局

    使用Flexbox实现页面元素的灵活布局,确保游戏在不同设备上都能良好显示。通过min-height: 100vh确保游戏容器始终居中显示。

    📖 3.2.2 棋盘样式

    棋盘采用木质纹理风格,通过#board的背景色和边框模拟真实棋盘效果。单元格使用border属性创建网格线,hover效果提供视觉反馈。

    📖 3.2.3 棋子样式

    通过CSS伪元素实现棋子效果:

    • 黑棋:使用●字符和黑色
    • 白棋:使用○字符和白色,配合阴影增强立体感
    📖 3.2.4 动画效果
    • 落子特效:使用CSS3动画实现棋子放置时的粒子效果
    • 胜利消息:实现淡入放大效果
    • 按钮交互:添加悬停和点击时的缩放和阴影变化

    📘 3.3 视觉反馈设计

    • 悬停效果:单元格和按钮在鼠标悬停时提供视觉反馈
    • 当前玩家高亮:通过背景色和缩放效果突出显示当前回合的玩家
    • 难度按钮状态:使用.active类标记当前选择的难度

    📚 四、JavaScript核心逻辑:游戏引擎与AI实现

    📘 4.1 游戏状态管理

    通过全局变量管理游戏状态:

    • board:二维数组存储棋盘状态
    • currentPlayer:当前玩家(‘black’或’white’)
    • gameOver:游戏是否结束
    • difficulty:当前AI难度
    • isPlayerTurn:是否为玩家回合

    📘 4.2 棋盘初始化与管理

    📖 4.2.1 棋盘创建

    initBoard()函数负责初始化棋盘:

    • 创建15×15的二维数组
    • 动态生成DOM元素构建棋盘网格
    • 绑定单元格点击事件
    • 重置游戏状态
    📖 4.2.2 落子处理

    handleCellClick()函数处理玩家落子:

    • 验证落子合法性
    • 更新棋盘状态
    • 播放落子音效
    • 添加落子特效
    • 检查胜负
    • 切换到电脑回合

    📘 4.3 胜负判定系统

    📖 4.3.1 核心算法

    checkWin()函数实现胜负判定:

    • 检查四个方向(水平、垂直、两个对角线)
    • 计算连续相同颜色的棋子数量
    • 当连续数量达到5时判定胜利
    📖 4.3.2 位置验证

    isValidPosition()函数确保坐标在棋盘范围内,防止数组越界。

    📘 4.4 AI系统设计

    📖 4.4.1 难度等级

    实现三级AI难度:

    • 简单:随机选择空格落子
    • 中等:优先防守,其次进攻
    • 困难:基于评分系统的智能落子
    📖 4.4.2 困难AI实现

    getHardMove()函数采用评估系统:

    • 遍历所有空格
    • 评估每个位置的落子价值
    • 考虑连珠情况和中心位置优势
    • 选择评分最高的位置落子

    📘 4.5 音效与特效系统

    📖 4.5.1 音效实现

    使用Web Audio API创建各种音效:

    • playDropSound():落子音效
    • playWinSound():胜利音效
    • playResetSound():重置音效
    📖 4.5.2 视觉特效
    • addDropEffect():落子特效
    • addWinEffect():胜利特效
    • showWinMessage():胜利消息显示

    📘 4.6 背景音乐系统

    📖 4.6.1 音乐生成

    backgroundMusic.js模块使用Web Audio API动态生成背景音乐:

    • 基于预设旋律生成科幻电子风格音乐
    • 使用方波和锯齿波创建激进的音效
    • 包含低音增强节奏感
    📖 4.6.2 音乐控制
    • startBackgroundMusic():开始播放背景音乐
    • stopBackgroundMusic():停止播放背景音乐
    • 音乐播放状态与游戏状态同步

    📚 五、技术特点与创新点

    📘 5.1 技术亮点

  • 纯原生实现:不依赖任何框架,使用纯JavaScript实现完整功能
  • Web Audio API应用:创造性地使用Web Audio API生成动态背景音乐
  • 模块化设计:将背景音乐功能分离为独立模块
  • 响应式布局:适配不同屏幕尺寸
  • 丰富的视觉效果:结合CSS3动画和JavaScript特效
  • 📘 5.2 游戏体验优化

  • 三级AI难度:满足不同水平玩家的需求
  • 即时视觉反馈:落子特效和状态指示
  • 沉浸式音效:增强游戏氛围
  • 流畅的动画:提升视觉体验
  • 清晰的胜负判定:明确的胜利消息和特效
  • 📘 5.3 代码质量分析

    • 代码结构清晰:模块化设计,函数职责明确
    • 命名规范:变量和函数命名语义化
    • 注释完善:关键逻辑有详细注释
    • 错误处理:包含基本的错误捕获
    • 性能优化:AI算法效率合理

    📚 六、总结与建议

    📘 6.1 项目价值

    本项目是一个功能完整、体验良好的五子棋游戏,具有以下价值:

    • 教育意义:展示了纯原生JavaScript实现复杂游戏的方法
    • 技术参考:Web Audio API的实际应用案例
    • 游戏体验:提供了一个可玩的五子棋游戏

    📘 6.2 改进建议

  • 代码分离:将CSS和JavaScript分离到独立文件,提高可维护性
  • AI优化:困难模式可考虑使用 minimax 算法进一步提升AI水平
  • 多人模式:增加双人对战功能
  • 本地存储:使用localStorage保存游戏设置和历史记录
  • 响应式优化:进一步优化移动设备体验
  • 棋子动画:添加更丰富的棋子放置动画
  • 📘 6.3 技术拓展可能

  • 网络对战:基于WebSocket实现网络对战
  • 自定义棋盘:支持不同大小的棋盘
  • 主题系统:支持切换游戏主题
  • 成就系统:添加游戏成就和统计
  • 教程模式:为新手提供游戏教程
  • 📚 七、结论

    本项目成功实现了一个功能完整、体验良好的五子棋游戏。通过纯原生JavaScript和Web Audio API,开发者展示了如何构建一个具有现代感的网页游戏。项目结构清晰,代码质量高,功能丰富,是一个优秀的前端小型游戏开发案例。

    游戏的核心功能包括标准的15×15棋盘、三级AI难度、完整的音效系统和现代化的视觉效果。虽然代码量不大,但实现了五子棋游戏的所有核心要素,同时在用户体验和视觉效果上做了不少优化。

    作为一个学习项目,它展示了如何将复杂的游戏逻辑分解为可管理的模块,如何使用Web Audio API创建动态音效,以及如何通过CSS3和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>
    * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    }

    body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    overflow: hidden;
    }

    .game-container {
    text-align: center;
    background: rgba(255, 255, 255, 0.95);
    padding: 20px;
    border-radius: 20px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    position: relative;
    }

    h1 {
    color: #333;
    margin-bottom: 20px;
    font-size: 2.5em;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
    }

    .game-info {
    display: flex;
    justify-content: space-around;
    margin-bottom: 20px;
    font-size: 1.2em;
    color: #555;
    }

    .player-info {
    padding: 10px 20px;
    border-radius: 10px;
    transition: all 0.3s ease;
    }

    .current-player {
    background: #4CAF50;
    color: white;
    transform: scale(1.1);
    box-shadow: 0 5px 15px rgba(76, 175, 80, 0.4);
    }

    #board {
    display: inline-block;
    background: #d4b996;
    border: 10px solid #8b4513;
    border-radius: 10px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
    position: relative;
    }

    .row {
    display: flex;
    }

    .cell {
    width: 40px;
    height: 40px;
    border: 1px solid #8b4513;
    cursor: pointer;
    position: relative;
    transition: all 0.2s ease;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 24px;
    }

    .cell:hover {
    background: rgba(255, 255, 255, 0.3);
    transform: scale(1.05);
    box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);
    }

    .cell.black::before {
    content: "●";
    color: #000;
    font-size: 36px;
    text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    }

    .cell.white::before {
    content: "○";
    color: #fff;
    font-size: 36px;
    text-shadow: 0 0 10px rgba(0, 0, 0, 0.5), 0 0 5px #000;
    }

    .effect {
    position: absolute;
    font-size: 40px;
    pointer-events: none;
    z-index: 100;
    animation: effect-animation 1s ease-out forwards;
    }

    @keyframes effect-animation {
    0% {
    opacity: 1;
    transform: scale(1) translateY(0);
    }
    50% {
    opacity: 0.8;
    transform: scale(1.5) translateY(-20px);
    }
    100% {
    opacity: 0;
    transform: scale(0.5) translateY(-40px);
    }
    }

    .btn {
    margin: 10px;
    padding: 10px 20px;
    font-size: 1.1em;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: all 0.3s ease;
    background: #4CAF50;
    color: white;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }

    .btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
    }

    .btn:active {
    transform: translateY(0);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }

    .btn.reset {
    background: #f44336;
    }

    .btn.sound {
    background: #2196F3;
    }

    .game-over {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0, 0, 0, 0.8);
    color: white;
    padding: 30px 50px;
    border-radius: 20px;
    font-size: 2em;
    z-index: 200;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
    animation: fadeIn 0.5s ease-out;
    }

    @keyframes fadeIn {
    from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.8);
    }
    to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    }
    }

    .difficulty-selector {
    margin: 20px 0;
    display: flex;
    justify-content: center;
    gap: 10px;
    }

    .difficulty-btn {
    padding: 8px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 1em;
    transition: all 0.3s ease;
    background: #2196F3;
    color: white;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }

    .difficulty-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(33, 150, 243, 0.4);
    }

    .difficulty-btn.active {
    background: #4CAF50;
    transform: scale(1.1);
    box-shadow: 0 5px 15px rgba(76, 175, 80, 0.4);
    }

    .control-panel {
    margin-top: 20px;
    }
    </style>
    </head>
    <body>
    <div class="game-container">
    <h1>🎮 五子棋游戏 🎮</h1>

    <div class="game-info">
    <div class="player-info current-player" id="player1">
    玩家 <span></span>
    </div>
    <div class="player-info" id="player2">
    电脑 <span></span>
    </div>
    </div>

    <div class="difficulty-selector">
    <button class="difficulty-btn active" onclick="setDifficulty('easy')">🧠 简单</button>
    <button class="difficulty-btn" onclick="setDifficulty('medium')">🤔 中等</button>
    <button class="difficulty-btn" onclick="setDifficulty('hard')">🧠💪 困难</button>
    </div>

    <div id="board"></div>

    <div class="control-panel">
    <button class="btn" onclick="resetGame()">🔄 重新开始</button>
    <button class="btn sound" onclick="toggleSound()">🔊 音效开关</button>
    </div>
    </div>

    <script src="backgroundMusic.js"></script>
    <script>
    // 游戏状态
    const BOARD_SIZE = 15;
    let board = [];
    let currentPlayer = 'black';
    let gameOver = false;
    let soundEnabled = true;
    let musicEnabled = true;
    let difficulty = 'easy'; // 难度级别:easy, medium, hard
    let isPlayerTurn = true; // 是否是玩家回合

    // Web Audio API
    let audioContext;
    let backgroundMusicGain;
    let soundGain;

    // 初始化游戏
    function initGame() {
    // 初始化音频上下文
    initAudioContext();

    // 初始化棋盘
    initBoard();

    // 开始背景音乐
    startMusic();
    }

    // 初始化音频上下文
    function initAudioContext() {
    audioContext = new (window.AudioContext || window.webkitAudioContext)();
    backgroundMusicGain = audioContext.createGain();
    soundGain = audioContext.createGain();

    backgroundMusicGain.connect(audioContext.destination);
    soundGain.connect(audioContext.destination);

    backgroundMusicGain.gain.value = 0.3;
    soundGain.gain.value = 0.5;

    // 初始化背景音乐模块
    initBackgroundMusic(audioContext, backgroundMusicGain);

    // 设置游戏状态获取函数
    setGameStateGetter(() => ({
    gameRunning: true,
    gamePaused: false,
    gameOver: gameOver
    }));
    }

    // 设置难度
    function setDifficulty(level) {
    difficulty = level;

    // 更新按钮状态
    const buttons = document.querySelectorAll('.difficulty-btn');
    buttons.forEach(btn => btn.classList.remove('active'));
    event.target.classList.add('active');

    // 重置游戏
    resetGame();
    }

    // 初始化棋盘
    function initBoard() {
    const boardElement = document.getElementById('board');
    boardElement.innerHTML = '';
    board = [];

    for (let i = 0; i < BOARD_SIZE; i++) {
    const row = [];
    const rowElement = document.createElement('div');
    rowElement.className = 'row';

    for (let j = 0; j < BOARD_SIZE; j++) {
    row.push(null);
    const cell = document.createElement('div');
    cell.className = 'cell';
    cell.dataset.row = i;
    cell.dataset.col = j;
    cell.addEventListener('click', handleCellClick);
    rowElement.appendChild(cell);
    }

    board.push(row);
    boardElement.appendChild(rowElement);
    }

    // 重置游戏状态
    currentPlayer = 'black';
    gameOver = false;
    isPlayerTurn = true;
    updatePlayerInfo();

    // 移除游戏结束弹窗
    const gameOverElement = document.querySelector('.game-over');
    if (gameOverElement) {
    gameOverElement.remove();
    }
    }

    // 处理单元格点击
    function handleCellClick(e) {
    if (gameOver || !isPlayerTurn) return;

    const row = parseInt(e.target.dataset.row);
    const col = parseInt(e.target.dataset.col);

    if (board[row][col]) return;

    // 落子
    board[row][col] = currentPlayer;
    e.target.classList.add(currentPlayer);

    // 播放落子音效
    playDropSound();

    // 添加落子特效
    addDropEffect(e.target, row, col);

    // 检查胜利
    if (checkWin(row, col)) {
    gameOver = true;
    showWinMessage();
    return;
    }

    // 切换到电脑回合
    currentPlayer = 'white';
    isPlayerTurn = false;
    updatePlayerInfo();

    // 电脑思考并落子
    setTimeout(() => {
    computerMove();
    }, 500); // 电脑思考时间
    }

    // 电脑落子
    function computerMove() {
    if (gameOver) return;

    let move;

    // 根据难度选择落子策略
    switch (difficulty) {
    case 'easy':
    move = getEasyMove();
    break;
    case 'medium':
    move = getMediumMove();
    break;
    case 'hard':
    move = getHardMove();
    break;
    default:
    move = getEasyMove();
    }

    if (move) {
    const { row, col } = move;
    const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);

    // 落子
    board[row][col] = currentPlayer;
    cell.classList.add(currentPlayer);

    // 播放落子音效
    playDropSound();

    // 添加落子特效
    addDropEffect(cell, row, col);

    // 检查胜利
    if (checkWin(row, col)) {
    gameOver = true;
    showWinMessage();
    return;
    }

    // 切换回玩家回合
    currentPlayer = 'black';
    isPlayerTurn = true;
    updatePlayerInfo();
    }
    }

    // 更新玩家信息
    function updatePlayerInfo() {
    const player1 = document.getElementById('player1');
    const player2 = document.getElementById('player2');

    if (currentPlayer === 'black') {
    player1.classList.add('current-player');
    player2.classList.remove('current-player');
    } else {
    player1.classList.remove('current-player');
    player2.classList.add('current-player');
    }
    }

    // 检查胜利
    function checkWin(row, col) {
    const directions = [
    [0, 1], // 水平
    [1, 0], // 垂直
    [1, 1], // 对角线
    [1, 1] // 反对角线
    ];

    for (const [dx, dy] of directions) {
    let count = 1;

    // 检查正方向
    for (let i = 1; i < 5; i++) {
    const newRow = row + dx * i;
    const newCol = col + dy * i;
    if (isValidPosition(newRow, newCol) && board[newRow][newCol] === currentPlayer) {
    count++;
    } else {
    break;
    }
    }

    // 检查反方向
    for (let i = 1; i < 5; i++) {
    const newRow = row dx * i;
    const newCol = col dy * i;
    if (isValidPosition(newRow, newCol) && board[newRow][newCol] === currentPlayer) {
    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 getEmptyCells() {
    const emptyCells = [];
    for (let i = 0; i < BOARD_SIZE; i++) {
    for (let j = 0; j < BOARD_SIZE; j++) {
    if (!board[i][j]) {
    emptyCells.push({ row: i, col: j });
    }
    }
    }
    return emptyCells;
    }

    // 简单难度:随机选择空格
    function getEasyMove() {
    const emptyCells = getEmptyCells();
    if (emptyCells.length === 0) return null;

    // 随机选择一个空格
    const randomIndex = Math.floor(Math.random() * emptyCells.length);
    return emptyCells[randomIndex];
    }

    // 中等难度:优先防守,然后进攻
    function getMediumMove() {
    const emptyCells = getEmptyCells();
    if (emptyCells.length === 0) return null;

    // 1. 检查是否有获胜机会
    for (const cell of emptyCells) {
    board[cell.row][cell.col] = 'white';
    if (checkWin(cell.row, cell.col)) {
    board[cell.row][cell.col] = null;
    return cell;
    }
    board[cell.row][cell.col] = null;
    }

    // 2. 检查是否需要防守
    for (const cell of emptyCells) {
    board[cell.row][cell.col] = 'black';
    if (checkWin(cell.row, cell.col)) {
    board[cell.row][cell.col] = null;
    return cell;
    }
    board[cell.row][cell.col] = null;
    }

    // 3. 随机选择
    const randomIndex = Math.floor(Math.random() * emptyCells.length);
    return emptyCells[randomIndex];
    }

    // 困难难度:评估所有可能的落子位置
    function getHardMove() {
    const emptyCells = getEmptyCells();
    if (emptyCells.length === 0) return null;

    let bestMove = null;
    let bestScore = Infinity;

    for (const cell of emptyCells) {
    // 计算落子评分
    const score = evaluateMove(cell.row, cell.col);

    if (score > bestScore) {
    bestScore = score;
    bestMove = cell;
    }
    }

    return bestMove;
    }

    // 评估落子位置的分数
    function evaluateMove(row, col) {
    let score = 0;

    // 检查电脑自己的连珠情况
    board[row][col] = 'white';
    if (checkWin(row, col)) {
    board[row][col] = null;
    return 10000; // 获胜棋,最高分
    }
    score += countConsecutive(row, col, 'white') * 10;
    board[row][col] = null;

    // 检查玩家的连珠情况
    board[row][col] = 'black';
    if (checkWin(row, col)) {
    board[row][col] = null;
    return 9000; // 必须防守,高分
    }
    score += countConsecutive(row, col, 'black') * 15;
    board[row][col] = null;

    // 中心位置加分
    const centerRow = Math.floor(BOARD_SIZE / 2);
    const centerCol = Math.floor(BOARD_SIZE / 2);
    const distanceToCenter = Math.abs(row centerRow) + Math.abs(col centerCol);
    score += (20 distanceToCenter) * 2;

    return score;
    }

    // 计算连珠数量
    function countConsecutive(row, col, player) {
    let maxCount = 0;
    const directions = [
    [0, 1], // 水平
    [1, 0], // 垂直
    [1, 1], // 对角线
    [1, 1] // 反对角线
    ];

    for (const [dx, dy] of directions) {
    let count = 1;

    // 检查正方向
    for (let i = 1; i < 5; i++) {
    const newRow = row + dx * i;
    const newCol = col + dy * i;
    if (isValidPosition(newRow, newCol) && board[newRow][newCol] === player) {
    count++;
    } else {
    break;
    }
    }

    // 检查反方向
    for (let i = 1; i < 5; i++) {
    const newRow = row dx * i;
    const newCol = col dy * i;
    if (isValidPosition(newRow, newCol) && board[newRow][newCol] === player) {
    count++;
    } else {
    break;
    }
    }

    if (count > maxCount) {
    maxCount = count;
    }
    }

    return maxCount;
    }

    // 显示胜利消息
    function showWinMessage() {
    const winner = currentPlayer === 'black' ? '玩家' : '电脑';
    const gameContainer = document.querySelector('.game-container');
    const winElement = document.createElement('div');
    winElement.className = 'game-over';
    winElement.innerHTML = `🎉 ${winner} 获胜! 🎉`;
    gameContainer.appendChild(winElement);

    // 播放胜利音效
    playWinSound();

    // 添加胜利特效
    addWinEffect();
    }

    // 重置游戏
    function resetGame() {
    // 播放重置音效
    playResetSound();
    initBoard();
    }

    // 切换音效
    function toggleSound() {
    soundEnabled = !soundEnabled;
    musicEnabled = !musicEnabled;

    const btn = document.querySelector('.btn.sound');
    btn.textContent = soundEnabled ? '🔊 音效开关' : '🔇 音效关闭';

    // 控制音乐
    if (musicEnabled) {
    startMusic();
    } else {
    stopBackgroundMusic();
    }
    }

    // 开始音乐
    function startMusic() {
    if (musicEnabled) {
    startBackgroundMusic();
    }
    }

    // 播放落子音效
    function playDropSound() {
    if (!soundEnabled) return;

    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(soundGain);

    oscillator.type = 'sine';
    oscillator.frequency.value = 800;

    const now = audioContext.currentTime;
    gainNode.gain.setValueAtTime(0.5, now);
    gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.2);

    oscillator.start(now);
    oscillator.stop(now + 0.2);
    }

    // 播放胜利音效
    function playWinSound() {
    if (!soundEnabled) return;

    const frequencies = [523, 659, 784, 1047]; // C, E, G, C

    frequencies.forEach((freq, index) => {
    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(soundGain);

    oscillator.type = 'sine';
    oscillator.frequency.value = freq;

    const now = audioContext.currentTime;
    const delay = index * 0.2;

    gainNode.gain.setValueAtTime(0, now + delay);
    gainNode.gain.linearRampToValueAtTime(0.5, now + delay + 0.1);
    gainNode.gain.exponentialRampToValueAtTime(0.01, now + delay + 0.3);

    oscillator.start(now + delay);
    oscillator.stop(now + delay + 0.3);
    });
    }

    // 播放重置音效
    function playResetSound() {
    if (!soundEnabled) return;

    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(soundGain);

    oscillator.type = 'sine';
    oscillator.frequency.value = 400;

    const now = audioContext.currentTime;
    gainNode.gain.setValueAtTime(0.5, now);
    gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.3);

    oscillator.frequency.exponentialRampToValueAtTime(200, now + 0.3);

    oscillator.start(now);
    oscillator.stop(now + 0.3);
    }

    // 添加落子特效
    function addDropEffect(cell, row, col) {
    // 创建emoji特效
    const effect = document.createElement('div');
    effect.className = 'effect';

    // 随机选择特效emoji
    const effects = ['✨', '🌟', '💫', '⚡', '🎯'];
    effect.textContent = effects[Math.floor(Math.random() * effects.length)];

    // 设置位置
    const rect = cell.getBoundingClientRect();
    const boardRect = document.getElementById('board').getBoundingClientRect();

    effect.style.left = `${rect.left boardRect.left + 20}px`;
    effect.style.top = `${rect.top boardRect.top + 20}px`;

    // 添加到棋盘
    document.getElementById('board').appendChild(effect);

    // 动画结束后移除
    setTimeout(() => {
    effect.remove();
    }, 1000);
    }

    // 添加胜利特效
    function addWinEffect() {
    // 在棋盘上随机生成多个庆祝emoji
    const effects = ['🎉', '🎊', '🏆', '🎁', '🎈'];

    for (let i = 0; i < 20; i++) {
    const effect = document.createElement('div');
    effect.className = 'effect';
    effect.textContent = effects[Math.floor(Math.random() * effects.length)];

    // 随机位置
    const x = Math.random() * 600;
    const y = Math.random() * 600;

    effect.style.left = `${x}px`;
    effect.style.top = `${y}px`;

    // 随机动画时间
    effect.style.animationDuration = `${0.5 + Math.random() * 1}s`;

    document.getElementById('board').appendChild(effect);

    setTimeout(() => {
    effect.remove();
    }, 1500);
    }
    }

    // 页面加载完成后初始化游戏
    window.addEventListener('DOMContentLoaded', initGame);
    </script>
    </body>
    </html>

    📖 javascript代码

    backgroundMusic.js

    // 背景音乐模块
    // 使用 Web Audio API 生成背景音乐

    let musicInterval = null;
    // 注意:audioContext 和 backgroundMusicGain 在主脚本中声明,这里只存储引用
    let audioContextRef = null;
    let backgroundMusicGainRef = null;

    // 初始化背景音乐(需要传入音频上下文和增益节点)
    function initBackgroundMusic(audioCtx, musicGain) {
    audioContextRef = audioCtx;
    backgroundMusicGainRef = musicGain;
    }

    // 获取游戏状态的函数(由主游戏传入)
    let getGameState = null;

    // 设置游戏状态获取函数
    function setGameStateGetter(getter) {
    getGameState = getter;
    }

    // 生成背景音乐
    function startBackgroundMusic() {
    if (!audioContextRef || !backgroundMusicGainRef || musicInterval) return;

    try {
    // 激进快速的旋律循环 – 科幻电子风格
    const melody = [
    // 第一段:快速上升
    { freq1: 523.25, freq2: 659.25, duration: 0.2, bass: 261.63 }, // C5, E5, C4低音
    { freq1: 659.25, freq2: 783.99, duration: 0.2, bass: 329.63 }, // E5, G5, E4
    { freq1: 783.99, freq2: 987.77, duration: 0.2, bass: 392.00 }, // G5, B5, G4
    { freq1: 987.77, freq2: 1174.66, duration: 0.2, bass: 493.88 }, // B5, D6, B4
    // 第二段:跳跃音程
    { freq1: 880.00, freq2: 1318.51, duration: 0.2, bass: 440.00 }, // A5, E6, A4
    { freq1: 1046.50, freq2: 1567.98, duration: 0.2, bass: 523.25 }, // C6, G6, C5
    { freq1: 1174.66, freq2: 1760.00, duration: 0.2, bass: 587.33 }, // D6, A6, D5
    // 第三段:快速下降
    { freq1: 1046.50, freq2: 1318.51, duration: 0.2, bass: 523.25 }, // C6, E6, C5
    { freq1: 880.00, freq2: 1108.73, duration: 0.2, bass: 440.00 }, // A5, C#6, A4
    { freq1: 783.99, freq2: 987.77, duration: 0.2, bass: 392.00 }, // G5, B5, G4
    { freq1: 659.25, freq2: 830.61, duration: 0.2, bass: 329.63 }, // E5, G#5, E4
    ];

    let noteIndex = 0;

    function playNextNote() {
    // 获取当前游戏状态
    if (getGameState) {
    const state = getGameState();
    if (!state.gameRunning || state.gamePaused || state.gameOver) {
    return;
    }
    }

    const note = melody[noteIndex];
    const currentTime = audioContextRef.currentTime;

    // 创建主旋律振荡器(高频,更尖锐)
    const osc1 = audioContextRef.createOscillator();
    const osc2 = audioContextRef.createOscillator();
    const gain1 = audioContextRef.createGain();
    const gain2 = audioContextRef.createGain();

    osc1.connect(gain1);
    osc2.connect(gain2);
    gain1.connect(backgroundMusicGainRef);
    gain2.connect(backgroundMusicGainRef);

    // 使用更激进的波形:方波和锯齿波
    osc1.type = 'square'; // 方波更尖锐
    osc2.type = 'sawtooth'; // 锯齿波更激进
    osc1.frequency.value = note.freq1;
    osc2.frequency.value = note.freq2;

    // 更快的起音和衰减,营造冲击感
    gain1.gain.setValueAtTime(0.12, currentTime);
    gain1.gain.exponentialRampToValueAtTime(0.01, currentTime + note.duration);
    gain2.gain.setValueAtTime(0.10, currentTime);
    gain2.gain.exponentialRampToValueAtTime(0.01, currentTime + note.duration);

    osc1.start(currentTime);
    osc1.stop(currentTime + note.duration);
    osc2.start(currentTime);
    osc2.stop(currentTime + note.duration);

    // 添加低音增强节奏感(如果有低音频率)
    if (note.bass) {
    const bassOsc = audioContextRef.createOscillator();
    const bassGain = audioContextRef.createGain();

    bassOsc.connect(bassGain);
    bassGain.connect(backgroundMusicGainRef);

    bassOsc.type = 'square'; // 低音使用方波
    bassOsc.frequency.value = note.bass;

    bassGain.gain.setValueAtTime(0.08, currentTime);
    bassGain.gain.exponentialRampToValueAtTime(0.01, currentTime + note.duration);

    bassOsc.start(currentTime);
    bassOsc.stop(currentTime + note.duration);
    }

    noteIndex = (noteIndex + 1) % melody.length;
    }

    // 立即播放第一个音符
    playNextNote();

    // 设置定时器循环播放 – 更快的节奏(250ms间隔)
    musicInterval = setInterval(() => {
    if (getGameState) {
    const state = getGameState();
    if (state.gameRunning && !state.gamePaused && !state.gameOver) {
    playNextNote();
    }
    } else {
    playNextNote();
    }
    }, 250); // 每250ms播放一个音符(比原来快一倍)
    } catch (e) {
    console.log('背景音乐生成失败:', e);
    }
    }

    // 停止背景音乐
    function stopBackgroundMusic() {
    if (musicInterval) {
    clearInterval(musicInterval);
    musicInterval = null;
    }
    }

     

    ———— ⬆️·`正文结束`·⬆️————

     


    到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易,如果能帮助到大家,希望大家多多支持宝码香车~💕,若转载本文,一定注明本文链接。


    整理不易,点赞关注宝码香车

    更多专栏订阅推荐: 👍 html+css+js 绚丽效果 💕 vue ✈️ Electron ⭐️ js 📝 字符串 ✍️ 时间对象(Date())操作

    赞(0)
    未经允许不得转载:171主机测评 » (文后附完整代码)html+css+javascript 五子棋项目分析报告
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址