专栏文章
电脑没网时可以做的事(html)
休闲·娱乐参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mmc3ed6r
- 此快照首次捕获于
- 2026/03/04 21:48 3 天前
- 此快照最后确认于
- 2026/03/04 21:48 3 天前
下面是用HTML编写的五子棋离线游戏:
- 先在电脑桌面新建文本文档;
- 将下面代码复制进去,保存;
- 将文件改为HTML格式(.html),回车;
- 选择用浏览器打开它,就可以了。
可在评论区改进代码,觉得好的话可以关注作者
代码如下(HTML)
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", sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: #f5f5f5;
padding: 20px;
}
.game-container {
display: flex;
align-items: flex-start;
gap: 30px;
margin-top: 20px;
}
.game-info {
width: 200px;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.game-info h2 {
color: #333;
margin-bottom: 15px;
text-align: center;
}
.difficulty {
margin: 15px 0;
}
.difficulty h3 {
font-size: 16px;
color: #666;
margin-bottom: 10px;
text-align: center;
}
.difficulty-buttons {
display: flex;
gap: 5px;
justify-content: center;
}
.diff-btn {
padding: 5px 10px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f8f8f8;
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
}
.diff-btn.active {
background-color: #4CAF50;
color: white;
border-color: #4CAF50;
}
.diff-btn:hover:not(.active) {
background-color: #eee;
}
.status {
font-size: 18px;
margin: 20px 0;
color: #555;
text-align: center;
}
#reset-btn {
width: 100%;
padding: 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
margin-top: 15px;
}
#reset-btn:hover {
background-color: #45a049;
}
.chessboard {
display: grid;
grid-template-columns: repeat(15, 30px);
grid-template-rows: repeat(15, 30px);
gap: 1px;
background-color: #e6b87d;
padding: 5px;
border-radius: 5px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.chess-cell {
width: 30px;
height: 30px;
background-color: #e6b87d;
position: relative;
cursor: pointer;
}
/* 棋盘网格线 */
.chess-cell::before {
content: '';
position: absolute;
width: 1px;
height: 100%;
background-color: #8b5a2b;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.chess-cell::after {
content: '';
position: absolute;
height: 1px;
width: 100%;
background-color: #8b5a2b;
top: 50%;
left: 0;
transform: translateY(-50%);
}
/* 去掉边缘的网格线 */
.chess-cell:first-child::before,
.chess-cell:nth-child(15n+1)::before {
display: none;
}
.chess-cell:nth-child(-n+15)::after {
display: none;
}
/* 棋子样式 */
.chess {
position: absolute;
width: 26px;
height: 26px;
border-radius: 50%;
top: 2px;
left: 2px;
z-index: 10;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
}
.black {
background-color: #000;
}
.white {
background-color: #fff;
border: 1px solid #ddd;
}
/* 胜利提示 */
.win-message {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0,0,0,0.8);
color: white;
padding: 30px 50px;
border-radius: 10px;
font-size: 24px;
z-index: 100;
display: none;
}
</style>
</head>
<body>
<h1>离线五子棋 - 人机对战</h1>
<div class="game-container">
<div class="chessboard" id="chessboard"></div>
<div class="game-info">
<h2>游戏信息</h2>
<div class="difficulty">
<h3>选择难度</h3>
<div class="difficulty-buttons">
<button class="diff-btn active" data-level="easy">简单</button>
<button class="diff-btn" data-level="medium">中等</button>
<button class="diff-btn" data-level="hard">困难</button>
</div>
</div>
<div class="status" id="game-status">你的回合 (黑子)</div>
<button id="reset-btn">重新开始</button>
</div>
</div>
<div class="win-message" id="win-message"></div>
<script>
// 游戏状态常量
const EMPTY = 0;
const BLACK = 1; // 玩家
const WHITE = 2; // AI
// 难度等级常量
const DIFFICULTY = {
EASY: 'easy',
MEDIUM: 'medium',
HARD: 'hard'
};
// 游戏变量
let chessboard = Array(15).fill().map(() => Array(15).fill(EMPTY));
let gameOver = false;
let currentPlayer = BLACK;
let currentDifficulty = DIFFICULTY.EASY; // 默认简单难度
// 获取DOM元素
const chessboardDom = document.getElementById('chessboard');
const gameStatus = document.getElementById('game-status');
const resetBtn = document.getElementById('reset-btn');
const winMessage = document.getElementById('win-message');
const difficultyButtons = document.querySelectorAll('.diff-btn');
// 初始化棋盘
function initChessboard() {
chessboardDom.innerHTML = '';
chessboard = Array(15).fill().map(() => Array(15).fill(EMPTY));
gameOver = false;
currentPlayer = BLACK;
gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
winMessage.style.display = 'none';
// 创建15x15的棋盘格子
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
const cell = document.createElement('div');
cell.className = 'chess-cell';
cell.dataset.row = row;
cell.dataset.col = col;
// 点击落子事件
cell.addEventListener('click', () => handleCellClick(row, col));
chessboardDom.appendChild(cell);
}
}
}
// 获取难度显示文本
function getDifficultyText() {
switch(currentDifficulty) {
case DIFFICULTY.EASY: return '简单难度';
case DIFFICULTY.MEDIUM: return '中等难度';
case DIFFICULTY.HARD: return '困难难度';
default: return '简单难度';
}
}
// 处理难度选择
function handleDifficultyChange(level) {
// 如果游戏中切换难度,提示重新开始
if (!gameOver && !isBoardEmpty()) {
if (confirm('切换难度将重新开始游戏,确定吗?')) {
currentDifficulty = level;
updateDifficultyButtons();
initChessboard();
}
} else {
currentDifficulty = level;
updateDifficultyButtons();
gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
}
}
// 检查棋盘是否为空
function isBoardEmpty() {
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
if (chessboard[row][col] !== EMPTY) {
return false;
}
}
}
return true;
}
// 更新难度按钮样式
function updateDifficultyButtons() {
difficultyButtons.forEach(btn => {
if (btn.dataset.level === currentDifficulty) {
btn.classList.add('active');
} else {
btn.classList.remove('active');
}
});
}
// 处理格子点击事件
function handleCellClick(row, col) {
// 游戏结束或位置已有棋子则返回
if (gameOver || chessboard[row][col] !== EMPTY) return;
// 玩家落子(黑子)
placeChess(row, col, BLACK);
// 检查玩家是否获胜
if (checkWin(row, col, BLACK)) {
gameOver = true;
gameStatus.textContent = `恭喜你获胜! - ${getDifficultyText()}`;
winMessage.textContent = '恭喜你获胜!';
winMessage.style.display = 'block';
return;
}
// 检查是否平局
if (checkDraw()) {
gameOver = true;
gameStatus.textContent = `平局! - ${getDifficultyText()}`;
winMessage.textContent = '平局!';
winMessage.style.display = 'block';
return;
}
// AI回合
gameStatus.textContent = `AI思考中... - ${getDifficultyText()}`;
setTimeout(() => aiMove(), 500); // 延迟500ms,模拟思考
}
// 落子函数
function placeChess(row, col, player) {
chessboard[row][col] = player;
// 创建棋子DOM元素
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
const chess = document.createElement('div');
chess.className = `chess ${player === BLACK ? 'black' : 'white'}`;
cell.appendChild(chess);
}
// 评估位置得分(核心AI逻辑)
function evaluatePosition(row, col, player) {
let score = 0;
const opponent = player === BLACK ? WHITE : BLACK;
// 检查四个方向
const directions = [[0, 1], [1, 0], [1, 1], [1, -1]];
for (const [dx, dy] of directions) {
let count = 0; // 连续棋子数
let empty = 0; // 两端空位数量
let block = 0; // 被阻挡的端数
// 正向检查
let r = row + dx;
let c = col + dy;
while (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === player) {
count++;
r += dx;
c += dy;
}
// 检查正向末端
if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === EMPTY) {
empty++;
} else if (r >= 0 && r < 15 && c >= 0 && c < 15) {
block++;
}
// 反向检查
r = row - dx;
c = col - dy;
while (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === player) {
count++;
r -= dx;
c -= dy;
}
// 检查反向末端
if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === EMPTY) {
empty++;
} else if (r >= 0 && r < 15 && c >= 0 && c < 15) {
block++;
}
// 根据连续棋子数和两端情况打分
if (count >= 4) score += 100000; // 五连(必胜)
else if (count === 3 && empty === 2) score += 10000; // 活四
else if (count === 3 && empty === 1) score += 1000; // 冲四
else if (count === 2 && empty === 2) score += 100; // 活三
else if (count === 2 && empty === 1) score += 10; // 冲三
else if (count === 1 && empty === 2) score += 5; // 活二
}
return score;
}
// AI落子逻辑(根据难度调整)
function aiMove() {
if (gameOver) return;
let bestScore = -1;
let bestPos = null;
let allPossibleMoves = [];
// 遍历所有空位,计算得分
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
if (chessboard[row][col] !== EMPTY) continue;
// 1. 计算AI落在此处的得分(进攻)
const aiScore = evaluatePosition(row, col, WHITE);
// 2. 计算玩家落在此处的得分(防守)
const playerScore = evaluatePosition(row, col, BLACK);
// 综合得分:防守优先级高于进攻
const totalScore = Math.max(aiScore, playerScore * 1.1);
allPossibleMoves.push({
row,
col,
score: totalScore
});
// 更新最佳位置
if (totalScore > bestScore) {
bestScore = totalScore;
bestPos = { row, col };
}
}
}
// 根据难度调整AI落子策略
switch(currentDifficulty) {
case DIFFICULTY.EASY:
// 简单难度:30%概率选择非最佳位置
if (Math.random() < 0.3 && allPossibleMoves.length > 1) {
// 过滤掉最高分的位置
const filteredMoves = allPossibleMoves.filter(move => move.score < bestScore);
if (filteredMoves.length > 0) {
const randomIndex = Math.floor(Math.random() * filteredMoves.length);
bestPos = filteredMoves[randomIndex];
}
}
break;
case DIFFICULTY.MEDIUM:
// 中等难度:15%概率选择非最佳位置
if (Math.random() < 0.15 && allPossibleMoves.length > 1) {
const filteredMoves = allPossibleMoves.filter(move => move.score < bestScore);
if (filteredMoves.length > 0) {
const randomIndex = Math.floor(Math.random() * filteredMoves.length);
bestPos = filteredMoves[randomIndex];
}
}
break;
case DIFFICULTY.HARD:
// 困难难度:总是选择最佳位置
break;
}
// 如果没有找到有价值的位置,选择已有棋子周围的空位(兜底)
if (!bestPos) {
const emptyPositions = [];
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
if (chessboard[row][col] === EMPTY) {
// 检查周围是否有棋子(3x3范围)
let hasNearChess = false;
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
const r = row + dr;
const c = col + dc;
if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] !== EMPTY) {
hasNearChess = true;
break;
}
}
if (hasNearChess) break;
}
if (hasNearChess || emptyPositions.length === 0) {
emptyPositions.push({ row, col });
}
}
}
}
bestPos = emptyPositions[Math.floor(Math.random() * emptyPositions.length)];
}
// AI落子
placeChess(bestPos.row, bestPos.col, WHITE);
// 检查AI是否获胜
if (checkWin(bestPos.row, bestPos.col, WHITE)) {
gameOver = true;
gameStatus.textContent = `AI获胜! - ${getDifficultyText()}`;
winMessage.textContent = 'AI获胜!';
winMessage.style.display = 'block';
return;
}
// 检查是否平局
if (checkDraw()) {
gameOver = true;
gameStatus.textContent = `平局! - ${getDifficultyText()}`;
winMessage.textContent = '平局!';
winMessage.style.display = 'block';
return;
}
// 回到玩家回合
currentPlayer = BLACK;
gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
}
// 检查是否获胜
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 < 5; i++) {
const newRow = row + dx * i;
const newCol = col + dy * i;
if (newRow >= 0 && newRow < 15 && newCol >= 0 && newCol < 15 && chessboard[newRow][newCol] === player) {
count++;
} else {
break;
}
}
// 反向检查
for (let i = 1; i < 5; i++) {
const newRow = row - dx * i;
const newCol = col - dy * i;
if (newRow >= 0 && newRow < 15 && newCol >= 0 && newCol < 15 && chessboard[newRow][newCol] === player) {
count++;
} else {
break;
}
}
// 五子连珠
if (count >= 5) {
return true;
}
}
return false;
}
// 检查是否平局
function checkDraw() {
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
if (chessboard[row][col] === EMPTY) {
return false; // 还有空位置,不是平局
}
}
}
return true; // 棋盘已满,平局
}
// 绑定事件监听
resetBtn.addEventListener('click', initChessboard);
// 难度选择按钮事件
difficultyButtons.forEach(btn => {
btn.addEventListener('click', () => {
handleDifficultyChange(btn.dataset.level);
});
});
// 初始化游戏
initChessboard();
</script>
</body>
</html>
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...