javascript五子棋小游戏,基于div+canvas的五子棋小游戏

javascript五子棋小游戏

基于div+canvas的五子棋小游戏

示例地址:链接

开始

开始游戏:



主要逻辑:

1.绘制棋盘

javascript 复制代码
/**
         * 
         * 绘制棋盘
         * @param {*} point
         *  */
        function DrawBoard() {
            points = []
            ctx.beginPath();
            // 绘制棋盘,14*14,每格50px*50px
            for (let s = 0; s < counts + 1; s++) {
                //先绘制横
                ctx.moveTo(50, 50 * (s + 1));
                ctx.font = "14px Arial";
                ctx.lineTo(widths, 50 * (s + 1));
                // 绘制横的文字,从15开始
                ctx.fillText((counts + 1 - s), widths + 10, 50 * (s + 1)+4);
                points.push([50, 50 * (s + 1), widths, 50 * (s + 1)]);
                // 再绘制竖
                ctx.moveTo(50 * s + 50, 50);
                ctx.lineTo(50 * s + 50, heights);
                // 绘制底部文字
                ctx.fillText(bottomArray[s], 50 * s + 50-4, heights + 20);

            }
            ctx.closePath();
            ctx.stroke();

            if(!isStart)
             OpenDialog("开始游戏");
        }

2.绘制棋子

javascript 复制代码
/** 
         * 绘制棋子
         * **/
        function DrawCircle(point2, isBlack = true) {

            ctx.beginPath();
            ctx.save();
            // 绘制圆形
            ctx.arc(point2.x, point2.y, gridWidth * 0.2, 0, 2 * Math.PI);
            ctx.closePath();
            // 绘制具体的颜色
            ctx.shadowColor = SHADOW_COLOR;
            ctx.shadowOffsetX = ctx.shadowOffsetY = gridWidth * 0.06; // 位置偏移来实现阴影效果
            ctx.shadowBlur = gridWidth * 0.04;
            const gradient = ctx.createRadialGradient(point2.x, point2.y, 0, point2.x, point2.y, gridWidth * 0.4); //利用镜像画面实现立体感
            gradient.addColorStop(0, isBlack ? BLACK_CHESS_TOP_COLOR : WHITE_CHESS_TOP_COLOR);
            gradient.addColorStop(1, isBlack ? BLACK_CHESS_COLOR : WHITE_CHESS_COLOR);
            ctx.fillStyle = gradient;
            ctx.fill();

            ctx.restore();//保存最开始的状态,避免被影响---canvas相当于一个画笔,颜色之类的可能会改变
        }

3.获取棋盘所有点

javascript 复制代码
/**
         * 获取棋盘所有交点的坐标 
         * 
         * **/
        function getAllIntersectPoints() {
            pointsAll = []
            // 获取所有交点的坐标
            for (let i = 0; i < points.length; i++) {
                // 第一个为x轴,每个需要+50,第二个不变,3和4暂时不需要
                // 一行15个点
                for (let s = 0; s < 15; s++) {
                    pointsAll.push({ x: points[i][0] + (50 * s), y: points[i][1], radius: gridWidth * 0.5, tr: i, td: s, status: -1 })
                }
            }
        }

4.开始游戏

