• Bio

    五子棋游戏 body { font-family: Arial, sans-serif; background-color: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; }
        #game-container {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        #game-board {
            background-color: #f3d2b5;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
            cursor: pointer;
        }
        
        #info {
            font-size: 20px;
            margin-top: 20px;
            text-align: center;
            height: 30px;
        }
        
        #restart-btn {
            margin-top: 20px;
            padding: 8px 16px;
            font-size: 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        
        #restart-btn:hover {
            background-color: #45a049;
        }
    </style>
    
    重新开始
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const canvas = document.getElementById('game-board');
            const ctx = canvas.getContext('2d');
            const infoDiv = document.getElementById('info');
            const restartBtn = document.getElementById('restart-btn');
            
            const BOARD_SIZE = 15;
            const CELL_SIZE = canvas.width / BOARD_SIZE;
            const PIECE_RADIUS = CELL_SIZE * 0.4;
            
            let board = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(0));
            let currentPlayer = 1; // 1: 黑棋(先手), 2: 白棋
            let gameOver = false;
            let playerColor = Math.random() < 0.5 ? 1 : 2;
            let aiColor = playerColor === 1 ? 2 : 1;
            
            // 棋型评分常量
            const SCORE = {
                FIVE: 100000,
                LIVE_FOUR: 10000,
                DIE_FOUR: 1000,
                LIVE_THREE: 1000,
                DIE_THREE: 100,
                LIVE_TWO: 100,
                DIE_TWO: 10,
                SINGLE: 1
            };
            
            function initGame() {
                board = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(0));
                currentPlayer = 1;
                playerColor = Math.random() < 0.5 ? 1 : 2;
                aiColor = playerColor === 1 ? 2 : 1;
                gameOver = false;
                drawBoard();
                updateInfo();
                
                if (currentPlayer === 1 && aiColor === 1) {
                    setTimeout(aiMove, 500);
                }
            }
            
            function drawBoard() {
                ctx.fillStyle = '#f3d2b5';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                ctx.strokeStyle = '#000';
                ctx.lineWidth = 1;
                
                for (let i = 0; i < BOARD_SIZE; i++) {
                    ctx.beginPath();
                    ctx.moveTo(CELL_SIZE / 2, i * CELL_SIZE + CELL_SIZE / 2);
                    ctx.lineTo(canvas.width - CELL_SIZE / 2, i * CELL_SIZE + CELL_SIZE / 2);
                    ctx.stroke();
                    
                    ctx.beginPath();
                    ctx.moveTo(i * CELL_SIZE + CELL_SIZE / 2, CELL_SIZE / 2);
                    ctx.lineTo(i * CELL_SIZE + CELL_SIZE / 2, canvas.height - CELL_SIZE / 2);
                    ctx.stroke();
                }
                
                for (let i = 0; i < BOARD_SIZE; i++) {
                    for (let j = 0; j < BOARD_SIZE; j++) {
                        if (board[i][j] === 1) {
                            drawPiece(j, i, 'black');
                        } else if (board[i][j] === 2) {
                            drawPiece(j, i, 'white');
                        }
                    }
                }
            }
            
            function drawPiece(x, y, color) {
                const centerX = x * CELL_SIZE + CELL_SIZE / 2;
                const centerY = y * CELL_SIZE + CELL_SIZE / 2;
                
                ctx.beginPath();
                ctx.arc(centerX, centerY, PIECE_RADIUS, 0, Math.PI * 2);
                ctx.fillStyle = color;
                ctx.fill();
                
                if (color === 'white') {
                    ctx.strokeStyle = '#000';
                    ctx.lineWidth = 1;
                    ctx.stroke();
                }
            }
            
            function updateInfo() {
                if (gameOver) return;
                
                if (currentPlayer === playerColor) {
                    infoDiv.textContent = `你的回合 (${playerColor === 1 ? '黑棋' : '白棋'})`;
                } else {
                    infoDiv.textContent = `AI思考中 (${aiColor === 1 ? '黑棋' : '白棋'})...`;
                }
            }
            
            function placePiece(x, y) {
                if (gameOver || currentPlayer !== playerColor) return;
                
                const gridX = Math.round((x - CELL_SIZE / 2) / CELL_SIZE);
                const gridY = Math.round((y - CELL_SIZE / 2) / CELL_SIZE);
                
                if (gridX >= 0 && gridX < BOARD_SIZE && gridY >= 0 && gridY < BOARD_SIZE && board[gridY][gridX] === 0) {
                    board[gridY][gridX] = currentPlayer;
                    drawBoard();
                    
                    if (checkWin(gridX, gridY, currentPlayer)) {
                        gameOver = true;
                        infoDiv.textContent = `恭喜你赢了! (${playerColor === 1 ? '黑棋' : '白棋'})`;
                        return;
                    }
                    
                    currentPlayer = currentPlayer === 1 ? 2 : 1;
                    updateInfo();
                    
                    setTimeout(aiMove, 500);
                }
            }
            
            function aiMove() {
                if (gameOver || currentPlayer !== aiColor) return;
                
                // 1. 检查AI是否能直接获胜
                const winMove = findWinningMove(aiColor);
                if (winMove) {
                    makeAIMove(winMove.x, winMove.y);
                    return;
                }
                
                // 2. 检查是否需要防守玩家即将获胜
                const blockWinMove = findWinningMove(playerColor);
                if (blockWinMove) {
                    makeAIMove(blockWinMove.x, blockWinMove.y);
                    return;
                }
                
                // 3. 增强的活三检测和防守
                const blockThreeMove = findBlockThreeMove();
                if (blockThreeMove) {
                    makeAIMove(blockThreeMove.x, blockThreeMove.y);
                    return;
                }
                
                // 4. 尝试创建活四或冲四
                const createFourMove = findBestScoreMove(aiColor, ['LIVE_FOUR', 'DIE_FOUR']);
                if (createFourMove) {
                    makeAIMove(createFourMove.x, createFourMove.y);
                    return;
                }
                
                // 5. 阻止玩家形成活二
                const blockTwoMove = findBestScoreMove(playerColor, ['LIVE_TWO']);
                if (blockTwoMove) {
                    makeAIMove(blockTwoMove.x, blockTwoMove.y);
                    return;
                }
                
                // 6. 尝试创建活三
                const createThreeMove = findBestScoreMove(aiColor, ['LIVE_THREE']);
                if (createThreeMove) {
                    makeAIMove(createThreeMove.x, createThreeMove.y);
                    return;
                }
                
                // 7. 最佳落子点
                const bestMove = findBestPosition();
                if (bestMove) {
                    makeAIMove(bestMove.x, bestMove.y);
                    return;
                }
            }
            
            // 增强的活三检测函数
            function findBlockThreeMove() {
                const directions = [
                    [1, 0], [0, 1], [1, 1], [1, -1]
                ];
                
                let bestDefense = null;
                let maxThreat = 0;
                
                for (let y = 0; y < BOARD_SIZE; y++) {
                    for (let x = 0; x < BOARD_SIZE; x++) {
                        if (board[y][x] === 0) {
                            let threatLevel = 0;
                            let defensePoints = [];
                            
                            for (const [dx, dy] of directions) {
                                // 检查正方向
                                let count = 0;
                                let emptyCount = 0;
                                let blockCount = 0;
                                
                                // 正方向
                                let i = 1;
                                while (true) {
                                    const nx = x + i * dx;
                                    const ny = y + i * dy;
                                    
                                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                                        blockCount++;
                                        break;
                                    }
                                    
                                    if (board[ny][nx] === playerColor) {
                                        count++;
                                        i++;
                                    } else if (board[ny][nx] === 0) {
                                        emptyCount++;
                                        break;
                                    } else {
                                        blockCount++;
                                        break;
                                    }
                                }
                                
                                // 负方向
                                i = 1;
                                while (true) {
                                    const nx = x - i * dx;
                                    const ny = y - i * dy;
                                    
                                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                                        blockCount++;
                                        break;
                                    }
                                    
                                    if (board[ny][nx] === playerColor) {
                                        count++;
                                        i++;
                                    } else if (board[ny][nx] === 0) {
                                        emptyCount++;
                                        break;
                                    } else {
                                        blockCount++;
                                        break;
                                    }
                                }
                                
                                // 判断是否是活三威胁
                                if (count === 3 && emptyCount >= 1) {
                                    // 连活三
                                    if (emptyCount === 2) {
                                        threatLevel += SCORE.LIVE_THREE * 2;
                                        defensePoints.push({x, y, direction: [dx, dy]});
                                    } 
                                    // 跳活三
                                    else {
                                        // 检查是否是跳活三
                                        const jumpThree = checkJumpThree(x, y, dx, dy, playerColor);
                                        if (jumpThree) {
                                            threatLevel += SCORE.LIVE_THREE;
                                            defensePoints.push(jumpThree);
                                        }
                                    }
                                }
                            }
                            
                            // 选择威胁最大的防守点
                            if (threatLevel > maxThreat) {
                                maxThreat = threatLevel;
                                if (defensePoints.length > 0) {
                                    // 优先选择能同时防守多个方向的点
                                    bestDefense = defensePoints[0];
                                }
                            }
                        }
                    }
                }
                
                return bestDefense;
            }
            
            // 检查跳活三
            function checkJumpThree(x, y, dx, dy, color) {
                // 检查正方向跳活三
                let pattern1 = [
                    [0, 0],
                    [dx, dy],
                    [2*dx, 2*dy],
                    [3*dx, 3*dy]
                ];
                
                let pattern2 = [
                    [0, 0],
                    [dx, dy],
                    [3*dx, 3*dy],
                    [4*dx, 4*dy]
                ];
                
                // 检查第一种跳活三模式:_OO_O
                let match1 = true;
                for (const [px, py] of pattern1) {
                    const nx = x + px;
                    const ny = y + py;
                    
                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                        match1 = false;
                        break;
                    }
                    
                    if ((px === 0 && py === 0) || (px === 3*dx && py === 3*dy)) {
                        if (board[ny][nx] !== 0) {
                            match1 = false;
                            break;
                        }
                    } else {
                        if (board[ny][nx] !== color) {
                            match1 = false;
                            break;
                        }
                    }
                }
                
                if (match1) {
                    return {x: x + 3*dx, y: y + 3*dy};
                }
                
                // 检查第二种跳活三模式:_O_OO
                let match2 = true;
                for (const [px, py] of pattern2) {
                    const nx = x + px;
                    const ny = y + py;
                    
                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                        match2 = false;
                        break;
                    }
                    
                    if ((px === 0 && py === 0) || (px === dx && py === dy)) {
                        if (board[ny][nx] !== 0) {
                            match2 = false;
                            break;
                        }
                    } else {
                        if (board[ny][nx] !== color) {
                            match2 = false;
                            break;
                        }
                    }
                }
                
                if (match2) {
                    return {x: x + dx, y: y + dy};
                }
                
                return null;
            }
            
            function makeAIMove(x, y) {
                board[y][x] = aiColor;
                drawBoard();
                
                if (checkWin(x, y, aiColor)) {
                    gameOver = true;
                    infoDiv.textContent = `AI赢了! (${aiColor === 1 ? '黑棋' : '白棋'})`;
                    return;
                }
                
                if (isDraw()) {
                    gameOver = true;
                    infoDiv.textContent = "平局!";
                    return;
                }
                
                currentPlayer = playerColor;
                updateInfo();
            }
            
            function isDraw() {
                for (let y = 0; y < BOARD_SIZE; y++) {
                    for (let x = 0; x < BOARD_SIZE; x++) {
                        if (board[y][x] === 0) return false;
                    }
                }
                return true;
            }
            
            function findWinningMove(color) {
                for (let y = 0; y < BOARD_SIZE; y++) {
                    for (let x = 0; x < BOARD_SIZE; x++) {
                        if (board[y][x] === 0) {
                            board[y][x] = color;
                            if (checkWin(x, y, color)) {
                                board[y][x] = 0;
                                return {x, y};
                            }
                            board[y][x] = 0;
                        }
                    }
                }
                return null;
            }
            
            function findBestScoreMove(color, patterns) {
                let bestScore = -1;
                let bestMove = null;
                
                for (let y = 0; y < BOARD_SIZE; y++) {
                    for (let x = 0; x < BOARD_SIZE; x++) {
                        if (board[y][x] === 0) {
                            const score = evaluatePosition(x, y, color, patterns);
                            if (score > bestScore) {
                                bestScore = score;
                                bestMove = {x, y};
                            }
                        }
                    }
                }
                
                return bestMove;
            }
            
            function evaluatePosition(x, y, color, patterns) {
                const directions = [
                    [1, 0], [0, 1], [1, 1], [1, -1]
                ];
                
                let totalScore = 0;
                
                for (const [dx, dy] of directions) {
                    const pattern = evaluateDirection(x, y, dx, dy, color);
                    if (patterns.includes(pattern.type)) {
                        totalScore += SCORE[pattern.type];
                    }
                }
                
                // 增加位置分(中心区域更高)
                const centerX = BOARD_SIZE / 2;
                const centerY = BOARD_SIZE / 2;
                const distanceToCenter = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
                totalScore += (BOARD_SIZE - distanceToCenter) * 2;
                
                // 增加邻近棋子分
                totalScore += getNearbyScore(x, y, color);
                
                return totalScore;
            }
            
            function evaluateDirection(x, y, dx, dy, color) {
                let count = 1;
                let emptyEnds = 0;
                let blockEnds = 0;
                
                // 正方向
                let i = 1;
                while (true) {
                    const nx = x + i * dx;
                    const ny = y + i * dy;
                    
                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                        blockEnds++;
                        break;
                    }
                    
                    if (board[ny][nx] === color) {
                        count++;
                        i++;
                    } else if (board[ny][nx] === 0) {
                        emptyEnds++;
                        break;
                    } else {
                        blockEnds++;
                        break;
                    }
                }
                
                // 负方向
                i = 1;
                while (true) {
                    const nx = x - i * dx;
                    const ny = y - i * dy;
                    
                    if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) {
                        blockEnds++;
                        break;
                    }
                    
                    if (board[ny][nx] === color) {
                        count++;
                        i++;
                    } else if (board[ny][nx] === 0) {
                        emptyEnds++;
                        break;
                    } else {
                        blockEnds++;
                        break;
                    }
                }
                
                // 判断棋型
                if (count >= 5) return {type: 'FIVE'};
                if (count === 4) {
                    if (emptyEnds === 2) return {type: 'LIVE_FOUR'};
                    if (emptyEnds === 1) return {type: 'DIE_FOUR'};
                }
                if (count === 3) {
                    if (emptyEnds === 2) return {type: 'LIVE_THREE'};
                    if (emptyEnds === 1) return {type: 'DIE_THREE'};
                }
                if (count === 2) {
                    if (emptyEnds === 2) return {type: 'LIVE_TWO'};
                    if (emptyEnds === 1) return {type: 'DIE_TWO'};
                }
                
                return {type: 'SINGLE'};
            }
            
            function getNearbyScore(x, y, color) {
                let score = 0;
                const directions = [
                    [-1, -1], [-1, 0], [-1, 1],
                    [0, -1],           [0, 1],
                    [1, -1],  [1, 0],  [1, 1]
                ];
                
                for (const [dx, dy] of directions) {
                    const nx = x + dx;
                    const ny = y + dy;
                    
                    if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) {
                        if (board[ny][nx] === color) {
                            score += 5;
                        } else if (board[ny][nx] !== 0) {
                            score += 3;
                        }
                    }
                }
                
                return score;
            }
            
            function findBestPosition() {
                let bestScore = -1;
                let bestMove = null;
                
                // 优先寻找靠近已有棋子的位置
                for (let y = 0; y < BOARD_SIZE; y++) {
                    for (let x = 0; x < BOARD_SIZE; x++) {
                        if (board[y][x] === 0) {
                            // 评估位置价值
                            let score = 0;
                            
                            // 1. 中心区域价值更高
                            const centerX = BOARD_SIZE / 2;
                            const centerY = BOARD_SIZE / 2;
                            const distanceToCenter = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
                            score += (BOARD_SIZE - distanceToCenter) * 2;
                            
                            // 2. 靠近AI棋子的位置价值更高
                            score += getNearbyScore(x, y, aiColor) * 2;
                            
                            // 3. 靠近玩家棋子的位置也有一定价值(防守)
                            score += getNearbyScore(x, y, playerColor);
                            
                            if (score > bestScore) {
                                bestScore = score;
                                bestMove = {x, y};
                            }
                        }
                    }
                }
                
                return bestMove;
            }
            
            function checkWin(x, y, color) {
                const directions = [
                    [1, 0], [0, 1], [1, 1], [1, -1]
                ];
                
                for (const [dx, dy] of directions) {
                    let count = 1;
                    
                    // 正方向
                    let i = 1;
                    while (x + i * dx >= 0 && x + i * dx < BOARD_SIZE && 
                           y + i * dy >= 0 && y + i * dy < BOARD_SIZE && 
                           board[y + i * dy][x + i * dx] === color) {
                        count++;
                        i++;
                    }
                    
                    // 负方向
                    i = 1;
                    while (x - i * dx >= 0 && x - i * dx < BOARD_SIZE && 
                           y - i * dy >= 0 && y - i * dy < BOARD_SIZE && 
                           board[y - i * dy][x - i * dx] === color) {
                        count++;
                        i++;
                    }
                    
                    if (count >= 5) {
                        return true;
                    }
                }
                
                return false;
            }
            
            canvas.addEventListener('click', (e) => {
                const rect = canvas.getBoundingClientRect();
                const x = e.clientX - rect.left;
                const y = e.clientY - rect.top;
                placePiece(x, y);
            });
            
            restartBtn.addEventListener('click', initGame);
            
            initGame();
        });
    </script>
    
  • Recent Activities

    This person is lazy and didn't join any contests or homework.