<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>五子棋验证卡密</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
align-items: center;
padding: 15px 0;
min-height: 100vh;
width: 100%;
overflow-x: hidden;
}
#title {
font-size: clamp(1.2rem, 3vw, 1.5rem);
color: #333;
margin: 0 15px 8px;
text-align: center;
width: 100%;
max-width: 90%;
}
#notice {
font-size: clamp(0.9rem, 2vw, 1rem);
color: #666;
margin: 0 15px 12px;
text-align: center;
width: 100%;
max-width: 90%;
}
#difficulty-tip {
font-size: clamp(0.85rem, 2vw, 1rem);
color: #e63946;
margin: 0 15px 10px;
font-weight: bold;
text-align: center;
width: 100%;
max-width: 90%;
padding: 5px 10px;
background-color: rgba(230, 57, 70, 0.05);
border-radius: 4px;
}
#chess-color-tip {
font-size: clamp(0.8rem, 1.8vw, 0.9rem);
color: #e63946;
margin: 0 15px 10px;
font-weight: bold;
text-align: center;
width: 100%;
max-width: 90%;
line-height: 1.4;
display: none;
}
#capital-tip {
font-size: clamp(0.8rem, 1.8vw, 0.9rem);
color: #f77f00;
margin: 8px 15px;
font-weight: bold;
display: none;
animation: flash 0.8s infinite alternate;
text-align: center;
width: 100%;
max-width: 90%;
}
@keyframes flash {
from {opacity: 1; transform: scale(1);}
to {opacity: 0.7; transform: scale(1.03);}
}
#chess-container {
background-color: #d18b47;
padding: clamp(6px, 1.5vw, 8px);
border-radius: 5px;
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
width: calc(100vw - 30px);
height: calc(100vw - 30px);
max-height: calc(100vh - 200px);
min-width: 240px;
min-height: 240px;
margin: 0 auto;
display: none;
}
#chess-board {
display: grid;
grid-template-columns: repeat(15, 1fr);
grid-template-rows: repeat(15, 1fr);
gap: 1px;
width: 100%;
height: 100%;
}
.chess-cell {
position: relative;
cursor: pointer;
}
.chess-cell::before {
content: "";
position: absolute;
width: 100%;
height: 1.5px;
background-color: #333;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.chess-cell::after {
content: "";
position: absolute;
width: 1.5px;
height: 100%;
background-color: #333;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.chess-black, .chess-white {
position: absolute;
width: 82%;
height: 82%;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
border: 1px solid rgba(0,0,0,0.2);
transition: all 0.3s ease;
}
.chess-black {
background-color: #000;
box-shadow: inset 0 0 3px rgba(255,255,255,0.1);
}
.chess-white {
background-color: #fff;
border: 1px solid #bbb;
box-shadow: 0 0 2px rgba(0,0,0,0.1);
}
/* 高亮棋子样式 */
.chess-black.win-highlight {
background: linear-gradient(45deg, #000, #ff6b6b);
box-shadow: 0 0 15px #ff6b6b, inset 0 0 5px rgba(255,255,255,0.3);
transform: translate(-50%, -50%) scale(1.1);
border: 2px solid #ffeb3b;
}
.chess-white.win-highlight {
background: linear-gradient(45deg, #fff, #ff6b6b);
box-shadow: 0 0 15px #ff6b6b, 0 0 5px rgba(0,0,0,0.3);
transform: translate(-50%, -50%) scale(1.1);
border: 2px solid #ffeb3b;
}
.last-user-move {
position: absolute;
width: 40%;
height: 40%;
border: 2px solid #e63946;
border-radius: 50%;
background: transparent;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
pointer-events: none;
}
.last-ai-move {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
pointer-events: none;
font-size: clamp(8px, 2vw, 12px);
font-weight: bold;
color: #fff;
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
}
/* 修复:白棋AI标记颜色问题 */
.chess-white .last-ai-move {
color: #1d3557;
text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
}
#win-tip {
font-size: clamp(0.9rem, 2vw, 1.1rem);
color: #e63946;
margin: 15px 15px 8px;
font-weight: bold;
display: none;
text-align: center;
line-height: 1.5;
width: 100%;
max-width: 90%;
}
.restart-btn {
padding: clamp(8px, 2vw, 12px) clamp(20px, 5vw, 28px);
background-color: #1d3557;
color: #fff;
border: none;
border-radius: 4px;
font-size: clamp(0.9rem, 2vw, 1rem);
cursor: pointer;
transition: background-color 0.3s;
margin-top: 8px;
}
.restart-btn:hover {
background-color: #0a1a2f;
}
#restart-btn-container {
display: none;
justify-content: center;
margin: 0 15px 15px;
width: 100%;
}
#verify-section {
background-color: #fff;
padding: clamp(15px, 4vw, 20px);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
width: calc(100vw - 30px);
max-width: 500px;
display: none;
margin: 10px auto 15px;
}
.form-group {
margin-bottom: 15px;
width: 100%;
}
.form-group label {
display: block;
font-size: clamp(0.9rem, 2vw, 1rem);
color: #333;
margin-bottom: 6px;
}
.form-group input {
width: 100%;
padding: clamp(9px, 2.2vw, 11px);
border: 1px solid #ddd;
border-radius: 4px;
font-size: clamp(0.85rem, 1.8vw, 0.95rem);
box-sizing: border-box;
}
.btn-group {
display: flex;
gap: clamp(8px, 2vw, 12px);
margin-top: 8px;
width: 100%;
}
.btn {
flex: 1;
padding: clamp(9px, 2.2vw, 11px);
border: none;
border-radius: 4px;
font-size: clamp(0.85rem, 1.8vw, 0.95rem);
cursor: pointer;
transition: background-color 0.3s;
}
#Query_Trial {
background-color: #457b9d;
color: #fff;
}
#Query_Trial:hover {
background-color: #1d3557;
}
#Verify {
background-color: #1d3557;
color: #fff;
}
#Verify:hover {
background-color: #0a1a2f;
}
#Pay {
width: 100%;
background-color: #e63946;
color: #fff;
margin-top: 10px;
}
#Pay:hover {
background-color: #c1121f;
}
</style>
</head>
<body>
<h1 id="title"></h1>
<p id="notice"></p>
<!-- 难度提示:必须保留,显示识别结果 -->
<div id="difficulty-tip">正在识别难度...</div>
<div id="chess-color-tip">
你使用的棋子:<span style="color: #000; border: 1px solid #ccc; padding: 2px 6px; border-radius: 3px; font-size: 0.85rem;">黑色</span>
| <span style="color:#e63946">你的落棋:棋内红色圈</span>
| <span style="color:#1d3557">AI落棋:棋内"AI"文字</span>
</div>
<div id="capital-tip">⚠️ AI触发「资本做局」!替换你[危险等级]的最危险棋子(该棋子转为AI所有) ⚠️</div>
<div id="chess-container">
<div id="chess-board"></div>
</div>
<div id="win-tip">AI获胜,点击下方按钮重新开局</div>
<div id="restart-btn-container">
<button id="restart-btn" class="restart-btn" onclick="restartGame()">确认重新开局</button>
</div>
<!-- 查码按钮绑定 -->
<div id="verify-section">
<div class="form-group">
<label for="card-code">请输入卡密</label>
<input type="text" id="card-code" placeholder="例如:ABC123-DEF456-GHI789" />
</div>
<div class="btn-group">
<button class="btn" id="Query_Trial" onclick="Call_Query_Trial(document.getElementById('card-code').value)"></button>
<button class="btn" id="Verify" onclick="Call_Verify(document.getElementById('card-code').value)">验证</button>
</div>
<button class="btn" id="Pay" onclick="Call_Pay()"></button>
</div>
<script>
let gameState = {
size: 15,
userColor: Math.random() > 0.5 ? "black" : "white",
aiColor: "",
currentPlayer: "",
chessData: [],
userChessPositions: [],
replacedUserPositions: new Set(),
isGameOver: false,
lastUserMove: null,
lastAIMove: null,
difficulty: "中", // 默认难度
capitalGameRate: {
level1: 0.01,
level2: 0.05,
level3: 0.15,
level4: 0.3,
level5: 0.5
},
winHighlightPositions: [], // 存储获胜棋子的位置
dom: {
chessBoard: document.getElementById("chess-board"),
winTip: document.getElementById("win-tip"),
restartBtnContainer: document.getElementById("restart-btn-container"),
restartBtn: document.getElementById("restart-btn"),
verifySection: document.getElementById("verify-section"),
chessColorTip: document.getElementById("chess-color-tip"),
payBtn: document.getElementById("Pay"),
capitalTip: document.getElementById("capital-tip"),
title: document.getElementById("title"),
notice: document.getElementById("notice"),
queryTrialBtn: document.getElementById("Query_Trial"),
difficultyTip: document.getElementById("difficulty-tip"),
chessContainer: document.getElementById("chess-container")
}
};
gameState.aiColor = gameState.userColor === "black" ? "white" : "black";
gameState.currentPlayer = gameState.userColor === "black" ? "user" : "ai";
gameState.chessData = Array(gameState.size).fill().map(() => Array(gameState.size).fill(null));
// ------------------------------
// 恢复核心:难度识别逻辑(从标题提取<强>/<中>/<弱>/<关>)
// ------------------------------
function extractDifficultyFromTitle(title) {
// 匹配标题中的难度标记(兼容带空格格式,如< 强 >)
const difficultyMatch = title.match(/<\s*(\S+)\s*>/);
const validDifficulties = ["强", "中", "弱", "关"];
if (difficultyMatch && difficultyMatch[1] && validDifficulties.includes(difficultyMatch[1])) {
const difficulty = difficultyMatch[1];
// 清理标题:移除难度标记,避免显示在页面上
const cleanTitle = title.replace(/<\s*\S+\s*>/, "").trim();
console.log("难度识别成功:", difficulty, "| 清理后标题:", cleanTitle);
return { difficulty, cleanTitle, success: true };
} else {
console.log("未识别到有效难度标记,默认难度=中");
return { difficulty: "中", cleanTitle: title.trim(), success: false };
}
}
// 恢复:难度规则(强→中→弱→关逐级递减)
function getDifficultyRule(difficulty) {
const ruleMap = {
"强": { hasCapitalGame: true, aiAttack: true, aiDefend: true, needPlayGame: true, desc: "AI有资本做局+主动进攻+防守(最难)" },
"中": { hasCapitalGame: false, aiAttack: true, aiDefend: true, needPlayGame: true, desc: "AI无资本做局+主动进攻+防守(比强简单)" },
"弱": { hasCapitalGame: false, aiAttack: false, aiDefend: "nearOnly", needPlayGame: true, desc: "AI无资本做局+仅附近防守(比中简单)" },
"关": { hasCapitalGame: false, aiAttack: false, aiDefend: false, needPlayGame: false, desc: "无需下棋,直接输卡密(最简单)" }
};
return ruleMap[difficulty] || ruleMap["中"];
}
// ------------------------------
// 修复:整合查码初始化和难度识别,不冲突
// ------------------------------
function initPanGolinData() {
gameState.dom.difficultyTip.innerHTML = "正在识别难度...";
try {
// 1. 先获取PanGolin原始标题(用于难度识别)
let originalTitle = "";
if (typeof PanGolin !== "undefined" && typeof PanGolin.GetTitle === "function") {
originalTitle = PanGolin.GetTitle() || "五子棋验证卡密系统";
} else {
originalTitle = "五子棋验证卡密系统";
}
// 2. 执行难度识别:提取难度+清理标题
const { difficulty, cleanTitle, success } = extractDifficultyFromTitle(originalTitle);
gameState.difficulty = difficulty;
const difficultyRule = getDifficultyRule(difficulty);
// 3. 严格按用户提供的JS更新标题、公告、查码按钮文本
document.getElementById("title").innerHTML = cleanTitle; // 用清理后的标题(移除难度标记)
document.getElementById("notice").innerHTML = (typeof PanGolin !== "undefined" && PanGolin.GetNotice) ? PanGolin.GetNotice() : "完成五子棋获胜,即可解锁卡密验证功能";
document.getElementById("Query_Trial").innerHTML = (typeof PanGolin !== "undefined" && typeof PanGolin.Is_Trial !== "undefined") ? (PanGolin.Is_Trial() == true ? "试用" : "查码") : "查码";
document.getElementById("Pay").style.display = (typeof PanGolin !== "undefined" && typeof PanGolin.Is_Pay !== "undefined") ? (PanGolin.Is_Pay() == true ? "block" : "none") : "none";
// 4. 更新难度提示(让用户看到识别结果)
if (success) {
gameState.dom.difficultyTip.innerHTML = `✅ 难度识别成功:${difficulty} | ${difficultyRule.desc}`;
} else {
gameState.dom.difficultyTip.innerHTML = `⚠️ 未识别到难度标记(需含<强>/<中>/<弱>/<关>)| 默认难度:中 | ${difficultyRule.desc}`;
}
// 5. 支付按钮文本兜底
gameState.dom.payBtn.innerHTML = (typeof PanGolin !== "undefined" && PanGolin.GetPayText) ? PanGolin.GetPayText() : "前往支付";
// 6. 根据难度规则适配UI(棋盘/卡密区显示)
adaptUIByRule(difficultyRule);
} catch (e) {
// 异常兜底:保留难度识别和查码功能
gameState.difficulty = "中";
const defaultRule = getDifficultyRule("中");
document.getElementById("title").innerHTML = "五子棋验证卡密系统";
document.getElementById("notice").innerHTML = "完成五子棋获胜,即可解锁卡密验证功能";
document.getElementById("Query_Trial").innerHTML = "查码";
document.getElementById("Pay").style.display = "none";
gameState.dom.payBtn.innerHTML = "前往支付";
gameState.dom.difficultyTip.innerHTML = `❌ 初始化出错 | 默认难度:中 | ${defaultRule.desc}`;
adaptUIByRule(defaultRule);
console.error("PanGolin初始化异常:", e);
}
}
// 恢复:根据难度规则适配UI
function adaptUIByRule(rule) {
const { chessContainer, verifySection, chessColorTip } = gameState.dom;
if (rule.needPlayGame) {
// 需要下棋:显示棋盘,隐藏卡密区
chessContainer.style.display = "block";
verifySection.style.display = "none";
chessColorTip.style.display = "block";
} else {
// 无需下棋(关难度):隐藏棋盘,显示卡密区
chessContainer.style.display = "none";
verifySection.style.display = "block";
chessColorTip.style.display = "none";
}
gameState.dom.capitalTip.style.display = "none";
gameState.dom.restartBtnContainer.style.display = "none";
}
// 修复:更新落棋标记 - 确保每次落子后都正确更新标记
function updateLastUserMove(pos) {
// 清除所有用户标记
const oldUserMarks = document.querySelectorAll(".last-user-move");
oldUserMarks.forEach(mark => mark.remove());
gameState.lastUserMove = pos;
if (!pos) return;
const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
if (!cell) return;
const userChess = cell.querySelector(`.chess-${gameState.userColor}`);
if (userChess) {
const userMark = document.createElement("span");
userMark.className = "last-user-move";
userChess.appendChild(userMark);
}
}
function updateLastAIMove(pos) {
// 清除所有AI标记
const oldAIMarks = document.querySelectorAll(".last-ai-move");
oldAIMarks.forEach(mark => mark.remove());
gameState.lastAIMove = pos;
if (!pos) return;
const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
if (!cell) return;
const aiChess = cell.querySelector(`.chess-${gameState.aiColor}`);
if (aiChess) {
const aiMark = document.createElement("span");
aiMark.className = "last-ai-move";
aiMark.textContent = "AI";
aiChess.appendChild(aiMark);
}
}
// 页面初始化:同时执行难度识别和查码初始化
function initPage() {
initPanGolinData(); // 一次调用,同时完成难度识别和查码配置
const currentRule = getDifficultyRule(gameState.difficulty);
if (currentRule.needPlayGame) {
renderChessBoard();
if (gameState.currentPlayer === "ai") {
setTimeout(() => aiFirstPlace(), 300);
}
}
}
function renderChessBoard() {
gameState.dom.chessBoard.innerHTML = "";
for (let i = 0; i < gameState.size; i++) {
for (let j = 0; j < gameState.size; j++) {
const cell = document.createElement("div");
cell.className = "chess-cell";
cell.dataset.row = i;
cell.dataset.col = j;
cell.onclick = () => userPlaceChess(i, j);
gameState.dom.chessBoard.appendChild(cell);
}
}
// 重新渲染已有的棋子
for (let i = 0; i < gameState.size; i++) {
for (let j = 0; j < gameState.size; j++) {
if (gameState.chessData[i][j]) {
const cell = document.querySelector(`.chess-cell[data-row="${i}"][data-col="${j}"]`);
if (cell) {
const chessDom = document.createElement("div");
chessDom.className = `chess-${gameState.chessData[i][j]}`;
// 如果是获胜棋子,添加高亮样式
const isWinPiece = gameState.winHighlightPositions.some(pos =>
pos.row === i && pos.col === j
);
if (isWinPiece) {
chessDom.classList.add('win-highlight');
}
cell.appendChild(chessDom);
}
}
}
}
// 恢复标记 - 确保标记正确显示
if (gameState.lastUserMove) {
updateLastUserMove(gameState.lastUserMove);
}
if (gameState.lastAIMove) {
updateLastAIMove(gameState.lastAIMove);
}
}
// 弱难度:仅用户落棋附近防守
function getUserNearEmptyPositions(lastUserPos) {
const emptyPositions = new Set();
if (!lastUserPos) return [];
const { row: uRow, col: uCol } = lastUserPos;
// 仅遍历用户落棋周围1格(3x3范围)
for (let i = uRow - 1; i <= uRow + 1; i++) {
for (let j = uCol - 1; j <= uCol + 1; j++) {
if (isInBoard(i, j) && gameState.chessData[i][j] === null) {
emptyPositions.add(`${i}-${j}`);
}
}
}
return Array.from(emptyPositions).map(str => ({ row: Number(str.split('-')[0]), col: Number(str.split('-')[1]) }));
}
// 基础工具函数
function isReplacedPosition(row, col) {
return gameState.replacedUserPositions.has(`${row}-${col}`);
}
function getUserValidChessCount() {
return gameState.userChessPositions.length;
}
function isInBoard(row, col) {
return row >= 0 && row < gameState.size && col >= 0 && col < gameState.size;
}
// 资本做局(仅强难度生效)
function triggerCapitalGameByLevel(dangerInfo, nearEmptyPos) {
const currentRule = getDifficultyRule(gameState.difficulty);
if (!currentRule.hasCapitalGame) return null;
const { level, desc } = dangerInfo;
const targetLevel = Math.min(level, 5);
let triggerRate = gameState.capitalGameRate[`level${targetLevel}`] || 0;
if (Math.random() > triggerRate) return null;
const mostDangerousPos = findMostDangerousUserChess(level, nearEmptyPos);
if (!mostDangerousPos) return null;
const { row: dRow, col: dCol } = mostDangerousPos;
const cellDom = document.querySelector(`.chess-cell[data-row="${dRow}"][data-col="${dCol}"]`);
const userChessDom = cellDom.querySelector(`.chess-${gameState.userColor}`);
if (userChessDom) userChessDom.remove();
gameState.userChessPositions = gameState.userChessPositions.filter(p => !(p.row === dRow && p.col === dCol));
gameState.lastUserMove = null;
gameState.replacedUserPositions.add(`${dRow}-${dCol}`);
gameState.chessData[dRow][dCol] = gameState.aiColor;
const aiChessDom = document.createElement("div");
aiChessDom.className = `chess-${gameState.aiColor}`;
cellDom.appendChild(aiChessDom);
// 修复:资本做局后立即更新AI标记
updateLastAIMove({ row: dRow, col: dCol });
gameState.dom.capitalTip.innerHTML = `⚠️ AI触发「资本做局」!替换你${desc}的最危险棋子(该棋子转为AI所有) ⚠️`;
gameState.dom.capitalTip.style.display = "block";
if (checkWin(dRow, dCol, gameState.aiColor)) {
gameState.isGameOver = true;
gameState.dom.winTip.textContent = "AI触发资本做局后获胜,点击下方按钮重新开局";
gameState.dom.winTip.style.display = "block";
gameState.dom.restartBtnContainer.style.display = "flex";
}
return mostDangerousPos;
}
// AI决策(按难度规则)
function aiDecision(dangerInfo, nearEmptyPos) {
const currentRule = getDifficultyRule(gameState.difficulty);
const { level, pos: dangerPos } = dangerInfo;
if (level >= 2 && dangerPos) return dangerPos;
if (currentRule.aiAttack) {
// 强/中难度:主动进攻
let attackPos = null;
for (let i = 0; i < nearEmptyPos.length; i++) {
const p = nearEmptyPos[i];
if (canFormLiveThree(p.row, p.col, gameState.aiColor)) {
attackPos = p;
break;
}
}
if (!attackPos) {
for (let i = 0; i < nearEmptyPos.length; i++) {
const p = nearEmptyPos[i];
if (canFormLiveTwo(p.row, p.col, gameState.aiColor)) {
attackPos = p;
break;
}
}
}
return attackPos || (nearEmptyPos.length > 0 ? nearEmptyPos[0] : null);
} else if (currentRule.aiDefend === "nearOnly") {
// 弱难度:仅附近防守
const lastUserPos = gameState.userChessPositions[gameState.userChessPositions.length - 1];
const nearPos = getUserNearEmptyPositions(lastUserPos);
return nearPos.length > 0 ? nearPos[0] : null;
} else {
return null;
}
}
function canFormLiveTwo(row, col, color) {
const dirs = [[0,1],[1,0],[1,1],[1,-1]];
gameState.chessData[row][col] = color;
let hasLiveTwo = false;
for (let [dx, dy] of dirs) {
let count = 1, leftEmpty = 0, rightEmpty = 0;
for (let i = 1; i < 4; i++) {
const r = row + dx * i, c = col + dy * i;
if (!isInBoard(r, c)) break;
if (gameState.chessData[r][c] === color) count++;
else if (gameState.chessData[r][c] === null) { rightEmpty = 1; break; }
else break;
}
for (let i = 1; i < 4; i++) {
const r = row - dx * i, c = col - dy * i;
if (!isInBoard(r, c)) break;
if (gameState.chessData[r][c] === color) count++;
else if (gameState.chessData[r][c] === null) { leftEmpty = 1; break; }
else break;
}
if (count === 2 && (leftEmpty + rightEmpty) >= 2) { hasLiveTwo = true; break; }
}
gameState.chessData[row][col] = null;
return hasLiveTwo;
}
function canFormLiveThree(row, col, color) {
const dirs = [[0,1],[1,0],[1,1],[1,-1]];
gameState.chessData[row][col] = color;
let hasLiveThree = false;
for (let [dx, dy] of dirs) {
let count = 1, leftEmpty = 0, rightEmpty = 0;
for (let i = 1; i < 5; i++) {
const r = row + dx * i, c = col + dy * i;
if (!isInBoard(r, c)) break;
if (gameState.chessData[r][c] === color) count++;
else if (gameState.chessData[r][c] === null) { rightEmpty = 1; break; }
else break;
}
for (let i = 1; i < 5; i++) {
const r = row - dx * i, c = col - dy * i;
if (!isInBoard(r, c)) break;
if (gameState.chessData[r][c] === color) count++;
else if (gameState.chessData[r][c] === null) { leftEmpty = 1; break; }
else break;
}
if (count === 3 && (leftEmpty + rightEmpty) >= 2) { hasLiveThree = true; break; }
}
gameState.chessData[row][col] = null;
return hasLiveThree;
}
// 落子逻辑
function aiFirstPlace() {
const centerPos = { row: 7, col: 7 };
const cell = document.querySelector(`.chess-cell[data-row="${centerPos.row}"][data-col="${centerPos.col}"]`);
const aiChessDom = document.createElement("div");
aiChessDom.className = `chess-${gameState.aiColor}`;
cell.appendChild(aiChessDom);
gameState.chessData[centerPos.row][centerPos.col] = gameState.aiColor;
// 修复:AI先手时立即更新标记
updateLastAIMove(centerPos);
gameState.currentPlayer = "user";
}
function userPlaceChess(row, col) {
const currentRule = getDifficultyRule(gameState.difficulty);
if (!currentRule.needPlayGame) return;
gameState.dom.capitalTip.style.display = "none";
if (gameState.currentPlayer !== "user" || gameState.isGameOver || gameState.chessData[row][col] !== null) return;
const cell = document.querySelector(`.chess-cell[data-row="${row}"][data-col="${col}"]`);
const userChessDom = document.createElement("div");
userChessDom.className = `chess-${gameState.userColor}`;
cell.appendChild(userChessDom);
gameState.chessData[row][col] = gameState.userColor;
if (isReplacedPosition(row, col)) gameState.replacedUserPositions.delete(`${row}-${col}`);
gameState.userChessPositions.push({ row, col });
updateLastUserMove({ row, col });
if (checkWin(row, col, gameState.userColor)) {
gameState.isGameOver = true;
gameState.dom.winTip.textContent = "恭喜!五子连珠获胜,可进行卡密验证";
gameState.dom.winTip.style.display = "block";
gameState.dom.restartBtnContainer.style.display = "none";
gameState.dom.verifySection.style.display = "block";
return;
}
if (isBoardFull()) {
gameState.isGameOver = true;
gameState.dom.winTip.textContent = "棋盘已满,点击下方按钮重新开局";
gameState.dom.winTip.style.display = "block";
gameState.dom.restartBtnContainer.style.display = "flex";
return;
}
gameState.currentPlayer = "ai";
setTimeout(() => {
let nearEmptyPos;
if (currentRule.aiDefend === "nearOnly") {
nearEmptyPos = getUserNearEmptyPositions({ row, col });
} else {
nearEmptyPos = [];
gameState.userChessPositions.forEach(pos => {
const { row: uRow, col: uCol } = pos;
for (let i = uRow - 2; i <= uRow + 2; i++) {
for (let j = uCol - 2; j <= uCol + 2; j++) {
if (isInBoard(i, j) && gameState.chessData[i][j] === null) {
nearEmptyPos.push({ row: i, col: j });
}
}
}
});
}
if (nearEmptyPos.length === 0) {
gameState.currentPlayer = "user";
return;
}
const dangerInfo = detectUserDangerLevel(nearEmptyPos);
const replacedPos = triggerCapitalGameByLevel(dangerInfo, nearEmptyPos);
if (replacedPos) {
gameState.currentPlayer = "user";
return;
}
const aiPos = aiDecision(dangerInfo, nearEmptyPos);
if (aiPos) {
aiPlaceChess(aiPos.row, aiPos.col);
} else {
// 修复:如果没有找到合适位置,随机选择一个位置
const randomPos = nearEmptyPos[Math.floor(Math.random() * nearEmptyPos.length)];
if (randomPos) {
aiPlaceChess(randomPos.row, randomPos.col);
} else {
gameState.currentPlayer = "user";
}
}
}, 1000);
}
function aiPlaceChess(row, col) {
const cell = document.querySelector(`.chess-cell[data-row="${row}"][data-col="${col}"]`);
if (!cell) return;
const aiChessDom = document.createElement("div");
aiChessDom.className = `chess-${gameState.aiColor}`;
cell.appendChild(aiChessDom);
gameState.chessData[row][col] = gameState.aiColor;
// 修复:确保AI落子后立即更新标记
updateLastAIMove({ row, col });
if (checkWin(row, col, gameState.aiColor)) {
gameState.isGameOver = true;
gameState.dom.winTip.textContent = "AI获胜,点击下方按钮重新开局";
gameState.dom.winTip.style.display = "block";
gameState.dom.restartBtnContainer.style.display = "flex";
return;
}
if (isBoardFull()) {
gameState.isGameOver = true;
gameState.dom.winTip.textContent = "棋盘已满,点击下方按钮重新开局";
gameState.dom.winTip.style.display = "block";
gameState.dom.restartBtnContainer.style.display = "flex";
return;
}
gameState.currentPlayer = "user";
}
// 修复:游戏状态判定 - 确保正确检测五子连线并高亮棋子
function checkWin(row, col, color) {
const dirs = [[0,1],[1,0],[1,1],[1,-1]];
for (let [dx, dy] of dirs) {
let count = 1;
let winPositions = [{row, col}];
// 正向检测
for (let i = 1; i < 5; i++) {
const r = row + dx * i, c = col + dy * i;
if (!isInBoard(r, c) || gameState.chessData[r][c] !== color) break;
count++;
winPositions.push({row: r, col: c});
}
// 反向检测
for (let i = 1; i < 5; i++) {
const r = row - dx * i, c = col - dy * i;
if (!isInBoard(r, c) || gameState.chessData[r][c] !== color) break;
count++;
winPositions.unshift({row: r, col: c});
}
if (count >= 5) {
// 存储获胜棋子的位置
gameState.winHighlightPositions = winPositions.slice(0, 5);
// 高亮显示获胜棋子
highlightWinPieces(gameState.winHighlightPositions, color);
return true;
}
}
return false;
}
// 高亮显示获胜棋子
function highlightWinPieces(positions, color) {
// 清除之前的高亮
const oldHighlights = document.querySelectorAll('.win-highlight');
oldHighlights.forEach(highlight => highlight.classList.remove('win-highlight'));
// 为每个获胜棋子添加高亮样式
positions.forEach(pos => {
const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
if (cell) {
const chess = cell.querySelector(`.chess-${color}`);
if (chess) {
chess.classList.add('win-highlight');
}
}
});
}
function isBoardFull() {
for (let i = 0; i < gameState.size; i++) {
for (let j = 0; j < gameState.size; j++) {
if (gameState.chessData[i][j] === null) return false;
}
}
return true;
}
// 修复:重启游戏 - 确保标记正确重置
function restartGame() {
// 清除高亮
const oldHighlights = document.querySelectorAll('.win-highlight');
oldHighlights.forEach(highlight => highlight.classList.remove('win-highlight'));
// 重置游戏状态
gameState.userColor = Math.random() > 0.5 ? "black" : "white";
gameState.aiColor = gameState.userColor === "black" ? "white" : "black";
gameState.currentPlayer = gameState.userColor === "black" ? "user" : "ai";
gameState.chessData = Array(gameState.size).fill().map(() => Array(gameState.size).fill(null));
gameState.userChessPositions = [];
gameState.replacedUserPositions.clear();
gameState.isGameOver = false;
gameState.lastUserMove = null;
gameState.lastAIMove = null;
gameState.winHighlightPositions = [];
gameState.dom.winTip.style.display = "none";
gameState.dom.restartBtnContainer.style.display = "none";
gameState.dom.capitalTip.style.display = "none";
gameState.dom.verifySection.style.display = "none";
// 重新渲染棋盘
renderChessBoard();
// AI先手时自动落子
if (gameState.currentPlayer === "ai") {
setTimeout(() => aiFirstPlace(), 300);
}
}
// 危险等级检测
function detectUserDangerLevel(nearEmptyPos) {
const dirs = [[0,1],[1,0],[1,1],[1,-1]];
let maxDangerLevel = 1, dangerPos = null, dangerDesc = `1颗棋子(共${getUserValidChessCount()}颗)`;
if (getUserValidChessCount() === 0) return { level: 1, pos: null, desc: "0颗有效棋子" };
nearEmptyPos.forEach(pos => {
const { row, col } = pos;
gameState.chessData[row][col] = gameState.userColor;
for (let [dx, dy] of dirs) {
let count = 1, emptyCount = 0;
for (let i = 1; i < 6; i++) {
const r = row + dx * i, c = col + dy * i;
if (!isInBoard(r, c) || isReplacedPosition(r, c)) break;
if (gameState.chessData[r][c] === gameState.userColor) count++;
else if (gameState.chessData[r][c] === null) { emptyCount++; break; }
else break;
}
for (let i = 1; i < 6; i++) {
const r = row - dx * i, c = col - dy * i;
if (!isInBoard(r, c) || isReplacedPosition(r, c)) break;
if (gameState.chessData[r][c] === gameState.userColor) count++;
else if (gameState.chessData[r][c] === null) { emptyCount++; break; }
else break;
}
let currentLevel = 1, currentDesc = `1颗棋子(共${getUserValidChessCount()}颗)`;
if (count === 5) { currentLevel = 5; currentDesc = `5颗近获胜(共${getUserValidChessCount()}颗)`; }
else if (count === 4 && emptyCount >= 1) { currentLevel = 4; currentDesc = `4颗即将连线(共${getUserValidChessCount()}颗)`; }
else if (count === 3 && emptyCount >= 1) { currentLevel = 3; currentDesc = `${emptyCount >= 2 ? '3颗活三' : '3颗冲三'}(共${getUserValidChessCount()}颗)`; }
else if (count === 2 && emptyCount >= 2) { currentLevel = 2; currentDesc = `2颗活二(共${getUserValidChessCount()}颗)`; }
if (currentLevel > maxDangerLevel) { maxDangerLevel = currentLevel; dangerPos = pos; dangerDesc = currentDesc; }
}
gameState.chessData[row][col] = null;
});
const validCount = getUserValidChessCount();
if (maxDangerLevel === 1 && validCount >= 2) { maxDangerLevel = Math.min(validCount, 5); dangerDesc = `${validCount}颗棋子(无连续威胁)`; }
return { level: maxDangerLevel, pos: dangerPos, desc: dangerDesc };
}
function findMostDangerousUserChess(dangerLevel, nearEmptyPos) {
let mostDangerousPos = null, maxLevelDrop = 0;
gameState.userChessPositions.forEach(uPos => {
const { row, col } = uPos;
gameState.chessData[row][col] = null;
const newDangerInfo = detectUserDangerLevel(nearEmptyPos);
const levelDrop = dangerLevel - newDangerInfo.level;
gameState.chessData[row][col] = gameState.userColor;
if (levelDrop > maxLevelDrop) { maxLevelDrop = levelDrop; mostDangerousPos = uPos; }
});
if (!mostDangerousPos && gameState.userChessPositions.length > 0) {
mostDangerousPos = gameState.userChessPositions[gameState.userChessPositions.length - 1];
}
return mostDangerousPos;
}
// 严格按用户提供的JS编写查码函数
function Call_Verify(data) {
PanGolin.Verify(data);
}
function Call_Query_Trial(data) {
if (PanGolin.Is_Trial()) PanGolin.Trial();
else PanGolin.Query(data);
}
function Call_Pay() {
PanGolin.Pay();
}
window.addEventListener('load', initPage);
</script>
</body>
</html>
<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->