javascript 复制代码
// 棋子属性
        BLACK_CHESS_COLOR = '#000000', // 黑棋底黑
        BLACK_CHESS_TOP_COLOR = '#707070', // 黑棋顶灰,顶灰过渡到底黑+阴影=立体
        WHITE_CHESS_COLOR = '#D5D8DC',  // 白棋底灰
        WHITE_CHESS_TOP_COLOR = '#FFFFFF', // 白棋顶白,顶白过渡到底灰+阴影=立体
        SHADOW_COLOR = 'rgba(0, 0, 0, 0.5)', // 阴影颜色

        canvas.onclick = function (e) {
            x = e.offsetX;
            y = e.offsetY;
            if(!isStart){
               if (x >= 370 && x <= 390 && y >= 361 && y <= 391) {
                // 游戏开始
                RestartDrawPiece();
               }
 
            } 
            if(!isStart){
                return;
            }

            // 根据位置判断下是否在点位范围内
            for (let m = 0; m < pointsAll.length; m++) {
                var point2 = pointsAll[m]
                // 判断是不是在点位范围,在就获取点位
                if (Math.sqrt(Math.pow(x - point2.x, 2) + Math.pow(y - point2.y, 2)) <= point2.radius) {
                    if (pointsAll[m].status == -1) {
                        isBlack = !isBlack;
                        pointsAll[m].status = isBlack ? 1 : 0;
                        DrawCircle(pointsAll[m], isBlack);
                        if(canPlacePiece(isBlack, pointsAll[m].x, pointsAll[m].y)){
                            if(isBlack){

                                OpenDialog("黑子赢了");
                            } else {
                                OpenDialog("白子赢了");
                            }
                            isStart = false; // 游戏结束
                            isBlack = false; // 重置
                        }
                    }
                }
            }
        }
/**
         * 绘制提示弹框
         * */
        function OpenDialog(value){
            ctx.beginPath();
            ctx.rect(widths/2-150, heights/2-100, 300, 200);
            ctx.fillStyle = "white";
            ctx.fillRect(widths/2-150, heights/2-100, 300, 200);
            ctx.stroke();
            ctx.fillStyle = "black";
            ctx.font = "20px Arial";
            ctx.fillText(value, widths/2-40, heights/2-55);

            // 绘制开始图标
            ctx.beginPath();
            ctx.arc(widths/2, heights/2, 20, 0, 2 * Math.PI);
            ctx.stroke();

            // 绘制箭头
            ctx.beginPath();
            ctx.moveTo(390, 376);
            ctx.lineTo(370, 361);
            ctx.lineTo(370, 391);
            ctx.closePath();
            ctx.stroke();
            
        }
        

5.判断输赢

javascript 复制代码
/**
         * 检查输赢
         * @params x,y->当前的点位
         * @params role -> 黑棋还是白棋
         * */
        function canPlacePiece(isBlack=false,x=0,y=0) {
            let status = isBlack ? 1 : 0;
            // 需要将数组处理成二维数组,按行展开
            // 先获取行
            let trs = pointsAll.map(item => item['y'])
            trs= Array.from(new Set(trs));
            trs.sort((a,b) => {
                return a - b
            });
            let txys = []
            // 按行转化成二维数组
            for(let s=0;s<trs.length;s++){
                let arr = []
                let arrs = []
                for(let i=0;i<pointsAll.length;i++){
                    if(pointsAll[i].y === trs[s]){
                        arr.push(pointsAll[i])
                        
                    }
                    arrs.push([i,s])
                }
                txys.push(arr)
            }
            // 检查横向
            for(let i=0;i<txys.length;i++){
                for(let j=0;j<txys[i].length;j++){
                    if(txys[i][j].status === status){
                        // 开始检查
                        if(j+4<txys[i].length){
                            // 检查横向
                            if(txys[i][j].status === txys[i][j+1].status && txys[i][j].status === txys[i][j+2].status && txys[i][j].status === txys[i][j+3].status && txys[i][j].status === txys[i][j+4].status){
                                return true;
                            }
                        }
                        if(i+4<txys.length){
                            // 检查垂直方向
                            if(txys[i][j].status === txys[i+1][j].status && txys[i][j].status === txys[i+2][j].status && txys[i][j].status === txys[i+3][j].status && txys[i][j].status === txys[i+4][j].status){
                                return true;
                            }
                        }
                        if(i+4<txys.length && j+4<txys[i].length){
                            // 左上右下
                            if(txys[i][j].status == txys[i+1][j+1].status && txys[i][j].status == txys[i+2][j+2].status && txys[i][j].status == txys[i+3][j+3].status && txys[i][j].status == txys[i+4][j+4].status){
                              return true
                            }
                        }
                        if(i-4>=0 && j+4<txys[i].length){
                            // 右上到左下方向
                            if(txys[i][j].status == txys[i-1][j+1].status && txys[i][j].status == txys[i-2][j+2].status && txys[i][j].status == txys[i-3][j+3].status && txys[i][j].status == txys[i-4][j+4].status){
                                return true
                            }
                        }
                    }
                }
            }
            return false;
        
        }

