1、新建一个txt
文件
2、打开后将代码复制进去保存
<!DOCTYPE html>
<html>
<head>
<title>智能五子棋</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
background: #f0f0f0;
font-family: Arial, sans-serif;
}
canvas {
border: 2px solid #333;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
background: #F0D9B5;
margin: 20px;
}
.status {
font-size: 24px;
color: #333;
margin: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #45a049;
}
</style>
</head>
<body>
<div class="status" id="status">轮到玩家落子</div>
<canvas id="board" width="600" height="600"></canvas>
<button onclick="initGame()">重新开始</button>
<script>
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const SIZE = 40;
const ROWS = 15;
const AI_DEPTH = 3; // 搜索深度
let board = [];
let gameOver = false;
// 初始化游戏
function initGame() {
board = Array(ROWS).fill().map(() => Array(ROWS).fill(0));
gameOver = false;
document.getElementById('status').textContent = '轮到玩家落子';
drawBoard();
}
// 绘制棋盘
function drawBoard() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制网格
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
for (let i = 0; i < ROWS; i++) {
ctx.beginPath();
ctx.moveTo(SIZE/2, SIZE/2 + i*SIZE);
ctx.lineTo(canvas.width - SIZE/2, SIZE/2 + i*SIZE);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(SIZE/2 + i*SIZE, SIZE/2);
ctx.lineTo(SIZE/2 + i*SIZE, canvas.height - SIZE/2);
ctx.stroke();
}
// 绘制星位
const stars = [3, 7, 11];
stars.forEach(x => stars.forEach(y => {
ctx.beginPath();
ctx.arc(SIZE/2 + x*SIZE, SIZE/2 + y*SIZE, 3, 0, Math.PI*2);
ctx.fillStyle = '#666';
ctx.fill();
}));
// 绘制棋子
for (let i = 0; i < ROWS; i++) {
for (let j = 0; j < ROWS; j++) {
if (board[i][j] === 1) drawPiece(i, j, '#000');
else if (board[i][j] === 2) drawPiece(i, j, '#FFF');
}
}
}
// 绘制棋子
function drawPiece(x, y, color) {
ctx.beginPath();
ctx.arc(SIZE/2 + x*SIZE, SIZE/2 + y*SIZE, SIZE*0.4, 0, Math.PI*2);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = color === '#000' ? '#fff' : '#000';
ctx.lineWidth = 1;
ctx.stroke();
}
// AI核心逻辑
const PATTERNS = {
FIVE: 100000,
LIVE_FOUR: 50000,
DIE_FOUR: 400,
LIVE_THREE: 400,
DIE_THREE: 50,
LIVE_TWO: 50,
DIE_TWO: 5
};
function aiMove() {
document.getElementById('status').textContent = 'AI思考中...';
setTimeout(() => {
const move = getBestMove();
board[move.x][move.y] = 2;
if (checkWin(move.x, move.y, 2)) {
gameOver = true;
document.getElementById('status').textContent = 'AI获胜!';
} else {
document.getElementById('status').textContent = '轮到玩家落子';
}
drawBoard();
}, 100);
}
function getBestMove() {
let bestScore = -Infinity;
let bestMoves = [];
const candidates = getCandidatePositions();
candidates.forEach(({x, y}) => {
board[x][y] = 2;
let score = minimax(AI_DEPTH - 1, -Infinity, Infinity, false);
board[x][y] = 0;
if (score > bestScore) {
bestScore = score;
bestMoves = [{x, y}];
} else if (score === bestScore) {
bestMoves.push({x, y});
}
});
return bestMoves[Math.floor(Math.random() * bestMoves.length)];
}
function minimax(depth, alpha, beta, isMaximizing) {
if (depth === 0 || checkGameOver()) return evaluateBoard();
if (isMaximizing) {
let maxScore = -Infinity;
for (let {x, y} of getCandidatePositions()) {
board[x][y] = 2;
let score = minimax(depth - 1, alpha, beta, false);
board[x][y] = 0;
maxScore = Math.max(maxScore, score);
alpha = Math.max(alpha, score);
if (beta <= alpha) break;
}
return maxScore;
} else {
let minScore = Infinity;
for (let {x, y} of getCandidatePositions()) {
board[x][y] = 1;
let score = minimax(depth - 1, alpha, beta, true);
board[x][y] = 0;
minScore = Math.min(minScore, score);
beta = Math.min(beta, score);
if (beta <= alpha) break;
}
return minScore;
}
}
// 辅助函数
function getCandidatePositions() {
const candidates = [];
for (let i = 0; i < ROWS; i++) {
for (let j = 0; j < ROWS; j++) {
if (board[i][j] === 0 && hasNeighbor(i, j, 2)) {
candidates.push({x:i, y:j});
}
}
}
return candidates.length > 0 ? candidates : [{x:7, y:7}];
}
function hasNeighbor(x, y, range) {
for (let i = -range; i <= range; i++) {
for (let j = -range; j <= range; j++) {
const nx = x + i, ny = y + j;
if (nx >=0 && nx < ROWS && ny >=0 && ny < ROWS && board[nx][ny] !== 0) {
return true;
}
}
}
return false;
}
function evaluateBoard() {
let score = 0;
[[1,0], [0,1], [1,1], [1,-1]].forEach(([dx, dy]) => {
for (let i = 0; i < ROWS; i++) {
for (let j = 0; j < ROWS; j++) {
if (board[i][j] !== 0) {
const pattern = checkPattern(i, j, dx, dy, board[i][j]);
score += (board[i][j] === 2 ? pattern : -pattern);
}
}
}
});
return score;
}
function checkPattern(x, y, dx, dy, player) {
let count = 1, block = 0;
// 正方向
let i = 1;
while (validPos(x + dx*i, y + dy*i) && board[x + dx*i][y + dy*i] === player) {
count++;
i++;
}
if (!validPos(x + dx*i, y + dy*i) || board[x + dx*i][y + dy*i] !== 0) block++;
// 反方向
i = 1;
while (validPos(x - dx*i, y - dy*i) && board[x - dx*i][y - dy*i] === player) {
count++;
i++;
}
if (!validPos(x - dx*i, y - dy*i) || board[x - dx*i][y - dy*i] !== 0) block++;
if (count >= 5) return PATTERNS.FIVE;
if (count === 4) return block === 0 ? PATTERNS.LIVE_FOUR : PATTERNS.DIE_FOUR;
if (count === 3) return block === 0 ? PATTERNS.LIVE_THREE : PATTERNS.DIE_THREE;
if (count === 2) return block === 0 ? PATTERNS.LIVE_TWO : PATTERNS.DIE_TWO;
return 0;
}
function validPos(x, y) {
return x >=0 && x < ROWS && y >=0 && y < ROWS;
}
function checkGameOver() {
for (let i = 0; i < ROWS; i++) {
for (let j = 0; j < ROWS; j++) {
if (board[i][j] !== 0 && checkWin(i, j, board[i][j])) return true;
}
}
return false;
}
// 胜负判断
function checkWin(x, y, player) {
const directions = [[1,0], [0,1], [1,1], [1,-1]];
for (let [dx, dy] of directions) {
let count = 1;
for (let i = 1; validPos(x + dx*i, y + dy*i) && board[x + dx*i][y + dy*i] === player; i++) count++;
for (let i = 1; validPos(x - dx*i, y - dy*i) && board[x - dx*i][y - dy*i] === player; i++) count++;
if (count >= 5) return true;
}
return false;
}
// 玩家交互
canvas.addEventListener('click', (e) => {
if (gameOver) return;
const rect = canvas.getBoundingClientRect();
const x = Math.floor((e.clientX - rect.left - SIZE/2) / SIZE);
const y = Math.floor((e.clientY - rect.top - SIZE/2) / SIZE);
if (validPos(x, y) && board[x][y] === 0) {
board[x][y] = 1;
if (checkWin(x, y, 1)) {
gameOver = true;
document.getElementById('status').textContent = '玩家获胜!';
} else {
aiMove();
}
drawBoard();
}
});
// 启动游戏
initGame();
</script>
</body>
</html>
3、修改文件后缀名为,将txt
修改为html
4、打开方式选择浏览器打开,或者打开浏览器直接拖动到里面即可。如果后缀名修改html
后,图标显示的是浏览器的图标,直接双击打开即可。
5、效果如下: