- gf25051 的博客
《咸鱼概要 · 游戏(优质)》五子棋 - Pro Max版
- @ 2026-1-10 9:09:18
使用方法(代码放在使用方法下面了):
1.打开代码,点击Copy复制(粘贴了代码以后,就不要再粘贴其他东西了)

2.返回桌面,新建一个文本文档(txt)

3.给文本文档改名为“五子棋 - Pro Max版”

4.打开文本文档,点击右键,选择粘贴

5.然后点击左上角“文件”--->“另存为”

6.进入“另存为”界面,先将左侧栏的“创建位置”改为“桌面”,然后将文件名后缀改为html(也就是把.txt改为.html),最后点击“保存”

7.此时桌面上就会出现一个文件,叫做“五子棋 - Pro Max版.html”,这就是运行文件

8.点击运行文件,就可以游玩了。如果你有U盘,你还可以把运行文件放进U盘里,下次想玩时点击即可,不用再重新创造一个运行文件

代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>五子棋 - Pro Max版</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{display:flex;justify-content:center;align-items:center;min-height:100vh;background:linear-gradient(135deg,#0f0f23,#1a1a2e);font-family:'Microsoft YaHei',sans-serif;color:#fff;padding:20px}
.home-page{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;max-width:800px;text-align:center;gap:30px}
.game-title{font-size:4rem;margin-bottom:20px;background:linear-gradient(45deg,#ff6b6b,#4ecdc4,#45b7d1,#96c93d);-webkit-background-clip:text;-webkit-text-fill-color:transparent;text-shadow:0 0 30px rgba(255,107,107,0.3);animation:titleGlow 3s infinite alternate}
@keyframes titleGlow{0%{text-shadow:0 0 20px rgba(255,107,107,0.3)}100%{text-shadow:0 0 40px rgba(78,205,196,0.5)}}
.rank-system-home{display:flex;align-items:center;gap:20px;background:rgba(255,255,255,0.08);padding:20px 30px;border-radius:20px;box-shadow:0 10px 30px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1);margin-bottom:20px}
.rank-info-home{display:flex;flex-direction:column;gap:10px}
.rank-label-home{font-size:1rem;color:#aaa}
.rank-value-home{font-size:2rem;font-weight:bold;background:linear-gradient(45deg,#ffd700,#ff6b6b);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.exp-bar-home{width:200px;height:15px;background:rgba(255,255,255,0.1);border-radius:8px;overflow:hidden;position:relative}
.exp-fill-home{height:100%;background:linear-gradient(90deg,#4ecdc4,#45b7d1);transition:width 0.5s ease;position:relative;overflow:hidden}
.exp-text-home{font-size:1rem;color:#ccc;margin-top:8px}
.mode-selector-home{display:flex;flex-direction:column;gap:20px;width:100%;max-width:500px}
.mode-card{display:flex;flex-direction:column;align-items:center;gap:15px;padding:30px;background:rgba(255,255,255,0.08);border-radius:20px;cursor:pointer;transition:all 0.3s;border:2px solid transparent;box-shadow:0 10px 30px rgba(0,0,0,0.4)}
.mode-card:hover{transform:translateY(-10px);background:rgba(255,255,255,0.12);border-color:#4ecdc4;box-shadow:0 15px 40px rgba(78,205,196,0.3)}
.mode-icon{font-size:3rem;margin-bottom:10px}
.mode-title{font-size:1.8rem;font-weight:bold;color:#fff}
.mode-description{font-size:1rem;color:#ccc;text-align:center;line-height:1.5}
.match-history-home{width:100%;max-width:500px;background:rgba(255,255,255,0.08);padding:25px;border-radius:20px;box-shadow:0 10px 30px rgba(0,0,0,0.4);border:1px solid rgba(255,255,255,0.1)}
.history-title{font-size:1.3rem;margin-bottom:15px;color:#4ecdc4}
.history-list-home{max-height:200px;overflow-y:auto}
.history-item-home{padding:10px 15px;border-bottom:1px solid rgba(255,255,255,0.1);font-size:0.9rem;border-radius:5px;margin-bottom:5px;background:rgba(255,255,255,0.05)}
.game-page{display:none;flex-direction:column;align-items:center;gap:20px;max-width:1200px;width:100%}
.game-header{text-align:center;margin-bottom:10px;width:100%}
.game-header h1{font-size:2.8rem;margin-bottom:10px;background:linear-gradient(45deg,#ff6b6b,#4ecdc4,#45b7d1,#96c93d);-webkit-background-clip:text;-webkit-text-fill-color:transparent;text-shadow:0 0 20px rgba(255,107,107,0.3)}
.header-controls{display:flex;justify-content:space-between;align-items:center;width:100%;max-width:900px;margin-bottom:20px;flex-wrap:wrap}
.rank-system-game{display:flex;align-items:center;gap:15px;background:rgba(255,255,255,0.08);padding:15px 25px;border-radius:15px;box-shadow:0 5px 20px rgba(0,0,0,0.4);border:1px solid rgba(255,255,255,0.1)}
.rank-info-game{display:flex;flex-direction:column;gap:5px}
.rank-label-game{font-size:0.9rem;color:#aaa}
.rank-value-game{font-size:1.6rem;font-weight:bold;background:linear-gradient(45deg,#ffd700,#ff6b6b);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.exp-bar-game{width:180px;height:12px;background:rgba(255,255,255,0.1);border-radius:6px;overflow:hidden;position:relative}
.exp-fill-game{height:100%;background:linear-gradient(90deg,#4ecdc4,#45b7d1);transition:width 0.5s ease;position:relative;overflow:hidden}
.exp-text-game{font-size:0.9rem;color:#ccc;margin-top:5px}
.back-home-btn{padding:12px 25px;background:linear-gradient(45deg,#ff6b6b,#4ecdc4);border:none;border-radius:10px;color:white;font-size:1rem;font-weight:bold;cursor:pointer;transition:all 0.3s;box-shadow:0 5px 15px rgba(255,107,107,0.4)}
.back-home-btn:hover{transform:translateY(-3px);box-shadow:0 8px 20px rgba(255,107,107,0.6)}
.game-area{display:flex;gap:30px;align-items:flex-start;width:100%;max-width:1000px}
.game-board-container{flex:1;display:flex;flex-direction:column;align-items:center}
.difficulty-selector{display:none;gap:10px;margin-bottom:20px;background:rgba(255,255,255,0.08);padding:15px;border-radius:12px;box-shadow:0 5px 20px rgba(0,0,0,0.4);flex-wrap:wrap;justify-content:center}
.difficulty-btn{padding:10px 20px;border:none;border-radius:8px;background:rgba(255,255,255,0.1);color:white;font-size:1rem;cursor:pointer;transition:all 0.3s;min-width:80px;white-space:nowrap}
.difficulty-btn.active{background:linear-gradient(45deg,#45b7d1,#96c93d);box-shadow:0 5px 15px rgba(69,183,209,0.4)}
.difficulty-btn:hover:not(.active){background:rgba(255,255,255,0.2);transform:translateY(-2px)}
.game-board{position:relative;background:#e8c87e;border:4px solid #b89446;box-shadow:0 15px 40px rgba(0,0,0,0.7);border-radius:10px;overflow:hidden}
.board-grid{display:grid;grid-template-columns:repeat(15,1fr);grid-template-rows:repeat(15,1fr);width:600px;height:600px;position:relative}
.cell{position:relative;display:flex;justify-content:center;align-items:center;cursor:pointer;transition:background 0.2s}
.cell:hover{background:rgba(139,105,20,0.15)}
.cell::before,.cell::after{content:'';position:absolute;background:#8b6914}
.cell::before{width:100%;height:1px;top:50%;transform:translateY(-50%)}
.cell::after{width:1px;height:100%;left:50%;transform:translateX(-50%)}
.piece{position:absolute;width:36px;height:36px;border-radius:50%;z-index:10;box-shadow:0 5px 15px rgba(0,0,0,0.5);transform:scale(0);transition:transform 0.3s cubic-bezier(0.175,0.885,0.32,1.275)}
.piece.black{background:radial-gradient(circle at 30% 30%,#333,#000);border:2px solid #111}
.piece.white{background:radial-gradient(circle at 30% 30%,#fff,#ddd);border:2px solid #eee}
.piece.placed{transform:scale(1)}
.side-panel{width:320px;display:flex;flex-direction:column;gap:20px}
.game-info{background:rgba(255,255,255,0.08);padding:25px;border-radius:15px;box-shadow:0 5px 20px rgba(0,0,0,0.4);border:1px solid rgba(255,255,255,0.1)}
.player-info{display:flex;align-items:center;gap:15px;padding:15px;border-radius:10px;margin-bottom:15px;transition:all 0.3s}
.player-info.current-player{background:linear-gradient(45deg,rgba(255,107,107,0.2),rgba(78,205,196,0.2));border:2px solid #4ecdc4}
.player-icon{width:60px;height:60px;border-radius:50%;display:flex;justify-content:center;align-items:center;font-weight:bold;font-size:1.4rem;box-shadow:0 5px 15px rgba(0,0,0,0.4)}
.black-player .player-icon{background:linear-gradient(45deg,#222,#000);color:white}
.white-player .player-icon{background:linear-gradient(45deg,#fff,#eee);color:#000}
.player-details{flex:1}
.player-name{font-size:1.3rem;font-weight:bold;margin-bottom:5px}
.player-status{font-size:0.9rem;color:#ccc}
.player-rank{font-size:0.8rem;color:#aaa;margin-top:3px}
.controls-panel{background:rgba(255,255,255,0.08);padding:25px;border-radius:15px;box-shadow:0 5px 20px rgba(0,0,0,0.4);border:1px solid rgba(255,255,255,0.1)}
.controls{display:grid;grid-template-columns:repeat(2,1fr);gap:15px;margin-top:10px}
.game-button{padding:15px;border:none;border-radius:10px;background:linear-gradient(45deg,#45b7d1,#96c93d);color:white;font-size:1rem;font-weight:bold;cursor:pointer;transition:all 0.3s;box-shadow:0 5px 15px rgba(69,183,209,0.4)}
.game-button:hover:not(:disabled){transform:translateY(-3px);box-shadow:0 8px 20px rgba(69,183,209,0.6)}
.game-button:active:not(:disabled){transform:translateY(1px)}
.game-button:disabled{opacity:0.5;cursor:not-allowed}
.match-history-game{margin-top:20px;max-height:200px;overflow-y:auto;display:none}
.match-page{display:none;flex-direction:column;align-items:center;justify-content:center;width:100%;max-width:600px;gap:30px;padding:50px;background:rgba(255,255,255,0.08);border-radius:25px;box-shadow:0 15px 40px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1)}
.match-title{font-size:2.5rem;text-align:center;background:linear-gradient(45deg,#ff6b6b,#4ecdc4);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:10px}
.match-button{padding:25px 60px;font-size:1.8rem;background:linear-gradient(45deg,#ff6b6b,#4ecdc4);border:none;border-radius:20px;color:white;cursor:pointer;transition:all 0.3s;box-shadow:0 15px 40px rgba(255,107,107,0.4)}
.match-button:hover{transform:translateY(-8px) scale(1.05);box-shadow:0 20px 50px rgba(255,107,107,0.6)}
.match-button:disabled{opacity:0.6;cursor:not-allowed;transform:none}
.matching-text{font-size:1.8rem;margin:30px 0;color:#4ecdc4;font-weight:bold;display:none;text-align:center}
.matching-dots{display:inline-block;animation:dots 1.5s infinite}
@keyframes dots{0%,20%{content:''}40%{content:'.'}60%{content:'..'}80%,100%{content:'...'}}
.matched-info{background:rgba(78,205,196,0.2);padding:25px;border-radius:15px;margin-top:20px;border:2px solid #4ecdc4;display:none;width:100%;text-align:center}
.matched-title{font-size:1.5rem;margin-bottom:15px;color:#4ecdc4}
.matched-detail{margin:8px 0;color:#ccc;font-size:1.1rem}
.matched-difficulty{color:#ff6b6b;font-weight:bold}
.game-message{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);background:rgba(15,15,35,0.95);padding:50px;border-radius:20px;text-align:center;z-index:1000;transition:transform 0.5s cubic-bezier(0.175,0.885,0.32,1.275);box-shadow:0 0 50px rgba(255,107,107,0.8);border:2px solid #ff6b6b;width:90%;max-width:500px;backdrop-filter:blur(10px)}
.game-message.show{transform:translate(-50%,-50%) scale(1)}
.game-message h2{font-size:2.8rem;margin-bottom:20px;background:linear-gradient(45deg,#ff6b6b,#4ecdc4);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.game-message p{font-size:1.3rem;margin-bottom:20px;color:#fff}
.game-message .exp-change{font-size:1.4rem;font-weight:bold;margin:20px 0;padding:15px;border-radius:10px;background:rgba(255,255,255,0.1)}
.exp-gain{color:#96c93d}
.exp-loss{color:#ff6b6b}
.message-buttons{display:flex;gap:20px;justify-content:center;margin-top:30px}
.message-btn{padding:15px 30px;border:none;border-radius:10px;color:white;font-size:1.1rem;font-weight:bold;cursor:pointer;transition:all 0.3s}
.back-home-message-btn{background:linear-gradient(45deg,#ff6b6b,#4ecdc4);box-shadow:0 5px 15px rgba(255,107,107,0.4)}
.rematch-btn{background:linear-gradient(45deg,#45b7d1,#96c93d);box-shadow:0 5px 15px rgba(69,183,209,0.4)}
.message-btn:hover{transform:translateY(-3px);box-shadow:0 8px 20px rgba(0,0,0,0.5)}
.last-move{position:absolute;width:24px;height:24px;border-radius:50%;background:#ff6b6b;z-index:5;opacity:0;transform:scale(0);transition:all 0.3s;box-shadow:0 0 15px #ff6b6b}
.last-move.show{opacity:1;transform:scale(1);animation:pulse 2s infinite}
@keyframes pulse{0%{box-shadow:0 0 5px #ff6b6b}50%{box-shadow:0 0 20px #ff6b6b}100%{box-shadow:0 0 5px #ff6b6b}}
.ai-thinking{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(15,15,35,0.9);padding:25px 50px;border-radius:15px;font-size:1.5rem;z-index:20;display:none;border:2px solid #4ecdc4;box-shadow:0 0 30px rgba(78,205,196,0.5);backdrop-filter:blur(5px)}
.ai-thinking.show{display:block;animation:thinkingPulse 2s infinite}
@keyframes thinkingPulse{0%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.05)}100%{transform:translate(-50%,-50%) scale(1)}}
.history-win{border-left:4px solid #96c93d}
.history-loss{border-left:4px solid #ff6b6b}
.history-draw{border-left:4px solid #45b7d1}
@media(max-width:1100px){.game-area{flex-direction:column;align-items:center}.side-panel{width:100%;max-width:600px}.board-grid{width:500px;height:500px}.piece{width:30px;height:30px}.difficulty-selector{justify-content:center}}
@media(max-width:650px){.board-grid{width:400px;height:400px}.piece{width:24px;height:24px}.game-title{font-size:2.5rem}.mode-title{font-size:1.5rem}.match-title{font-size:2rem}.match-button{padding:20px 40px;font-size:1.5rem}.rank-system-home,.rank-system-game{flex-direction:column;align-items:center;text-align:center}.exp-bar-home,.exp-bar-game{width:150px}.header-controls{flex-direction:column;gap:15px}.difficulty-selector{width:100%;justify-content:space-between}.difficulty-btn{min-width:60px;padding:8px 12px;font-size:0.9rem}.message-buttons{flex-direction:column}}
@media(max-width:450px){.board-grid{width:320px;height:320px}.piece{width:18px;height:18px}.player-icon{width:50px;height:50px;font-size:1.2rem}.match-button{padding:15px 30px;font-size:1.2rem}.game-title{font-size:2rem}.mode-card{padding:20px}}
</style>
</head>
<body>
<div class="home-page" id="homePage">
<h1 class="game-title">五子棋 - Pro Max版</h1>
<div class="rank-system-home">
<div class="rank-info-home">
<div class="rank-label-home">当前段位</div>
<div class="rank-value-home" id="rankValueHome">青铜</div>
</div>
<div>
<div class="exp-bar-home">
<div class="exp-fill-home" id="expFillHome" style="width:0%"></div>
</div>
<div class="exp-text-home">经验值: <span id="currentExpHome">0</span>/5</div>
</div>
</div>
<div class="mode-selector-home">
<div class="mode-card" id="pvpModeCard">
<div class="mode-icon">⚔️</div>
<div class="mode-title">双人对战</div>
<div class="mode-description">与朋友面对面切磋棋艺,体验纯粹的博弈乐趣</div>
</div>
<div class="mode-card" id="pveModeCard">
<div class="mode-icon">🤖</div>
<div class="mode-title">人机对战</div>
<div class="mode-description">挑战AI,从简单到宗师,测试你的棋力水平</div>
</div>
<div class="mode-card" id="matchModeCard">
<div class="mode-icon">🎯</div>
<div class="mode-title">匹配对战</div>
<div class="mode-description">与随机AI对战,赢取经验值提升段位</div>
</div>
</div>
<div class="match-history-home">
<div class="history-title">最近战绩</div>
<div class="history-list-home" id="historyListHome"></div>
</div>
</div>
<div class="game-page" id="gamePage">
<div class="game-header">
<h1 id="gamePageTitle">五子棋 - Pro Max版</h1>
<p id="gamePageDescription">先连成五子者获胜</p>
<div class="header-controls">
<div class="rank-system-game">
<div class="rank-info-game">
<div class="rank-label-game">当前段位</div>
<div class="rank-value-game" id="rankValueGame">青铜</div>
</div>
<div>
<div class="exp-bar-game">
<div class="exp-fill-game" id="expFillGame" style="width:0%"></div>
</div>
<div class="exp-text-game">经验值: <span id="currentExpGame">0</span>/5</div>
</div>
</div>
<button class="back-home-btn" id="backHomeBtn">返回主页</button>
</div>
</div>
<div class="game-area">
<div class="game-board-container">
<div class="difficulty-selector" id="difficultySelector">
<button class="difficulty-btn active" data-level="easy">简单</button>
<button class="difficulty-btn" data-level="medium">中等</button>
<button class="difficulty-btn" data-level="hard">困难</button>
<button class="difficulty-btn" data-level="expert">专家</button>
<button class="difficulty-btn" data-level="grandmaster">宗师</button>
</div>
<div class="game-board">
<div class="board-grid" id="board"></div>
<div class="ai-thinking" id="aiThinking">AI思考中...</div>
</div>
</div>
<div class="side-panel">
<div class="game-info">
<div class="player-info black-player current-player">
<div class="player-icon">黑</div>
<div class="player-details">
<div class="player-name" id="blackPlayerName">玩家</div>
<div class="player-status" id="blackStatus">当前回合</div>
<div class="player-rank" id="blackRank"></div>
</div>
</div>
<div class="player-info white-player">
<div class="player-icon">白</div>
<div class="player-details">
<div class="player-name" id="whitePlayerName">玩家</div>
<div class="player-status" id="whiteStatus">等待中</div>
<div class="player-rank" id="whiteRank"></div>
</div>
</div>
</div>
<div class="controls-panel">
<h3 style="margin-bottom:15px;text-align:center">游戏控制</h3>
<div class="controls">
<button class="game-button" id="restart">重新开始</button>
<button class="game-button" id="undo">悔棋</button>
<button class="game-button" id="hint">提示</button>
<button class="game-button" id="soundToggle">音效: 开</button>
</div>
<div class="match-history-game" id="matchHistoryGame">
<h4 style="margin:15px 0 10px 0;color:#4ecdc4">匹配记录</h4>
<div id="historyListGame"></div>
</div>
</div>
</div>
</div>
</div>
<div class="match-page" id="matchPage">
<div class="match-title">匹配对战</div>
<button class="back-home-btn" id="backHomeFromMatch" style="margin-bottom:10px">返回主页</button>
<button class="match-button" id="startMatching">开始匹配</button>
<div class="matching-text" id="matchingText">
正在匹配对手<span class="matching-dots"></span>
</div>
<div class="matched-info" id="matchedInfo">
<div class="matched-title">匹配成功</div>
<div class="matched-detail">对手: <span id="opponentName" class="matched-difficulty">AI-大师</span></div>
<div class="matched-detail">难度: <span id="opponentDifficulty" class="matched-difficulty">宗师级</span></div>
<div class="matched-detail" style="margin-top:15px;color:#ff6b6b">匹配对战不可悔棋</div>
</div>
</div>
<div class="game-message" id="gameMessage">
<h2 id="messageTitle">游戏结束</h2>
<p id="messageContent">黑方获胜!</p>
<div id="expInfo" style="display:none">
<div class="exp-change" id="expChange">+1 经验值</div>
<div class="rank-up" id="rankUpMessage" style="display:none;color:#ffd700;font-size:1.5rem;margin:10px 0">恭喜升段!</div>
</div>
<div class="message-buttons">
<button class="message-btn back-home-message-btn" id="backHomeMessageBtn">返回主页</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded',function(){
const homePage=document.getElementById('homePage');
const rankValueHome=document.getElementById('rankValueHome');
const currentExpHome=document.getElementById('currentExpHome');
const expFillHome=document.getElementById('expFillHome');
const pvpModeCard=document.getElementById('pvpModeCard');
const pveModeCard=document.getElementById('pveModeCard');
const matchModeCard=document.getElementById('matchModeCard');
const historyListHome=document.getElementById('historyListHome');
const gamePage=document.getElementById('gamePage');
const gamePageTitle=document.getElementById('gamePageTitle');
const gamePageDescription=document.getElementById('gamePageDescription');
const rankValueGame=document.getElementById('rankValueGame');
const currentExpGame=document.getElementById('currentExpGame');
const expFillGame=document.getElementById('expFillGame');
const backHomeBtn=document.getElementById('backHomeBtn');
const board=document.getElementById('board');
const restartBtn=document.getElementById('restart');
const undoBtn=document.getElementById('undo');
const hintBtn=document.getElementById('hint');
const soundToggleBtn=document.getElementById('soundToggle');
const blackPlayerName=document.getElementById('blackPlayerName');
const whitePlayerName=document.getElementById('whitePlayerName');
const blackStatus=document.getElementById('blackStatus');
const whiteStatus=document.getElementById('whiteStatus');
const blackRank=document.getElementById('blackRank');
const whiteRank=document.getElementById('whiteRank');
const aiThinking=document.getElementById('aiThinking');
const difficultySelector=document.getElementById('difficultySelector');
const matchHistoryGame=document.getElementById('matchHistoryGame');
const historyListGame=document.getElementById('historyListGame');
const matchPage=document.getElementById('matchPage');
const startMatchingBtn=document.getElementById('startMatching');
const matchingText=document.getElementById('matchingText');
const matchedInfo=document.getElementById('matchedInfo');
const opponentName=document.getElementById('opponentName');
const opponentDifficulty=document.getElementById('opponentDifficulty');
const backHomeFromMatch=document.getElementById('backHomeFromMatch');
const gameMessage=document.getElementById('gameMessage');
const messageTitle=document.getElementById('messageTitle');
const messageContent=document.getElementById('messageContent');
const expInfo=document.getElementById('expInfo');
const expChange=document.getElementById('expChange');
const rankUpMessage=document.getElementById('rankUpMessage');
const backHomeMessageBtn=document.getElementById('backHomeMessageBtn');
const BOARD_SIZE=15;
let currentPlayer='black';
let gameOver=false;
let boardState=Array(BOARD_SIZE).fill().map(()=>Array(BOARD_SIZE).fill(null));
let moveHistory=[];
let lastMoveMarker=null;
let currentGameMode='';
let aiDifficulty='medium';
let isMatching=false;
let soundEnabled=true;
let rank=1;
let experience=0;
let isMatchGame=false;
let allowUndo=true;
let currentMatchOpponent='';
let currentMatchDifficulty='';
const aiNames=["黄延希","小黄","胡彦熙","张林柯","颜筠霖","李棂坤","黄炎硕","杨宇赫","凌海榕","毕子毅","罗子航","胡宇轩","王志锐","罗钰韵","常清琳","黄子杰","林培奇学长","云中棋客","风中棋手","雨中棋仙","雪中棋圣","月下棋魂","日下棋王","星棋罗布","棋走天涯","棋乐融融","棋思妙想","棋心不改","棋迷一枚","棋痴一个","棋呆子","棋疯子","棋傻子","棋天才","棋鬼才","棋怪才","棋神童","棋少年","棋老者","棋美女","棋帅哥","棋大叔","棋阿姨","棋爷爷","棋奶奶","棋宝宝","棋小学生","棋中学生","棋大学生","棋研究生","棋博士生","棋教授","棋专家","棋学者","棋作家","棋画家","棋音乐家","棋舞蹈家","棋体育家","棋科学家","棋工程师","棋医生","棋护士","棋警察","棋消防员","棋军人","棋宇航员","棋农民","棋工人","棋商人","棋企业家","棋政治家","棋外交家","棋军事家","棋经济学家","棋哲学家","棋历史学家","棋地理学家","棋生物学家","棋化学家","棋物理学家","棋数学家","棋天文学家","棋地质学家","棋海洋学家","棋气象学家","棋心理学家","棋社会学家","棋人类学家","棋语言学家","棋文学家","棋艺术家","棋设计师","棋程序员","棋测试员","棋产品经理","棋运营","棋市场","棋销售","棋客服","棋财务","棋人事","棋行政","棋法务","棋咨询","棋投资","棋银行","棋保险","棋证券","棋基金","棋信托","棋租赁","棋担保","棋典当","棋拍卖","棋评估","棋审计","棋税务","棋会计","棋统计","棋调查","棋研究","棋开发","棋生产","棋制造","棋加工","棋装配","棋检测","棋包装","棋运输","棋仓储","棋配送","棋快递","棋物流","棋供应链","棋采购","棋库存","棋订单","棋客户","棋供应商","棋合作伙伴","棋竞争对手","棋行业领袖","棋市场先锋","棋技术专家","棋管理大师","棋创新先锋","棋质量标杆","棋服务典范","棋效率冠军","棋成本控制","棋利润增长","棋市场份额","棋品牌价值","棋企业文化","棋团队精神","棋领导力","棋执行力","棋创造力","棋学习力","棋适应力","棋竞争力","棋合作力","棋沟通力","棋决策力","棋计划力","棋组织力","棋协调力","棋控制力","棋评估力","棋改进力","棋创新力","棋变革力","棋发展力","棋成长力","棋突破力","棋超越力","棋领先力","棋卓越力","棋完美力","棋极致力","棋无限力","棋永恒力","棋无敌力","棋至尊力","棋霸主力","棋王者力","棋帝王力","棋神之力","棋仙之力","棋圣之力","棋魔之力","棋鬼之力","棋妖之力","棋怪之力","棋精之力","棋灵之力","棋魂之力","棋魄之力","棋心之力","棋意之力","棋念之力","棋想之力","棋思之力","棋悟之力","棋道之力","棋法之力","棋术之力","棋技之力","棋艺之力","棋巧之力","棋妙之力","棋奇之力","棋异之力","棋特之力","棋独之力","棋专之力","棋精之力","棋通之力","棋达之力","棋成之力","棋就之力","棋功之力","棋业之力","棋绩之力","棋效之力","棋果之力","棋报之力","棋酬之力","棋赏之力","棋罚之力","棋奖之力","棋惩之力","棋励之力","棋激之力","棋鼓之力","棋舞之力","棋动之力","棋静之力","棋刚之力","棋柔之力","棋阴之力","棋阳之力","棋虚之力","棋实之力","棋空之力","棋满之力","棋有之力","棋无之力","棋生之力","棋灭之力","棋成之力","棋坏之力","棋增之力","棋减之力","棋进之力","棋退之力","棋攻之力","棋守之力","棋胜之力","棋败之力","棋强之力","棋弱之力","棋优之力","棋劣之力","棋好之力","棋坏之力","棋善之力","棋恶之力","棋美之力","棋丑之力","棋真之力","棋假之力","棋对之力","棋错之力","棋正之力","棋邪之力","棋是之力","棋非之力","棋黑之力","棋白之力","棋灰之力","棋彩之力","棋光之力","棋暗之力","棋明之力","棋晦之力","棋清之力","棋浊之力","棋纯之力","棋杂之力","棋简之力","棋繁之力","棋易之力","棋难之力","棋快之力","棋慢之力","棋急之力","棋缓之力","棋紧之力","棋松之力","棋重之力","棋轻之力","棋大之力","棋小之力","棋多之力","棋少之力","棋长之力","棋短之力","棋高之力","棋低之力","棋深之力","棋浅之力","棋远之力","棋近之力","棋宽之力","棋窄之力","棋厚之力","棋薄之力","棋硬之力","棋软之力","棋热之力","棋冷之力","棋干之力","棋湿之力","棋甜之力","棋苦之力","棋酸之力","棋辣之力","棋咸之力","棋淡之力","棋香之力","棋臭之力","棋鲜之力","棋腐之力","棋新之力","棋旧之力","棋生之力","棋熟之力","棋活之力","棋死之力","棋动之力","棋静之力","棋来之力","棋去之力","棋起之力","棋落之力","棋开之力","棋合之力","棋放之力","棋收之力","棋张之力","棋弛之力","棋伸之力","棋缩之力","棋展之力","棋卷之力","棋扬之力","棋抑之力","棋升之力","棋降之力","棋提之力","棋按之力","棋推之力","棋拉之力","棋拖之力","棋拽之力","棋扛之力","棋抬之力","棋搬之力","棋运之力","棋输之力","棋赢之力","棋得之力","棋失之力","棋取之力","棋舍之力","棋给之力","棋受之力","棋借之力","棋还之力","棋买之力","棋卖之力","棋租之力","棋赁之力","棋雇之力","棋聘之力","棋请之力","棋辞之力","棋招之力","棋募之力","棋集之力","棋散之力","棋聚之力","棋离之力","棋合之力","棋分之力","棋并之力","棋兼之力","棋混之力","棋清之力","棋澄之力","棋滤之力","棋洗之力","棋刷之力","棋擦之力","棋抹之力","棋涂之力","棋画之力","棋写之力","棋刻之力","棋雕之力","棋塑之力","棋铸之力","棋锻之力","棋炼之力","棋烧之力","棋烤之力","棋煮之力","棋蒸之力","棋炒之力","棋炸之力","棋煎之力","棋炖之力","棋熬之力","棋煲之力","棋焖之力","棋焗之力","棋熏之力","棋腌之力","棋泡之力","棋浸之力","棋渍之力","棋发酵","棋腐烂","棋生长","棋发育","棋成熟","棋衰老","棋死亡","棋复活","棋转生","棋轮回","棋涅槃","棋升华","棋堕落","棋飞升","棋下凡","棋成仙","棋化魔","棋变妖","棋为鬼","棋作怪","棋成精","棋显灵","棋附体","棋夺舍","棋寄生","棋共生","棋互利","棋竞争","棋捕食","棋被捕","棋猎物","棋猎人","棋农夫","棋陷阱","棋诱饵","棋诱捕","棋诱杀","棋诱骗","棋诱拐","棋诱惑","棋引诱","棋引导","棋导向","棋领导","棋指导","棋教导","棋教育","棋培训","棋训练","棋练习","棋实习","棋实践","棋实验","棋试验","棋测试","棋检验","棋检测","棋检查","棋审查","棋审核","棋审批","棋批准","棋许可","棋允许","棋同意","棋赞成","棋反对","棋否决","棋拒绝","棋接受","棋接收","棋领取"];
const rankNames=['青铜','白银','黄金','铂金','钻石','大师','宗师','王者'];
function initGame(){
loadGameData();
updateRankDisplay();
updateHistoryListHome();
showHomePage();
}
function showHomePage(){
homePage.style.display='flex';
gamePage.style.display='none';
matchPage.style.display='none';
gameMessage.classList.remove('show');
updateRankDisplay();
}
function showGamePage(mode){
currentGameMode=mode;
homePage.style.display='none';
gamePage.style.display='flex';
matchPage.style.display='none';
if(mode==='pvp'){
gamePageTitle.textContent='双人对战';
gamePageDescription.textContent='黑方与白方轮流落子,先连成五子者获胜';
whitePlayerName.textContent='玩家';
difficultySelector.style.display='none';
matchHistoryGame.style.display='none';
allowUndo=true;
}else if(mode==='pve'){
gamePageTitle.textContent='人机对战';
gamePageDescription.textContent='挑战AI,测试你的棋力水平';
whitePlayerName.textContent='AI';
difficultySelector.style.display='flex';
matchHistoryGame.style.display='none';
allowUndo=true;
updateAIName();
}else if(mode==='match'){
gamePageTitle.textContent='匹配对战';
gamePageDescription.textContent='与随机AI对战,赢取经验值';
whitePlayerName.textContent=currentMatchOpponent||'AI';
difficultySelector.style.display='none';
matchHistoryGame.style.display='block';
updateHistoryListGame();
allowUndo=false;
}
isMatchGame=(mode==='match');
restartGame();
updateUndoButton();
}
function showMatchPage(){
currentGameMode='match';
homePage.style.display='none';
gamePage.style.display='none';
matchPage.style.display='flex';
gameMessage.classList.remove('show');
startMatchingBtn.disabled=false;
startMatchingBtn.textContent='开始匹配';
matchingText.style.display='none';
matchedInfo.style.display='none';
isMatching=false;
isMatchGame=false;
}
function loadGameData(){
const savedData=localStorage.getItem('gomokuProMaxData');
if(savedData){
try{
const data=JSON.parse(savedData);
rank=data.rank||1;
experience=data.experience||0;
if(data.matchHistoryData){
matchHistoryData=data.matchHistoryData;
if(matchHistoryData.length>5){
matchHistoryData=matchHistoryData.slice(-5);
}
}else{
matchHistoryData=[];
}
}catch(e){
matchHistoryData=[];
}
}else{
matchHistoryData=[];
}
}
function saveGameData(){
const data={rank,experience,matchHistoryData:matchHistoryData||[]};
localStorage.setItem('gomokuProMaxData',JSON.stringify(data));
}
function updateRankDisplay(){
const rankName=rankNames[Math.min(rank-1,rankNames.length-1)];
rankValueHome.textContent=`${rankName} ${rank}段`;
rankValueGame.textContent=`${rankName} ${rank}段`;
currentExpHome.textContent=experience;
currentExpGame.textContent=experience;
expFillHome.style.width=`${(experience/5)*100}%`;
expFillGame.style.width=`${(experience/5)*100}%`;
}
function updateUndoButton(){
undoBtn.disabled=!allowUndo||gameOver||moveHistory.length===0;
}
const audioContext=new(window.AudioContext||window.webkitAudioContext)();
function playSound(frequency,duration,type='sine'){
if(!soundEnabled)return;
try{
const oscillator=audioContext.createOscillator();
const gainNode=audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value=frequency;
oscillator.type=type;
gainNode.gain.setValueAtTime(0.1,audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01,audioContext.currentTime+duration);
oscillator.start();
oscillator.stop(audioContext.currentTime+duration);
}catch(e){}
}
function initBoard(){
board.innerHTML='';
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
const cell=document.createElement('div');
cell.className='cell';
cell.dataset.row=i;
cell.dataset.col=j;
if((i===3||i===7||i===11)&&(j===3||j===7||j===11)){
const dot=document.createElement('div');
dot.style.position='absolute';
dot.style.width='8px';
dot.style.height='8px';
dot.style.backgroundColor='#8b6914';
dot.style.borderRadius='50%';
dot.style.zIndex='1';
cell.appendChild(dot);
}
cell.addEventListener('click',()=>handleCellClick(i,j));
board.appendChild(cell);
}
}
}
function handleCellClick(row,col){
if(gameOver||boardState[row][col])return;
placePiece(row,col,currentPlayer);
playSound(300+Math.random()*100,0.1,'sine');
const winResult=checkWin(row,col,currentPlayer);
if(winResult){
gameOver=true;
const winnerName=currentPlayer==='black'?'黑方':'白方';
if(isMatchGame){
if(currentPlayer==='black'){
addExperience(1);
addMatchHistory('胜利',currentMatchDifficulty,currentMatchOpponent);
showGameMessage(`${winnerName}获胜!`,true);
}else{
addExperience(-1);
addMatchHistory('失败',currentMatchDifficulty,currentMatchOpponent);
showGameMessage(`${winnerName}获胜!`,true);
}
}else{
showGameMessage(`${winnerName}获胜!`,false);
}
return;
}
if(isBoardFull()){
gameOver=true;
showGameMessage('平局!');
if(isMatchGame){
addMatchHistory('平局',currentMatchDifficulty,currentMatchOpponent);
}
return;
}
currentPlayer=currentPlayer==='black'?'white':'black';
updatePlayerIndicator();
if((currentGameMode==='pve'||currentGameMode==='match')&¤tPlayer==='white'&&!gameOver){
setTimeout(()=>{
aiThinking.classList.add('show');
setTimeout(()=>{
makeAIMove();
aiThinking.classList.remove('show');
},getAIDelay());
},300);
}
}
function placePiece(row,col,player){
boardState[row][col]=player;
moveHistory.push({row,col,player});
const cell=document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
const piece=document.createElement('div');
piece.className=`piece ${player}`;
cell.appendChild(piece);
setTimeout(()=>{
piece.classList.add('placed');
},10);
markLastMove(row,col);
}
function markLastMove(row,col){
if(lastMoveMarker){
lastMoveMarker.classList.remove('show');
}
const cell=document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
let marker=cell.querySelector('.last-move');
if(!marker){
marker=document.createElement('div');
marker.className='last-move';
cell.appendChild(marker);
}
marker.classList.add('show');
lastMoveMarker=marker;
}
function updatePlayerIndicator(){
const blackPlayer=document.querySelector('.black-player');
const whitePlayer=document.querySelector('.white-player');
if(currentPlayer==='black'){
blackPlayer.classList.add('current-player');
whitePlayer.classList.remove('current-player');
blackStatus.textContent='当前回合';
whiteStatus.textContent='等待中';
}else{
whitePlayer.classList.add('current-player');
blackPlayer.classList.remove('current-player');
blackStatus.textContent='等待中';
whiteStatus.textContent='当前回合';
}
}
function checkWin(row,col,player){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
for(let i=1;i<=4;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE&&boardState[newRow][newCol]===player){
count++;
}else{break;}
}
for(let i=1;i<=4;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE&&boardState[newRow][newCol]===player){
count++;
}else{break;}
}
if(count>=5){
playSound(600,0.3,'sine');
setTimeout(()=>playSound(800,0.3,'sine'),150);
setTimeout(()=>playSound(1000,0.5,'sine'),300);
return true;
}
}
return false;
}
function isBoardFull(){
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(!boardState[i][j]){return false;}
}
}
return true;
}
function restartGame(){
boardState=Array(BOARD_SIZE).fill().map(()=>Array(BOARD_SIZE).fill(null));
moveHistory=[];
currentPlayer='black';
gameOver=false;
if(lastMoveMarker){lastMoveMarker.classList.remove('show');}
updatePlayerIndicator();
initBoard();
updateUndoButton();
if((currentGameMode==='pve'||currentGameMode==='match')&&aiDifficulty!=='easy'&&Math.random()>0.5){
currentPlayer='white';
updatePlayerIndicator();
setTimeout(()=>{
aiThinking.classList.add('show');
setTimeout(()=>{
makeAIMove();
aiThinking.classList.remove('show');
},getAIDelay());
},500);
}
}
function undoMove(){
if(gameOver||moveHistory.length===0||!allowUndo)return;
const lastMove=moveHistory.pop();
boardState[lastMove.row][lastMove.col]=null;
const cell=document.querySelector(`.cell[data-row="${lastMove.row}"][data-col="${lastMove.col}"]`);
const piece=cell.querySelector('.piece');
if(piece){piece.remove();}
if(moveHistory.length>0){
const prevMove=moveHistory[moveHistory.length-1];
markLastMove(prevMove.row,prevMove.col);
}else if(lastMoveMarker){lastMoveMarker.classList.remove('show');}
currentPlayer=lastMove.player;
updatePlayerIndicator();
if((currentGameMode==='pve'||currentGameMode==='match')&&lastMove.player==='white'&&moveHistory.length>0){
const prevMove=moveHistory.pop();
boardState[prevMove.row][prevMove.col]=null;
const prevCell=document.querySelector(`.cell[data-row="${prevMove.row}"][data-col="${prevMove.col}"]`);
const prevPiece=prevCell.querySelector('.piece');
if(prevPiece){prevPiece.remove();}
if(moveHistory.length>0){
const newPrevMove=moveHistory[moveHistory.length-1];
markLastMove(newPrevMove.row,newPrevMove.col);
}else if(lastMoveMarker){lastMoveMarker.classList.remove('show');}
currentPlayer=prevMove.player;
updatePlayerIndicator();
}
gameOver=false;
updateUndoButton();
}
function showHint(){
if(gameOver)return;
const bestMove=getEasyAIMove();
if(!bestMove)return;
const cell=document.querySelector(`.cell[data-row="${bestMove.row}"][data-col="${bestMove.col}"]`);
cell.style.boxShadow='0 0 25px #4ecdc4';
cell.style.backgroundColor='rgba(78,205,196,0.4)';
playSound(500,0.3,'square');
setTimeout(()=>{
cell.style.boxShadow='';
cell.style.backgroundColor='';
},1500);
}
function getAIDelay(){
switch(aiDifficulty){
case'easy':return 300;
case'medium':return 600;
case'hard':return 900;
case'expert':return 1200;
case'grandmaster':return 1500;
default:return 600;
}
}
function makeAIMove(){
if(gameOver)return;
let bestMove;
switch(aiDifficulty){
case'easy':bestMove=getEasyAIMove();break;
case'medium':bestMove=getMediumAIMove();break;
case'hard':bestMove=getHardAIMove();break;
case'expert':bestMove=getExpertAIMove();break;
case'grandmaster':bestMove=getGrandmasterAIMove();break;
default:bestMove=getMediumAIMove();
}
if(bestMove){
placePiece(bestMove.row,bestMove.col,'white');
playSound(400+Math.random()*100,0.1,'sine');
const winResult=checkWin(bestMove.row,bestMove.col,'white');
if(winResult){
gameOver=true;
if(isMatchGame){
addExperience(-1);
addMatchHistory('失败',currentMatchDifficulty,currentMatchOpponent);
showGameMessage('白方(AI)获胜!',true);
}else{
showGameMessage('白方(AI)获胜!',false);
}
return;
}
if(isBoardFull()){
gameOver=true;
showGameMessage('平局!');
if(isMatchGame){addMatchHistory('平局',currentMatchDifficulty,currentMatchOpponent);}
return;
}
currentPlayer='black';
updatePlayerIndicator();
}
}
function getEasyAIMove(){
const candidateMoves=getCandidateMoves();
if(candidateMoves.length===0)return null;
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
if(checkWin(move.row,move.col,'white')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkWin(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
const playerOpenFourMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenFour(move.row,move.col,'black')){playerOpenFourMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(playerOpenFourMoves.length>0){
return playerOpenFourMoves[Math.floor(Math.random()*playerOpenFourMoves.length)];
}
const playerSleepFourMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkSleepFour(move.row,move.col,'black')){playerSleepFourMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(playerSleepFourMoves.length>0){
return playerSleepFourMoves[Math.floor(Math.random()*playerSleepFourMoves.length)];
}
const playerOpenThreeMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenThree(move.row,move.col,'black')){playerOpenThreeMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(playerOpenThreeMoves.length>0){
const aiOpenThreeMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
if(checkOpenThree(move.row,move.col,'white')){aiOpenThreeMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(aiOpenThreeMoves.length>0){
return aiOpenThreeMoves[Math.floor(Math.random()*aiOpenThreeMoves.length)];
}
return playerOpenThreeMoves[Math.floor(Math.random()*playerOpenThreeMoves.length)];
}
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
if(checkOpenThree(move.row,move.col,'white')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
const playerOpenTwoMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenTwo(move.row,move.col,'black')){playerOpenTwoMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(playerOpenTwoMoves.length>0){
const aiOpenTwoMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
if(checkOpenTwo(move.row,move.col,'white')){aiOpenTwoMoves.push(move);}
boardState[move.row][move.col]=null;
}
if(aiOpenTwoMoves.length>0){
return aiOpenTwoMoves[Math.floor(Math.random()*aiOpenTwoMoves.length)];
}
return playerOpenTwoMoves[Math.floor(Math.random()*playerOpenTwoMoves.length)];
}
const centerMoves=candidateMoves.filter(move=>{
const distFromCenter=Math.abs(move.row-7)+Math.abs(move.col-7);
return distFromCenter<=4;
});
if(centerMoves.length>0){return centerMoves[Math.floor(Math.random()*centerMoves.length)];}
return candidateMoves[Math.floor(Math.random()*candidateMoves.length)];
}
function checkOpenFour(row,col,player){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
let openEnds=0;
for(let i=1;i<=4;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===4)openEnds++;break;}
else{break;}
}else{break;}
}
for(let i=1;i<=4;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===4)openEnds++;break;}
else{break;}
}else{break;}
}
if(count===4&&openEnds===2){return true;}
}
return false;
}
function checkSleepFour(row,col,player){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
for(let offset=-4;offset<=0;offset++){
let count=0;
let emptyCount=0;
let emptyPositions=[];
for(let i=0;i<5;i++){
const newRow=row+dx*(i+offset);
const newCol=col+dy*(i+offset);
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){emptyCount++;emptyPositions.push({row:newRow,col:newCol});}
}
}
if(count===4&&emptyCount===1){
if(emptyPositions.length>0){
const emptyPos=emptyPositions[0];
const leftBlocked=checkBlocked(emptyPos.row-dx,emptyPos.col-dy,player);
const rightBlocked=checkBlocked(emptyPos.row+dx,emptyPos.col+dy,player);
if(leftBlocked||rightBlocked){return true;}
}
}
}
}
return false;
}
function checkBlocked(row,col,player){
if(row<0||row>=BOARD_SIZE||col<0||col>=BOARD_SIZE){return true;}
return boardState[row][col]!==null&&boardState[row][col]!==player;
}
function checkOpenThree(row,col,player){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
let openEnds=0;
for(let i=1;i<=3;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===3)openEnds++;break;}
else{break;}
}else{break;}
}
for(let i=1;i<=3;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===3)openEnds++;break;}
else{break;}
}else{break;}
}
if(count===3&&openEnds===2){return true;}
}
return false;
}
function checkOpenTwo(row,col,player){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
let openEnds=0;
for(let i=1;i<=2;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===2)openEnds++;break;}
else{break;}
}else{break;}
}
for(let i=1;i<=2;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){if(i===2)openEnds++;break;}
else{break;}
}else{break;}
}
if(count===2&&openEnds===2){return true;}
}
return false;
}
function getMediumAIMove(){
let bestScore=-Infinity;
let bestMove=null;
const candidateMoves=getCandidateMoves();
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkWin(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenFour(move.row,move.col,'black')||checkSleepFour(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
const score=evaluateBoard('white');
boardState[move.row][move.col]=null;
if(score>bestScore){
bestScore=score;
bestMove=move;
}
}
return bestMove||getEasyAIMove();
}
function getHardAIMove(){
let bestScore=-Infinity;
let bestMove=null;
const candidateMoves=getCandidateMoves();
const scoredMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkWin(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenFour(move.row,move.col,'black')||checkSleepFour(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
const score=evaluateBoard('white');
boardState[move.row][move.col]=null;
scoredMoves.push({move,score});
}
scoredMoves.sort((a,b)=>b.score-a.score);
const topMoves=scoredMoves.slice(0,Math.min(7,scoredMoves.length));
for(const{move}of topMoves){
boardState[move.row][move.col]='white';
const score=fastMinimax(2,false,-Infinity,Infinity);
boardState[move.row][move.col]=null;
if(score>bestScore){
bestScore=score;
bestMove=move;
}
}
return bestMove||getMediumAIMove();
}
function getExpertAIMove(){
let bestScore=-Infinity;
let bestMove=null;
const candidateMoves=getCandidateMoves();
const scoredMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkWin(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenFour(move.row,move.col,'black')||checkSleepFour(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
const score=evaluateBoard('white');
boardState[move.row][move.col]=null;
scoredMoves.push({move,score});
}
scoredMoves.sort((a,b)=>b.score-a.score);
const topMoves=scoredMoves.slice(0,Math.min(9,scoredMoves.length));
for(const{move}of topMoves){
boardState[move.row][move.col]='white';
const score=fastMinimax(3,false,-Infinity,Infinity);
boardState[move.row][move.col]=null;
if(score>bestScore){
bestScore=score;
bestMove=move;
}
}
return bestMove||getHardAIMove();
}
function getGrandmasterAIMove(){
let bestScore=-Infinity;
let bestMove=null;
const candidateMoves=getCandidateMoves();
const scoredMoves=[];
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkWin(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='black';
if(checkOpenFour(move.row,move.col,'black')||checkSleepFour(move.row,move.col,'black')){
boardState[move.row][move.col]=null;
return move;
}
boardState[move.row][move.col]=null;
}
for(const move of candidateMoves){
boardState[move.row][move.col]='white';
const score=evaluateBoard('white');
boardState[move.row][move.col]=null;
scoredMoves.push({move,score});
}
scoredMoves.sort((a,b)=>b.score-a.score);
const topMoves=scoredMoves.slice(0,Math.min(11,scoredMoves.length));
for(const{move}of topMoves){
boardState[move.row][move.col]='white';
const score=fastMinimax(4,false,-Infinity,Infinity);
boardState[move.row][move.col]=null;
if(score>bestScore){
bestScore=score;
bestMove=move;
}
}
return bestMove||getExpertAIMove();
}
function fastMinimax(depth,isMaximizing,alpha,beta){
if(depth===0){return evaluateBoard('white');}
const gameResult=checkGameResult();
if(gameResult!==null){return gameResult;}
if(isMaximizing){
let maxScore=-Infinity;
const candidateMoves=getCandidateMoves();
const topMoves=candidateMoves.slice(0,Math.min(8,candidateMoves.length));
for(const move of topMoves){
boardState[move.row][move.col]='white';
const score=fastMinimax(depth-1,false,alpha,beta);
boardState[move.row][move.col]=null;
maxScore=Math.max(maxScore,score);
alpha=Math.max(alpha,score);
if(beta<=alpha)break;
}
return maxScore;
}else{
let minScore=Infinity;
const candidateMoves=getCandidateMoves();
const topMoves=candidateMoves.slice(0,Math.min(8,candidateMoves.length));
for(const move of topMoves){
boardState[move.row][move.col]='black';
const score=fastMinimax(depth-1,true,alpha,beta);
boardState[move.row][move.col]=null;
minScore=Math.min(minScore,score);
beta=Math.min(beta,score);
if(beta<=alpha)break;
}
return minScore;
}
}
function checkGameResult(){
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(boardState[i][j]==='white'&&checkWin(i,j,'white')){return 1000000;}
}
}
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(boardState[i][j]==='black'&&checkWin(i,j,'black')){return -1000000;}
}
}
if(isBoardFull()){return 0;}
return null;
}
function getCandidateMoves(){
const candidateMoves=[];
const directions=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(boardState[i][j]){
for(const[dx,dy]of directions){
const newRow=i+dx;
const newCol=j+dy;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE&&!boardState[newRow][newCol]){
if(!candidateMoves.some(move=>move.row===newRow&&move.col===newCol)){
candidateMoves.push({row:newRow,col:newCol});
}
}
}
}
}
}
if(candidateMoves.length===0){
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(!boardState[i][j]){candidateMoves.push({row:i,col:j});}
}
}
}
return candidateMoves;
}
function evaluateBoard(player){
let score=0;
const opponent=player==='white'?'black':'white';
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(boardState[i][j]===player){score+=evaluatePosition(i,j,player);}
else if(boardState[i][j]===opponent){score-=evaluatePosition(i,j,opponent)*1.2;}
}
}
for(let i=5;i<=9;i++){
for(let j=5;j<=9;j++){
if(boardState[i][j]===player){score+=25;}
else if(boardState[i][j]===opponent){score-=25;}
}
}
score+=evaluateThreats(player)*100;
score-=evaluateThreats(opponent)*120;
return score;
}
function evaluatePosition(row,col,player){
let score=0;
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
let openEnds=0;
for(let i=1;i<=4;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){openEnds++;break;}
else{break;}
}else{break;}
}
for(let i=1;i<=4;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE){
if(boardState[newRow][newCol]===player){count++;}
else if(boardState[newRow][newCol]===null){openEnds++;break;}
else{break;}
}else{break;}
}
if(count>=5){score+=1000000;}
else if(count===4){
if(openEnds===2){score+=100000;}
else if(openEnds===1){score+=5000;}
}
else if(count===3){
if(openEnds===2){score+=3000;}
else if(openEnds===1){score+=500;}
}
else if(count===2){
if(openEnds===2){score+=300;}
else if(openEnds===1){score+=50;}
}
else if(count===1&&openEnds===2){score+=10;}
}
return score;
}
function evaluateThreats(player){
let threatScore=0;
for(let i=0;i<BOARD_SIZE;i++){
for(let j=0;j<BOARD_SIZE;j++){
if(!boardState[i][j]){
boardState[i][j]=player;
let threats=0;
if(checkPotentialWin(i,j,player,3))threats++;
if(checkPotentialWin(i,j,player,4))threats++;
boardState[i][j]=null;
if(threats>=2){threatScore+=50*threats;}
}
}
}
return threatScore;
}
function checkPotentialWin(row,col,player,length){
const directions=[[0,1],[1,0],[1,1],[1,-1]];
for(const[dx,dy]of directions){
let count=1;
for(let i=1;i<=4;i++){
const newRow=row+dx*i;
const newCol=col+dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE&&boardState[newRow][newCol]===player){count++;}else{break;}
}
for(let i=1;i<=4;i++){
const newRow=row-dx*i;
const newCol=col-dy*i;
if(newRow>=0&&newRow<BOARD_SIZE&&newCol>=0&&newCol<BOARD_SIZE&&boardState[newRow][newCol]===player){count++;}else{break;}
}
if(count>=length){return true;}
}
return false;
}
function startMatching(){
if(isMatching)return;
isMatching=true;
startMatchingBtn.disabled=true;
startMatchingBtn.textContent='匹配中...';
matchingText.style.display='block';
matchedInfo.style.display='none';
const waitTime=3000+Math.random()*2000;
setTimeout(()=>{
const difficulties=['easy','medium','hard','expert','grandmaster'];
const randomDifficulty=difficulties[Math.floor(Math.random()*difficulties.length)];
aiDifficulty=randomDifficulty;
currentMatchDifficulty=randomDifficulty;
const randomName=aiNames[Math.floor(Math.random()*aiNames.length)];
currentMatchOpponent=randomName;
matchingText.style.display='none';
matchedInfo.style.display='block';
opponentName.textContent=randomName;
const difficultyDisplay={'easy':'简单','medium':'中等','hard':'困难','expert':'专家','grandmaster':'宗师'};
opponentDifficulty.textContent=difficultyDisplay[randomDifficulty]+'级';
setTimeout(()=>{showGamePage('match');},1000);
},waitTime);
}
function showGameMessage(message,showExpInfo=false){
messageContent.textContent=message;
if(showExpInfo&&isMatchGame){
expInfo.style.display='block';
const isWin=message.includes('黑方获胜');
if(isWin){
expChange.textContent='+1 经验值';
expChange.className='exp-change exp-gain';
}else{
expChange.textContent='-1 经验值';
expChange.className='exp-change exp-loss';
}
}else{
expInfo.style.display='none';
rankUpMessage.style.display='none';
}
gameMessage.classList.add('show');
}
function addExperience(amount){
if(!isMatchGame)return;
experience+=amount;
while(experience>=5&&rank<8){
experience-=5;
rank++;
rankUpMessage.style.display='block';
playSound(800,0.3,'sine');
setTimeout(()=>playSound(1000,0.3,'sine'),150);
setTimeout(()=>playSound(1200,0.5,'sine'),300);
}
while(experience<0&&rank>1){
experience+=5;
rank--;
}
experience=Math.max(0,Math.min(4,experience));
updateRankDisplay();
saveGameData();
}
function addMatchHistory(result,difficulty,opponent){
if(!matchHistoryData){matchHistoryData=[];}
const historyItem={
date:new Date().toLocaleString(),
result,
difficulty:difficulty==='easy'?'简单':difficulty==='medium'?'中等':difficulty==='hard'?'困难':difficulty==='expert'?'专家':'宗师',
opponent:opponent||'AI',
rank:rankNames[Math.min(rank-1,rankNames.length-1)]+rank+'段'
};
matchHistoryData.push(historyItem);
if(matchHistoryData.length>5){matchHistoryData=matchHistoryData.slice(-5);}
updateHistoryListHome();
updateHistoryListGame();
saveGameData();
}
function updateHistoryListHome(){
historyListHome.innerHTML='';
if(!matchHistoryData||matchHistoryData.length===0){
const emptyDiv=document.createElement('div');
emptyDiv.className='history-item-home';
emptyDiv.textContent='暂无对战记录';
historyListHome.appendChild(emptyDiv);
return;
}
matchHistoryData.slice(-5).reverse().forEach(item=>{
const div=document.createElement('div');
div.className=`history-item-home ${item.result==='胜利'?'history-win':item.result==='失败'?'history-loss':'history-draw'}`;
div.innerHTML=`<div style="font-weight:bold">${item.result} (${item.difficulty})</div><div style="font-size:0.8rem;color:#aaa">对手: ${item.opponent}</div><div style="font-size:0.8rem;color:#888">${item.date}</div>`;
historyListHome.appendChild(div);
});
}
function updateHistoryListGame(){
historyListGame.innerHTML='';
if(!matchHistoryData||matchHistoryData.length===0){
const emptyDiv=document.createElement('div');
emptyDiv.className='history-item-home';
emptyDiv.textContent='暂无匹配记录';
historyListGame.appendChild(emptyDiv);
return;
}
matchHistoryData.slice().reverse().forEach(item=>{
const div=document.createElement('div');
div.className=`history-item-home ${item.result==='胜利'?'history-win':item.result==='失败'?'history-loss':'history-draw'}`;
div.innerHTML=`<div style="font-weight:bold">${item.result} (${item.difficulty})</div><div style="font-size:0.8rem;color:#aaa">对手: ${item.opponent}</div><div style="font-size:0.8rem;color:#888">${item.date}</div>`;
historyListGame.appendChild(div);
});
}
function updateAIName(){
const difficultyNames={'easy':'AI-简单','medium':'AI-中等','hard':'AI-困难','expert':'AI-专家','grandmaster':'AI-宗师'};
whitePlayerName.textContent=difficultyNames[aiDifficulty];
}
function toggleSound(){
soundEnabled=!soundEnabled;
soundToggleBtn.textContent=`音效: ${soundEnabled?'开':'关'}`;
}
pvpModeCard.addEventListener('click',()=>{showGamePage('pvp');});
pveModeCard.addEventListener('click',()=>{showGamePage('pve');});
matchModeCard.addEventListener('click',()=>{showMatchPage();});
backHomeBtn.addEventListener('click',showHomePage);
restartBtn.addEventListener('click',restartGame);
undoBtn.addEventListener('click',undoMove);
hintBtn.addEventListener('click',showHint);
soundToggleBtn.addEventListener('click',toggleSound);
difficultySelector.addEventListener('click',(e)=>{
if(e.target.classList.contains('difficulty-btn')){
document.querySelectorAll('.difficulty-btn').forEach(btn=>{btn.classList.remove('active');});
e.target.classList.add('active');
aiDifficulty=e.target.dataset.level;
updateAIName();
restartGame();
}
});
startMatchingBtn.addEventListener('click',startMatching);
backHomeFromMatch.addEventListener('click',showHomePage);
backHomeMessageBtn.addEventListener('click',()=>{
gameMessage.classList.remove('show');
showHomePage();
});
initGame();
});
</script>
</body>
</html>
咳咳
In fact, 70% of this article was generated by AI.