博主闲得无聊,自己摸鱼做了一个游戏 
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;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
}
header {
text-align: center;
margin-bottom: 15px;
width: 100%;
max-width: 500px;
}
.stats {
background: rgba(255,255,255,0.9);
padding: 10px 20px;
border-radius: 20px;
display: inline-block;
margin-bottom: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats span {
margin: 0 10px;
font-weight: bold;
color: #2c3e50;
}
h1 {
color: white;
font-size: 2em;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}
.players-info {
display: flex;
gap: 20px;
margin-bottom: 15px;
background: rgba(255,255,255,0.9);
padding: 10px 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.player {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9em;
font-weight: bold;
}
.player-indicator {
width: 25px;
height: 25px;
border-radius: 50%;
transition: all 0.3s;
}
.player1 { background: linear-gradient(135deg, #667eea, #764ba2); }
.player2 { background: linear-gradient(135deg, #f093fb, #f5576c); }
.player3 { background: linear-gradient(135deg, #4facfe, #00f2fe); }
.current-turn {
transform: scale(1.3);
box-shadow: 0 0 15px rgba(255,215,0,0.8);
}
main {
background: rgba(255,255,255,0.95);
padding: 15px;
border-radius: 15px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
max-width: 500px;
width: 100%;
}
#board {
display: grid;
grid-template-columns: repeat(10, 1fr);
gap: 2px;
background: #34495e;
padding: 8px;
border-radius: 10px;
aspect-ratio: 1;
}
.cell {
background: #ecf0f1;
cursor: pointer;
position: relative;
border-radius: 3px;
aspect-ratio: 1;
}
.cell:hover:not(.occupied) {
background: #bdc3c7;
transform: scale(1.05);
}
.piece {
width: 80%;
height: 80%;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation: dropIn 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
@keyframes dropIn {
from { transform: translate(-50%, -50%) scale(0); opacity: 0; }
to { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
.winning-piece {
animation: pulse 1s infinite;
}
@keyframes pulse {
0%, 100% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.2); }
}
.controls {
margin-top: 15px;
text-align: center;
}
button {
padding: 10px 20px;
font-size: 14px;
font-weight: bold;
border: none;
border-radius: 8px;
cursor: pointer;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
transition: all 0.3s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.status {
margin-top: 15px;
text-align: center;
font-size: 1.1em;
font-weight: bold;
color: #2c3e50;
min-height: 25px;
}
.winner {
color: #27ae60;
animation: celebrate 0.5s ease;
}
@keyframes celebrate {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
@media (max-width: 500px) {
#board {
max-width: 90vw;
}
}
</style>
</head>
<body>
<header>
<div class="stats">
<span>胜: <span id="wins">0</span></span>
<span>负: <span id="losses">0</span></span>
<span>平: <span id="draws">0</span></span>
</div>
<h1>三人四子棋</h1>
</header>
<div class="players-info">
<div class="player">
<div class="player-indicator player1" id="indicator1"></div>
<span>你</span>
</div>
<div class="player">
<div class="player-indicator player2" id="indicator2"></div>
<span>凤九歌</span>
</div>
<div class="player">
<div class="player-indicator player3" id="indicator3"></div>
<span>凉安</span>
</div>
</div>
<main>
<div id="board"></div>
<div class="controls">
<button onclick="resetGame()">重新开始</button>
</div>
<div class="status" id="status"></div>
</main>
<script>
const BOARD_SIZE = 10;
const WIN_COUNT = 4;
let board, currentPlayer, gameOver;
const players = {
1: { name: '你', class: 'player1' },
2: { name: '凤九歌', class: 'player2' },
3: { name: '凉安', class: 'player3' }
};
function initGame() {
board = Array(BOARD_SIZE).fill(null).map(() => Array(BOARD_SIZE).fill(null));
currentPlayer = 1;
gameOver = false;
createBoard();
updateStatus('');
updateTurnIndicator();
}
function createBoard() {
const boardEl = document.getElementById('board');
boardEl.innerHTML = '';
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.row = row;
cell.dataset.col = col;
cell.onclick = () => handleCellClick(row, col);
boardEl.appendChild(cell);
}
}
}
function handleCellClick(row, col) {
if (gameOver || currentPlayer !== 1 || board[row][col]) return;
makeMove(row, col, 1);
if (!gameOver) setTimeout(aiTurn, 500);
}
function makeMove(row, col, player) {
board[row][col] = player;
const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
cell.classList.add('occupied');
cell.innerHTML = `<div class="piece ${players[player].class}"></div>`;
if (checkWin(row, col, player)) {
gameOver = true;
highlightWinning(row, col, player);
updateStatus(`${players[player].name} 获胜!`, true);
updateStats(player);
} else if (isBoardFull()) {
gameOver = true;
updateStatus('平局!', true);
updateStats(0);
} else {
currentPlayer = currentPlayer % 3 + 1;
updateTurnIndicator();
}
}
function checkWin(row, col, player) {
const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]];
for (const dir of dirs) {
let count = 1;
for (const [dr, dc] of dir) {
let r = row + dr, c = col + dc;
while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) {
count++;
r += dr;
c += dc;
}
}
if (count >= WIN_COUNT) return true;
}
return false;
}
function highlightWinning(row, col, player) {
const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]];
for (const dir of dirs) {
let pieces = [{row, col}];
let count = 1;
for (const [dr, dc] of dir) {
let r = row + dr, c = col + dc;
while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) {
pieces.push({row: r, col: c});
count++;
r += dr;
c += dc;
}
}
if (count >= WIN_COUNT) {
pieces.forEach(pos => {
const piece = document.querySelector(`[data-row="${pos.row}"][data-col="${pos.col}"] .piece`);
if (piece) piece.classList.add('winning-piece');
});
return;
}
}
}
function isBoardFull() {
return board.every(row => row.every(cell => cell !== null));
}
function aiTurn() {
if (gameOver) return;
const move = currentPlayer === 2 ?
findBestMove(2, true) : findBestMove(3, false);
if (move) {
makeMove(move.row, move.col, currentPlayer);
if (!gameOver && currentPlayer !== 1) setTimeout(aiTurn, 500);
}
}
function findBestMove(player, aggressive) {
let move = findWinningMove(player);
if (move) return move;
if (aggressive) {
for (let p of [1, 3]) {
move = findWinningMove(p);
if (move) return move;
}
} else {
for (let p of [1, 2]) {
move = findWinningMove(p);
if (move) return move;
}
}
let bestScore = -1, bestMove = null;
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
if (!board[row][col]) {
const score = evaluatePosition(row, col, player);
if (score > bestScore) {
bestScore = score;
bestMove = {row, col};
}
}
}
}
return bestMove;
}
function findWinningMove(player) {
for (let row = 0; row < BOARD_SIZE; row++) {
for (let col = 0; col < BOARD_SIZE; col++) {
if (!board[row][col]) {
board[row][col] = player;
if (checkWin(row, col, player)) {
board[row][col] = null;
return {row, col};
}
board[row][col] = null;
}
}
}
return null;
}
function evaluatePosition(row, col, player) {
let score = 0;
const dirs = [[0,1], [1,0], [1,1], [1,-1]];
for (const [dr, dc] of dirs) {
let count = 0, open = 0;
for (const [rDir, cDir] of [[dr, dc], [-dr, -dc]]) {
let r = row + rDir, c = col + cDir;
while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) {
if (board[r][c] === player) count++;
else if (!board[r][c]) { open++; break; }
else break;
r += rDir;
c += cDir;
}
}
if (count >= 3) score += 100;
else if (count === 2 && open >= 1) score += 10;
else if (count === 1 && open >= 2) score += 1;
}
const center = BOARD_SIZE / 2;
score += Math.max(0, 5 - (Math.abs(row - center) + Math.abs(col - center)));
return score;
}
function updateTurnIndicator() {
document.querySelectorAll('.player-indicator').forEach(el =>
el.classList.remove('current-turn'));
document.getElementById(`indicator${currentPlayer}`).classList.add('current-turn');
}
function updateStatus(msg, isWinner = false) {
const status = document.getElementById('status');
status.textContent = msg;
status.className = isWinner ? 'status winner' : 'status';
}
function updateStats(winner) {
const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}');
if (winner === 1) stats.wins++;
else if (winner === 0) stats.draws++;
else stats.losses++;
localStorage.setItem('gameStats', JSON.stringify(stats));
document.getElementById('wins').textContent = stats.wins;
document.getElementById('losses').textContent = stats.losses;
document.getElementById('draws').textContent = stats.draws;
}
function loadStats() {
const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}');
document.getElementById('wins').textContent = stats.wins;
document.getElementById('losses').textContent = stats.losses;
document.getElementById('draws').textContent = stats.draws;
}
function resetGame() {
initGame();
}
loadStats();
initGame();
</script>
</body>
</html>