我让DeepSeek用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;
font-family: 'Microsoft YaHei', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
color: #fff;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 20px;
}
h1 {
font-size: 2.8rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.subtitle {
font-size: 1.2rem;
opacity: 0.9;
}
.game-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 30px;
max-width: 1200px;
width: 100%;
}
.board-container {
background-color: #deb887;
padding: 20px;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
position: relative;
}
#game-board {
display: grid;
grid-template-columns: repeat(15, 30px);
grid-template-rows: repeat(15, 30px);
background-color: #e0a95c;
position: relative;
}
.cell {
width: 30px;
height: 30px;
position: relative;
cursor: pointer;
}
/* 绘制棋盘线 */
.cell::before, .cell::after {
content: '';
position: absolute;
background-color: #000;
}
.cell::before {
width: 100%;
height: 1px;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.cell::after {
width: 1px;
height: 100%;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.piece {
position: absolute;
width: 26px;
height: 26px;
border-radius: 50%;
z-index: 2;
top: 2px;
left: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
transition: transform 0.2s ease-in-out;
}
.black {
background: radial-gradient(circle at 30% 30%, #3a3a3a, #000);
}
.white {
background: radial-gradient(circle at 30% 30%, #fff, #ddd);
}
.piece.placed {
animation: placePiece 0.3s ease-in-out;
}
@keyframes placePiece {
0% { transform: scale(0); }
70% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.winning-piece {
animation: winningAnimation 1s infinite alternate;
}
@keyframes winningAnimation {
0% { box-shadow: 0 0 5px #ffcc00, 0 0 10px #ffcc00; }
100% { box-shadow: 0 0 15px #ffcc00, 0 0 20px #ffcc00; }
}
.controls-panel {
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 20px;
border-radius: 10px;
width: 300px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.status {
text-align: center;
font-size: 1.4rem;
margin-bottom: 20px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 8px;
padding: 10px;
}
.win-message {
font-size: 1.8rem;
font-weight: bold;
color: #ffcc00;
text-shadow: 0 0 10px rgba(255, 204, 0, 0.8);
}
.difficulty-info {
margin-bottom: 20px;
text-align: center;
padding: 10px;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.difficulty-info h3 {
margin-bottom: 5px;
color: #fdbb2d;
}
.game-buttons {
display: flex;
flex-direction: column;
gap: 10px;
}
.game-buttons button {
padding: 12px;
}
#restart-btn {
background-color: #b21f1f;
}
#restart-btn:hover {
background-color: #c22f2f;
}
.thinking {
display: none;
text-align: center;
margin-top: 10px;
}
.thinking.active {
display: block;
}
.thinking-dots {
display: inline-block;
}
.thinking-dots span {
animation: thinking 1.5s infinite;
opacity: 0;
}
.thinking-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.thinking-dots span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes thinking {
0% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 0; }
}
.instructions {
margin-top: 20px;
background-color: rgba(0, 0, 0, 0.2);
padding: 15px;
border-radius: 8px;
}
.instructions h3 {
margin-bottom: 10px;
text-align: center;
}
.instructions p {
margin-bottom: 8px;
font-size: 0.9rem;
}
.ai-features {
margin-top: 15px;
background-color: rgba(0, 0, 0, 0.3);
padding: 10px;
border-radius: 8px;
}
.ai-features h4 {
margin-bottom: 8px;
text-align: center;
color: #fdbb2d;
}
.victory-overlay {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
justify-content: center;
align-items: center;
flex-direction: column;
z-index: 10;
border-radius: 10px;
}
.victory-overlay.active {
display: flex;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.victory-message {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
}
.victory-buttons {
display: flex;
gap: 15px;
}
@media (max-width: 768px) {
.game-container {
flex-direction: column;
align-items: center;
}
.controls-panel {
width: 100%;
max-width: 400px;
}
#game-board {
grid-template-columns: repeat(15, 20px);
grid-template-rows: repeat(15, 20px);
}
.cell {
width: 20px;
height: 20px;
}
.piece {
width: 16px;
height: 16px;
}
.victory-message {
font-size: 1.8rem;
}
}
</style>
</head>
<body>
<header>
<h1>五子棋</h1>
<p class="subtitle">挑战人工智能对手的经典策略游戏</p>
</header>
<div class="game-container">
<div class="board-container">
<div id="game-board"></div>
<div class="victory-overlay" id="victory-overlay">
<div class="victory-message" id="victory-message"></div>
<div class="victory-buttons">
<button id="play-again-btn">再玩一局</button>
<button id="close-btn">关闭</button>
</div>
</div>
</div>
<div class="controls-panel">
<div class="status" id="status">您的回合 (黑子)</div>
<div class="thinking" id="thinking">
AI思考中<span class="thinking-dots"><span>.</span><span>.</span><span>.</span></span>
</div>
<div class="difficulty-info">
<h3>当前难度: 专家级</h3>
<p>AI已启用高级策略和多步计算</p>
</div>
<div class="game-buttons">
<button id="restart-btn">重新开始</button>
<button id="hint-btn">显示提示</button>
</div>
<div class="instructions">
<h3>游戏规则</h3>
<p>• 您执<strong>黑子</strong>先行</p>
<p>• 连成五个或以上棋子即获胜</p>
<p>• 横、竖、斜线连子均有效</p>
<p>• AI对手执<strong>白子</strong></p>
<div class="ai-features">
<h4>AI高级功能</h4>
<p>• 增强模式识别与评估</p>
<p>• 深度威胁检测与应对</p>
<p>• 四步前瞻分析</p>
<p>• 最优战略位置选择</p>
<p>• 进攻与防守平衡</p>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const board = document.getElementById('game-board');
const status = document.getElementById('status');
const thinking = document.getElementById('thinking');
const victoryOverlay = document.getElementById('victory-overlay');
const victoryMessage = document.getElementById('victory-message');
const playAgainBtn = document.getElementById('play-again-btn');
const closeBtn = document.getElementById('close-btn');
const restartBtn = document.getElementById('restart-btn');
const hintBtn = document.getElementById('hint-btn');
let gameBoard = [];
let currentPlayer = 'black'; // 玩家是黑子,AI是白子
let gameActive = true;
let boardSize = 15;
let moveHistory = [];
let winningPieces = [];
// 模式评分用于评估
const patternScores = {
five: 1000000,
openFour: 100000,
closedFour: 10000,
openThree: 5000,
closedThree: 1000,
openTwo: 500,
closedTwo: 100,
openOne: 10,
closedOne: 1
};
// 初始化棋盘
function initializeBoard() {
board.innerHTML = '';
gameBoard = Array(boardSize).fill().map(() => Array(boardSize).fill(null));
moveHistory = [];
winningPieces = [];
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.dataset.row = i;
cell.dataset.col = j;
cell.addEventListener('click', () => handleCellClick(i, j));
board.appendChild(cell);
}
}
currentPlayer = 'black';
gameActive = true;
status.textContent = '您的回合 (黑子)';
thinking.classList.remove('active');
victoryOverlay.classList.remove('active');
// 移除任何获胜棋子的动画
const pieces = document.querySelectorAll('.piece');
pieces.forEach(piece => {
piece.classList.remove('winning-piece');
});
}
// 处理玩家落子
function handleCellClick(row, col) {
if (!gameActive || currentPlayer !== 'black' || gameBoard[row][col] !== null) {
return;
}
placePiece(row, col, 'black');
moveHistory.push({row, col, player: 'black'});
const winResult = checkWin(row, col, 'black');
if (winResult.win) {
showVictory('player', winResult.pieces);
return;
}
if (isBoardFull()) {
showVictory('draw');
return;
}
currentPlayer = 'white';
status.textContent = 'AI思考中...';
thinking.classList.add('active');
// AI在短暂延迟后落子
setTimeout(makeAIMove, 600);
}
// 在棋盘上放置棋子
function placePiece(row, col, color) {
gameBoard[row][col] = color;
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
const piece = document.createElement('div');
piece.classList.add('piece', color);
cell.appendChild(piece);
// 添加动画
setTimeout(() => {
piece.classList.add('placed');
}, 10);
}
// 从棋盘上移除棋子
function removePiece(row, col) {
gameBoard[row][col] = null;
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
const piece = cell.querySelector('.piece');
if (piece) {
cell.removeChild(piece);
}
}
// 检查是否获胜并返回获胜的棋子
function checkWin(row, col, color) {
const directions = [
[0, 1], // 水平
[1, 0], // 垂直
[1, 1], // 对角线
[1, -1] // 反对角线
];
for (const [dx, dy] of directions) {
let count = 1;
const pieces = [{row, col}];
// 检查正方向
for (let i = 1; i < 5; i++) {
const newRow = row + i * dx;
const newCol = col + i * dy;
if (newRow < 0 || newRow >= boardSize || newCol < 0 || newCol >= boardSize ||
gameBoard[newRow][newCol] !== color) {
break;
}
count++;
pieces.push({row: newRow, col: newCol});
}
// 检查负方向
for (let i = 1; i < 5; i++) {
const newRow = row - i * dx;
const newCol = col - i * dy;
if (newRow < 0 || newRow >= boardSize || newCol < 0 || newCol >= boardSize ||
gameBoard[newRow][newCol] !== color) {
break;
}
count++;
pieces.push({row: newRow, col: newCol});
}
if (count >= 5) {
return {win: true, pieces};
}
}
return {win: false, pieces: []};
}
// 高亮显示获胜的棋子
function highlightWinningPieces(pieces) {
winningPieces = pieces;
pieces.forEach(({row, col}) => {
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
const piece = cell.querySelector('.piece');
if (piece) {
piece.classList.add('winning-piece');
}
});
}
// 显示胜利信息
function showVictory(winner, pieces = []) {
gameActive = false;
thinking.classList.remove('active');
if (winner === 'player') {
status.innerHTML = '<span class="win-message">您赢了!</span>';
victoryMessage.textContent = '恭喜!您战胜了AI!';
highlightWinningPieces(pieces);
} else if (winner === 'ai') {
status.innerHTML = '<span class="win-message">AI赢了!</span>';
victoryMessage.textContent = 'AI战胜了您。再试一次!';
highlightWinningPieces(pieces);
} else {
status.innerHTML = '<span class="win-message">平局!</span>';
victoryMessage.textContent = '游戏平局。表现不错!';
}
victoryOverlay.classList.add('active');
}
// 检查棋盘是否已满
function isBoardFull() {
return gameBoard.every(row => row.every(cell => cell !== null));
}
// AI落子逻辑 - 增强版
function makeAIMove() {
if (!gameActive || currentPlayer !== 'white') {
thinking.classList.remove('active');
return;
}
// 使用增强的AI算法找到最佳落子
const move = getEnhancedAIMove();
if (move) {
const [row, col] = move;
placePiece(row, col, 'white');
moveHistory.push({row, col, player: 'white'});
const winResult = checkWin(row, col, 'white');
if (winResult.win) {
showVictory('ai', winResult.pieces);
thinking.classList.remove('active');
return;
}
if (isBoardFull()) {
showVictory('draw');
thinking.classList.remove('active');
return;
}
currentPlayer = 'black';
status.textContent = '您的回合 (黑子)';
}
thinking.classList.remove('active');
}
// 增强的AI算法
function getEnhancedAIMove() {
// 首先检查AI是否能获胜
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] === null) {
gameBoard[i][j] = 'white';
if (checkWin(i, j, 'white').win) {
gameBoard[i][j] = null;
return [i, j];
}
gameBoard[i][j] = null;
}
}
}
// 然后检查玩家是否即将获胜并阻止
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] === null) {
gameBoard[i][j] = 'black';
if (checkWin(i, j, 'black').win) {
gameBoard[i][j] = null;
return [i, j];
}
gameBoard[i][j] = null;
}
}
}
// 使用增强的评估函数找到最佳落子位置
return findBestMove(3); // 3步前瞻
}
// 使用minimax算法和alpha-beta剪枝找到最佳落子
function findBestMove(depth) {
let bestScore = -Infinity;
let bestMove = null;
// 获取所有可能的落子位置(只考虑已有棋子附近的区域)
const possibleMoves = getPossibleMoves();
// 按评估分数排序,提高alpha-beta剪枝效率
const scoredMoves = [];
for (const move of possibleMoves) {
const [i, j] = move;
gameBoard[i][j] = 'white';
const score = evaluatePosition(i, j, 'white');
gameBoard[i][j] = null;
scoredMoves.push({move, score});
}
// 按分数降序排序
scoredMoves.sort((a, b) => b.score - a.score);
for (const {move} of scoredMoves) {
const [i, j] = move;
// 落子
gameBoard[i][j] = 'white';
// 计算这个落子的分数
const score = minimax(depth - 1, -Infinity, Infinity, false);
// 撤销落子
gameBoard[i][j] = null;
if (score > bestScore) {
bestScore = score;
bestMove = [i, j];
}
}
return bestMove || getStrategicMove();
}
// 带alpha-beta剪枝的minimax算法
function minimax(depth, alpha, beta, isMaximizing) {
// 检查终止状态
if (checkWinForPlayer('white')) return patternScores.five;
if (checkWinForPlayer('black')) return -patternScores.five;
if (depth === 0) return evaluateBoard();
const possibleMoves = getPossibleMoves();
if (isMaximizing) {
let maxScore = -Infinity;
for (const move of possibleMoves) {
const [i, j] = move;
gameBoard[i][j] = 'white';
const score = minimax(depth - 1, alpha, beta, false);
gameBoard[i][j] = null;
maxScore = Math.max(maxScore, score);
alpha = Math.max(alpha, score);
if (beta <= alpha) break;
}
return maxScore;
} else {
let minScore = Infinity;
for (const move of possibleMoves) {
const [i, j] = move;
gameBoard[i][j] = 'black';
const score = minimax(depth - 1, alpha, beta, true);
gameBoard[i][j] = null;
minScore = Math.min(minScore, score);
beta = Math.min(beta, score);
if (beta <= alpha) break;
}
return minScore;
}
}
// 为AI评估棋盘
function evaluateBoard() {
let score = 0;
// 评估所有行、列和对角线
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] !== null) continue;
// 为白子(AI)评估
gameBoard[i][j] = 'white';
score += evaluatePosition(i, j, 'white');
gameBoard[i][j] = null;
// 为黑子(玩家)评估
gameBoard[i][j] = 'black';
score -= evaluatePosition(i, j, 'black') * 0.9; // 稍微偏向防守
gameBoard[i][j] = null;
}
}
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) {
score += evaluateDirection(row, col, dx, dy, player);
}
return score;
}
// 评估特定方向对玩家的价值
function evaluateDirection(row, col, dx, dy, player) {
let score = 0;
let count = 0;
let openEnds = 0;
let blockEnds = 0;
// 检查正方向
for (let i = 1; i <= 4; i++) {
const newRow = row + i * dx;
const newCol = col + i * dy;
if (newRow < 0 || newRow >= boardSize || newCol < 0 || newCol >= boardSize) {
blockEnds++;
break;
}
if (gameBoard[newRow][newCol] === player) {
count++;
} else if (gameBoard[newRow][newCol] === null) {
openEnds++;
break;
} else {
blockEnds++;
break;
}
}
// 检查负方向
for (let i = 1; i <= 4; i++) {
const newRow = row - i * dx;
const newCol = col - i * dy;
if (newRow < 0 || newRow >= boardSize || newCol < 0 || newCol >= boardSize) {
blockEnds++;
break;
}
if (gameBoard[newRow][newCol] === player) {
count++;
} else if (gameBoard[newRow][newCol] === null) {
openEnds++;
break;
} else {
blockEnds++;
break;
}
}
// 根据数量和开放端计分
if (count >= 4) {
score += patternScores.five;
} else if (count === 3) {
if (openEnds === 2) score += patternScores.openFour;
else if (openEnds === 1) score += patternScores.closedFour;
} else if (count === 2) {
if (openEnds === 2) score += patternScores.openThree;
else if (openEnds === 1) score += patternScores.closedThree;
} else if (count === 1) {
if (openEnds === 2) score += patternScores.openTwo;
else if (openEnds === 1) score += patternScores.closedTwo;
}
// 添加位置权重 - 中心位置更有价值
const centerDist = Math.abs(row - 7.5) + Math.abs(col - 7.5);
score += (15 - centerDist) * 2;
return score;
}
// 检查玩家是否获胜
function checkWinForPlayer(player) {
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] === player) {
const winResult = checkWin(i, j, player);
if (winResult.win) return true;
}
}
}
return false;
}
// 获取可能的落子位置(为提高效率,只考虑已有棋子附近的区域)
function getPossibleMoves() {
const moves = [];
const checked = Array(boardSize).fill().map(() => Array(boardSize).fill(false));
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] !== null) {
// 检查所有相邻单元格
for (let dx = -2; dx <= 2; dx++) {
for (let dy = -2; dy <= 2; dy++) {
const ni = i + dx;
const nj = j + dy;
if (ni >= 0 && ni < boardSize && nj >= 0 && nj < boardSize &&
gameBoard[ni][nj] === null && !checked[ni][nj]) {
moves.push([ni, nj]);
checked[ni][nj] = true;
}
}
}
}
}
}
// 如果没有找到落子位置(游戏开始时),返回中心
if (moves.length === 0) {
return [[Math.floor(boardSize/2), Math.floor(boardSize/2)]];
}
return moves;
}
// 获取战略性落子
function getStrategicMove() {
const strategicMoves = [];
for (let i = 0; i < boardSize; i++) {
for (let j = 0; j < boardSize; j++) {
if (gameBoard[i][j] === null) {
// 偏好中心位置和靠近已有棋子的位置
let score = 0;
// 为靠近中心添加分数
const centerDist = Math.abs(i - 7.5) + Math.abs(j - 7.5);
score += (15 - centerDist) * 2;
// 为靠近其他棋子添加分数
for (let dx = -2; dx <= 2; dx++) {
for (let dy = -2; dy <= 2; dy++) {
if (dx === 0 && dy === 0) continue;
const ni = i + dx;
const nj = j + dy;
if (ni >= 0 && ni < boardSize && nj >= 0 && nj < boardSize) {
if (gameBoard[ni][nj] === 'white') score += 5;
if (gameBoard[ni][nj] === 'black') score += 3;
}
}
}
strategicMoves.push({move: [i, j], score});
}
}
}
if (strategicMoves.length === 0) return null;
// 选择分数最高的落子
strategicMoves.sort((a, b) => b.score - a.score);
return strategicMoves[0].move;
}
// 向玩家显示提示
function showHint() {
if (!gameActive || currentPlayer !== 'black') {
return;
}
// 使用AI的评估为玩家找到最佳落子
let bestMove = null;
let bestScore = -Infinity;
const possibleMoves = getPossibleMoves();
for (const move of possibleMoves) {
const [i, j] = move;
// 落子
gameBoard[i][j] = 'black';
// 计算这个落子的分数
const score = evaluateBoard();
// 撤销落子
gameBoard[i][j] = null;
if (score > bestScore) {
bestScore = score;
bestMove = [i, j];
}
}
if (bestMove) {
highlightHint(bestMove[0], bestMove[1]);
}
}
// 在棋盘上高亮显示提示
function highlightHint(row, col) {
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
const hint = document.createElement('div');
hint.style.position = 'absolute';
hint.style.width = '20px';
hint.style.height = '20px';
hint.style.border = '2px dashed #ffcc00';
hint.style.borderRadius = '50%';
hint.style.zIndex = '1';
hint.style.top = '5px';
hint.style.left = '5px';
hint.style.animation = 'pulse 1s infinite';
cell.appendChild(hint);
// 3秒后移除提示
setTimeout(() => {
if (cell.contains(hint)) {
cell.removeChild(hint);
}
}, 3000);
}
// 事件监听器
restartBtn.addEventListener('click', initializeBoard);
hintBtn.addEventListener('click', () => {
if (gameActive && currentPlayer === 'black') {
showHint();
}
});
playAgainBtn.addEventListener('click', initializeBoard);
closeBtn.addEventListener('click', () => {
victoryOverlay.classList.remove('active');
});
// 初始化游戏
initializeBoard();
});
</script>
</body>
</html>
这是一个基于HTML/JavaScript实现的五子棋游戏,具有以下特点:
-
采用15x15标准棋盘,玩家执黑先行,AI执白
-
AI具备智能决策系统,包括:
- 胜利条件检测和防御机制
- 3步前瞻的minimax算法
- 模式识别与评分系统
- 进攻与防守平衡策略
-
游戏功能:
- 胜负判定与高亮显示
- 提示系统
- 重新开始功能
- 响应式设计适配不同设备
-
视觉效果:
- 棋子放置动画
- 获胜棋子高亮效果
- 渐变背景和UI设计
该实现完整包含了游戏逻辑、AI算法和交互界面,可直接在浏览器中运行。
368

被折叠的 条评论
为什么被折叠?



