古老的五子棋

午休忽然想起我奶奶喜欢下的一种古老的五子棋游戏,于是花了半小时开发出来了~

源代码:

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>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #faf1c0;
        }
        canvas {
            background-color: #DAA520; /* 黄棕色 */
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <canvas id="chessboard" width="600" height="600"></canvas>

    <script>
        const canvas = document.getElementById('chessboard');
        const ctx = canvas.getContext('2d');

        // 棋子信息存储
        let pieces = [];

        // 棋盘信息存储
        let board = { size: canvas.width, margin: canvas.width * 0.05, step: (canvas.width - canvas.width * 0.1) / 4 };
        board.drawableSize = board.size - 2 * board.margin;

        // 当前拖拽的棋子
        let currentPiece = null;

        function drawPiece(x, y, color, isDragging = false) {
            const radius = board.size / 28;  // 棋子的半径,可以根据需要调整
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.fillStyle = color;
            ctx.fill();
            if (isDragging) {
                ctx.strokeStyle = 'red';
                ctx.stroke();
            }
            ctx.closePath();
            return { x, y, radius, color };
        }

        function drawChessboard() {
            ctx.clearRect(0, 0, board.size, board.size);
            for (let i = 0; i <= 4; i++) {
                ctx.moveTo(board.margin, board.margin + i * board.step);
                ctx.lineTo(board.margin + board.drawableSize, board.margin + i * board.step);
                ctx.moveTo(board.margin + i * board.step, board.margin);
                ctx.lineTo(board.margin + i * board.step, board.margin + board.drawableSize);
            }
            let size = board.size
            let step = board.step
            let margin =  board.margin

            // 画对角线
            ctx.moveTo(margin, margin);
            ctx.lineTo(size-margin, size-margin);

            ctx.moveTo(margin, size-margin);
            ctx.lineTo(size-margin, margin);

            ctx.moveTo(margin, 2*step+margin);
            ctx.lineTo(2 * step+margin, size-margin);

            ctx.moveTo(2*step+margin, margin);
            ctx.lineTo(size-margin, 2 * step+margin);

            ctx.moveTo(margin, 2 * step+margin);
            ctx.lineTo(2 * step+margin, margin);

            ctx.moveTo(2*step+margin, size-margin);
            ctx.lineTo(size-margin, 2*step+margin);
            ctx.stroke();
        
            ctx.stroke();
        }

        // 初始化棋子
        function initPieces() {
            pieces = [];
            // 画白色棋子
            for (let i = 0; i <= 4; i++) {
                pieces.push(drawPiece(i * board.step + board.margin, board.margin, 'white'));
            }

            // 画黑色棋子
            for (let i = 0; i <= 4; i++) {
                pieces.push(drawPiece(i * board.step + board.margin, board.size - board.margin, 'black'));
            }
        }

        // 检测坐标是否在棋子上
        function isPieceUnderCoordinate(x, y, piece) {
            const distance = Math.sqrt((x - piece.x) ** 2 + (y - piece.y) ** 2);
            return distance < piece.radius;
        }

        // 开始拖拽
        canvas.onmousedown = function(event) {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            for (const piece of pieces) {
                if (isPieceUnderCoordinate(x, y, piece)) {
                    currentPiece = piece;
                    break;
                }
            }
        };

        // 拖拽移动
        canvas.onmousemove = function(event) {
            if (currentPiece) {
                const rect = canvas.getBoundingClientRect();
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;
                drawChessboard();
                for (const piece of pieces) {
                    if (piece === currentPiece) {
                        drawPiece(x, y, piece.color, true);
                    } else {
                        drawPiece(piece.x, piece.y, piece.color);
                    }
                }
            }
        };

        // 放下棋子
        canvas.onmouseup = function(event) {
            if (currentPiece) {
                const rect = canvas.getBoundingClientRect();
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;

                // 计算最接近的交点
                const closestX = Math.round((x - board.margin) / board.step) * board.step + board.margin;
                const closestY = Math.round((y - board.margin) / board.step) * board.step + board.margin;

                // 更新棋子位置
                currentPiece.x = closestX;
                currentPiece.y = closestY;

                drawChessboard();
                for (const piece of pieces) {
                    drawPiece(piece.x, piece.y, piece.color);
                }
            }
            currentPiece = null;
        };
        // 双击切换棋子颜色
        canvas.ondblclick = function(event) {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            for (const piece of pieces) {
                if (isPieceUnderCoordinate(x, y, piece)) {
                    // 切换颜色
                    piece.color = piece.color === 'white' ? 'black' : 'white';

                    // 重新绘制棋盘和棋子
                    drawChessboard();
                    for (const piece of pieces) {
                        drawPiece(piece.x, piece.y, piece.color);
                    }
                    break;
                }
            }
        };

        drawChessboard();
        initPieces();
    </script>
</body>
</html>

效果图:

相关推荐
FungLeo18 分钟前
成为全栈·Vue 管理后台篇·分类树与标签管理:层级数据如何落到管理界面
前端·javascript·vue.js·分类树·naive ui·标签管理·前端数据结构
总要学点什么1 小时前
第108篇:三维特效-图片轨迹线效果——把贴图滚成一串箭头,想用它的本色反而整条消失
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
Lank_M4 小时前
白底都占八成,PNG 为何只在图表页赢过 JPG
前端
张一凡934 小时前
给 Coding Agent 加一道"架构闸门":Jin 是如何做到"先审架构、再写代码、不漂移"的
前端·后端·agent
Linye4 小时前
AI 写的 HTML 原型全是空壳?聊聊真实 DOM 交互避坑
前端·人工智能
ZANE4 小时前
纯前端实现的 PDF 与图片互相转换工具技术实现
前端
Swot4 小时前
SvelteKit Remote Functions 使用指南
前端·后端
Cooper254 小时前
三源热榜去重加 AI 摘要:URL 唯一键踩出的三个坑
前端·python
Yk酱228404 小时前
A2UI探索随笔-技术选型
前端
前端繁华如梦5 小时前
# 从 73000 行压缩代码到 TypeScript 模块化:我把一个 Three.js FPS 游戏 1:1 复刻了一遍
前端