6.重新开始

javascript 复制代码
/**
         * 重新绘制,用来成功之后重新加载
         * 
         */
         function RestartDrawPiece() {
            isStart = true;
            ctx.clearRect(0, 0, 800, 800);
            DrawBoard();
            getAllIntersectPoints();
            
        }

7.完整代码

javascript 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页</title>
    <style>
        #canvas {
            background: #f1f1f1;
        }
    </style>
</head>

<body>
    <canvas id="canvas" height="800" width="800"></canvas>
    <script>
        var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        // 先绘制横线,
        // 设置棋盘宽度,高度,14*14
        var widths = 750; // 宽度,这边多出的50是他的起始位置
        var heights = 750; // 高度,这边多出的50是他的起始位置
        var counts = 14; // 格数
        var gridWidth = 50;
        var bottomArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'h', 'j', 'k', 'l', 'm', 'n', 'o'];
        var points = [];// 棋盘线所有点位
        var pointsAll = []; // 棋子可以落点的位置
        var savePiece = []; // 已保存的棋子
        let isBlack = false; // 是否是黑棋
        let successPiece = [];//成功的点位
        let isStart = false; // 是否开始游戏

        // 绘制棋盘
        DrawBoard();
        // 获取所有点位
        getAllIntersectPoints();

        // 棋子属性
        BLACK_CHESS_COLOR = '#000000', // 黑棋底黑
        BLACK_CHESS_TOP_COLOR = '#707070', // 黑棋顶灰,顶灰过渡到底黑+阴影=立体
        WHITE_CHESS_COLOR = '#D5D8DC',  // 白棋底灰
        WHITE_CHESS_TOP_COLOR = '#FFFFFF', // 白棋顶白,顶白过渡到底灰+阴影=立体
        SHADOW_COLOR = 'rgba(0, 0, 0, 0.5)', // 阴影颜色

        canvas.onclick = function (e) {
            x = e.offsetX;
            y = e.offsetY;
            if(!isStart){
               if (x >= 370 && x <= 390 && y >= 361 && y <= 391) {
                // 游戏开始
                RestartDrawPiece();
               }
 
            } 
            if(!isStart){
                return;
            }

            // 根据位置判断下是否在点位范围内
            for (let m = 0; m < pointsAll.length; m++) {
                var point2 = pointsAll[m]
                // 判断是不是在点位范围,在就获取点位
                if (Math.sqrt(Math.pow(x - point2.x, 2) + Math.pow(y - point2.y, 2)) <= point2.radius) {
                    if (pointsAll[m].status == -1) {
                        isBlack = !isBlack;
                        pointsAll[m].status = isBlack ? 1 : 0;
                        DrawCircle(pointsAll[m], isBlack);
                        if(canPlacePiece(isBlack, pointsAll[m].x, pointsAll[m].y)){
                            if(isBlack){

                                OpenDialog("黑子赢了");
                            } else {
                                OpenDialog("白子赢了");
                            }
                            isStart = false; // 游戏结束
                            isBlack = false; // 重置
                        }
                    }
                }
            }
        }

        // 此处是点击范围
        // for (let m = 0; m < pointsAll.length; m++) {
        //     ctx.beginPath();
        //     var point2 = pointsAll[m]
        //     ctx.arc(point2.x, point2.y, point2.radius, 0, 2 * Math.PI);
        //     ctx.stroke();
        // }

        /**
         * 
         * 绘制棋盘
         * @param {*} point
         *  */
        function DrawBoard() {
            points = []
            ctx.beginPath();
            // 绘制棋盘,14*14,每格50px*50px
            for (let s = 0; s < counts + 1; s++) {
                //先绘制横
                ctx.moveTo(50, 50 * (s + 1));
                ctx.font = "14px Arial";
                ctx.lineTo(widths, 50 * (s + 1));
                // 绘制横的文字,从15开始
                ctx.fillText((counts + 1 - s), widths + 10, 50 * (s + 1)+4);
                points.push([50, 50 * (s + 1), widths, 50 * (s + 1)]);
                // 再绘制竖
                ctx.moveTo(50 * s + 50, 50);
                ctx.lineTo(50 * s + 50, heights);
                // 绘制底部文字
                ctx.fillText(bottomArray[s], 50 * s + 50-4, heights + 20);

            }
            ctx.closePath();
            ctx.stroke();

            if(!isStart)
             OpenDialog("开始游戏");
        }
        
        
        /**
         * 获取棋盘所有交点的坐标 
         * 
         * **/
        function getAllIntersectPoints() {
            pointsAll = []
            // 获取所有交点的坐标
            for (let i = 0; i < points.length; i++) {
                // 第一个为x轴,每个需要+50,第二个不变,3和4暂时不需要
                // 一行15个点
                for (let s = 0; s < 15; s++) {
                    pointsAll.push({ x: points[i][0] + (50 * s), y: points[i][1], radius: gridWidth * 0.5, tr: i, td: s, status: -1 })
                }
            }
        }

        /** 
         * 绘制棋子
         * **/
        function DrawCircle(point2, isBlack = true) {

            ctx.beginPath();
            ctx.save();
            // 绘制圆形
            ctx.arc(point2.x, point2.y, gridWidth * 0.2, 0, 2 * Math.PI);
            ctx.closePath();
            // 绘制具体的颜色
            ctx.shadowColor = SHADOW_COLOR;
            ctx.shadowOffsetX = ctx.shadowOffsetY = gridWidth * 0.06; // 位置偏移来实现阴影效果
            ctx.shadowBlur = gridWidth * 0.04;
            const gradient = ctx.createRadialGradient(point2.x, point2.y, 0, point2.x, point2.y, gridWidth * 0.4); //利用镜像画面实现立体感
            gradient.addColorStop(0, isBlack ? BLACK_CHESS_TOP_COLOR : WHITE_CHESS_TOP_COLOR);
            gradient.addColorStop(1, isBlack ? BLACK_CHESS_COLOR : WHITE_CHESS_COLOR);
            ctx.fillStyle = gradient;
            ctx.fill();

            ctx.restore();//保存最开始的状态,避免被影响---canvas相当于一个画笔,颜色之类的可能会改变
        }
        /**
         * 重新绘制,用来成功之后重新加载
         * 
         */
         function RestartDrawPiece() {
            isStart = true;
            ctx.clearRect(0, 0, 800, 800);
            DrawBoard();
            getAllIntersectPoints();
            
        }
        /**
         * 绘制提示弹框
         * */
        function OpenDialog(value){
            ctx.beginPath();
            ctx.rect(widths/2-150, heights/2-100, 300, 200);
            ctx.fillStyle = "white";
            ctx.fillRect(widths/2-150, heights/2-100, 300, 200);
            ctx.stroke();
            ctx.fillStyle = "black";
            ctx.font = "20px Arial";
            ctx.fillText(value, widths/2-40, heights/2-55);

            // 绘制开始图标
            ctx.beginPath();
            ctx.arc(widths/2, heights/2, 20, 0, 2 * Math.PI);
            ctx.stroke();

            // 绘制箭头
            ctx.beginPath();
            ctx.moveTo(390, 376);
            ctx.lineTo(370, 361);
            ctx.lineTo(370, 391);
            ctx.closePath();
            ctx.stroke();
            
        }
        /**
         * 检查输赢
         * @params x,y->当前的点位
         * @params role -> 黑棋还是白棋
         * */
        function canPlacePiece(isBlack=false,x=0,y=0) {
            let status = isBlack ? 1 : 0;
            // 需要将数组处理成二维数组,按行展开
            // 先获取行
            let trs = pointsAll.map(item => item['y'])
            trs= Array.from(new Set(trs));
            trs.sort((a,b) => {
                return a - b
            });
            let txys = []
            // 按行转化成二维数组
            for(let s=0;s<trs.length;s++){
                let arr = []
                let arrs = []
                for(let i=0;i<pointsAll.length;i++){
                    if(pointsAll[i].y === trs[s]){
                        arr.push(pointsAll[i])
                        
                    }
                    arrs.push([i,s])
                }
                txys.push(arr)
            }
            // 检查横向
            for(let i=0;i<txys.length;i++){
                for(let j=0;j<txys[i].length;j++){
                    if(txys[i][j].status === status){
                        // 开始检查
                        if(j+4<txys[i].length){
                            // 检查横向
                            if(txys[i][j].status === txys[i][j+1].status && txys[i][j].status === txys[i][j+2].status && txys[i][j].status === txys[i][j+3].status && txys[i][j].status === txys[i][j+4].status){
                                return true;
                            }
                        }
                        if(i+4<txys.length){
                            // 检查垂直方向
                            if(txys[i][j].status === txys[i+1][j].status && txys[i][j].status === txys[i+2][j].status && txys[i][j].status === txys[i+3][j].status && txys[i][j].status === txys[i+4][j].status){
                                return true;
                            }
                        }
                        if(i+4<txys.length && j+4<txys[i].length){
                            // 左上右下
                            if(txys[i][j].status == txys[i+1][j+1].status && txys[i][j].status == txys[i+2][j+2].status && txys[i][j].status == txys[i+3][j+3].status && txys[i][j].status == txys[i+4][j+4].status){
                              return true
                            }
                        }
                        if(i-4>=0 && j+4<txys[i].length){
                            // 右上到左下方向
                            if(txys[i][j].status == txys[i-1][j+1].status && txys[i][j].status == txys[i-2][j+2].status && txys[i][j].status == txys[i-3][j+3].status && txys[i][j].status == txys[i-4][j+4].status){
                                return true
                            }
                        }
                    }
                }
            }
            return false;
        
        }

        // function checkWin(board, player) {
        //     // 遍历棋盘
        //     for (let i = 0; i < board.length; i++) {
        //         for (let j = 0; j < board[i].length; j++) {
        //             // 如果当前位置是当前玩家的棋子
        //             if (board[i][j].status === player) {
        //                 // 检查水平方向
        //                 if (j <= board[i].length - 5) {
        //                     if (board[i][j].status === board[i][j+1].status && board[i][j].status === board[i][j+2].status && board[i][j].status === board[i][j+3].status && board[i][j].status === board[i][j+4].status) {
        //                         return true;
        //                     }
        //                 }
        //                 // 检查垂直方向
        //                 if (i <= board.length - 5) {
        //                     if (board[i][j].status === board[i+1][j].status && board[i][j].status === board[i+2][j].status && board[i][j].status === board[i+3][j].status && board[i][j].status === board[i+4][j].status) {
        //                         return true;
        //                     }
        //                 }
        //                 // 检查左上到右下方向
        //                 if (i <= board.length - 5 && j <= board[i].length - 5) {
        //                     if (board[i][j].status === board[i+1][j+1].status && board[i][j].status === board[i+2][j+2].status && board[i][j].status === board[i+3][j+3].status && board[i][j].status === board[i+4][j+4].status) {
        //                         return true;
        //                     }
        //                 }
        //                 // 检查右上到左下方向
        //                 if (i >= 4 && j <= board[i].length - 5) {
        //                     if (board[i][j].status === board[i-1][j+1].status && board[i][j].status === board[i-2][j+2].status && board[i][j].status === board[i-3][j+3].status && board[i][j].status === board[i-4][j+4].status) {
        //                         return true;
        //                     }
        //                 }
        //             }
        //         }
        //     }
        //     // 如果没有找到连续的五个相同的棋子,则返回false
        //     return false;
        // }
    </script>
</body>

</html>
相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow1 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o1 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
----云烟----2 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024062 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
向宇it2 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康2 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud