古老的五子棋

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

源代码:

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>

效果图:

相关推荐
IT_陈寒29 分钟前
Vite的热更新突然失效,原来是因为这个配置
前端·人工智能·后端
ZC跨境爬虫1 小时前
3D 地球卫星轨道可视化平台开发 Day8(分步渲染200颗卫星+ 前端分页控制)
前端·python·3d·重构·html
竹林8181 小时前
RainbowKit快速集成多链钱包连接,我如何从“连不上”到“丝滑切换”
前端·javascript
笨笨狗吞噬者1 小时前
Opus 4.7 使用体验
前端·ai编程
No8g攻城狮1 小时前
【前端】Vue 中 const、var、let 的区别
前端·javascript·vue.js
文心快码BaiduComate1 小时前
Comate搭载Kimi K2.6,长程13h!
前端·后端·程序员
豹哥学前端2 小时前
新手小白学前端day4: Position定位
前端
fishmemory7sec2 小时前
Vue大屏自适应容器组件:v-scale-screen
前端·javascript·vue.js
饺子不吃醋2 小时前
Promise原理、手写与 async、await
前端·javascript
PILIPALAPENG2 小时前
第3周 Day 2:Function Calling —— 让 Agent 听懂人话,自己干活
前端·人工智能·python