欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

12.JavaScript实现拼图游戏源码

程序员文章站 2022-03-26 20:24:42
目前代码没有放到GitHub上,之后会放出链接 1.目录结构: 2.index.html文件:

目前代码没有放到github上,之后会放出链接

1.目录结构:

12.JavaScript实现拼图游戏源码

 

 2.index.html文件:

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>document</title>
</head>

<body>
    <div class="clearfix">
        <!-- 拼图游戏 -->
        <div style="float:left;" class="picture-puzzle">

        </div>
        <!-- 对比图片 -->
        <div style="float:right;">
            <img src="./image/dog.jpg" alt="">
        </div>
    </div>
    <script src="./js/index.js"></script>
</body>
</html>

3.index.js文件:

// 游戏参数
var gameconfig = {
    width: 589, //整张图片的宽度
    height: 416, //整张图片的高度
    row: 3, //小方块的行数
    cols: 3, //小方块的列数
    imageurl: "./image/dog.jpg", //图片的路径
    dom: document.getelementsbyclassname("picture-puzzle")[0], //游戏容器的dom
    isover: false, //游戏是否结束
    minstep: 30,//打乱拼图的最小步数
    maxstep: 100//打乱拼图的最大步数
    // ishavesolution: false //游戏是否有解
}

gameconfig.piecewidth = gameconfig.width / gameconfig.row; //每个小块的宽度
gameconfig.pieceheight = gameconfig.height / gameconfig.cols; //每个小块的高度

var blocks = []; //存储每个小块的信息

//小方块构造函数
function block(row, cols) {
    // this.sequencenumber; //方块的编号从1到(row*cols)-1;空白格编号为0
    this.width = gameconfig.piecewidth; //宽
    this.height = gameconfig.pieceheight; //高
    this.correctrow = row; //小方块所在正确的行数,用来判断方块行数是否正确
    this.correctcols = cols; //小方块所在正确的列数,用来判断方块列数是否正确
    this.row = row; //小方块当前所在行数
    this.cols = cols; //小方块当前所在列数
    this.isdisplay = false; //是否是空白块:true.是;false:否;

    this.div = document.createelement("div");
    this.div.style.width = gameconfig.piecewidth + "px";
    this.div.style.height = gameconfig.pieceheight + "px";
    this.div.style.background = `url("${gameconfig.imageurl}") -${this.correctcols * this.width}px -${this.correctrow * this.height}px`;
    this.div.style.border = "1px solid #fff";
    this.div.style['box-sizing'] = "border-box";
    this.div.style.position = "absolute";

    this.show = function () { //展示小方块显示的位置
        this.div.style.left = this.cols * gameconfig.piecewidth + "px";
        this.div.style.top = this.row * gameconfig.pieceheight + "px";

    }
    this.show();

    if (row === gameconfig.row - 1 && cols === gameconfig.cols - 1) { //最后一方块隐藏
        this.div.style.display = "none";
        this.isdisplay = true; //是否是空白块:true.是;false:否;
    }
    gameconfig.dom.appendchild(this.div);

    this.iscorrect = function () { //判断方块当前位置的行列是否等于正确位置的行列
        if (this.row === this.correctrow && this.cols === this.correctcols) {
            return true;
        }
        return false;
    }
}

//初始化游戏
function init() {
    //1.初始化游戏容器宽度
    initgamedom();
    //2.初始化每个小方块基本信息
    initblocksarray();
    //3.乱序拼图可解的算法没有看懂,只能程序自动走100步
    // while (!gameconfig.ishavesolution) {
    randomsort();
    // }
    //4.注册点击事件
    registerevent();

    //初始化游戏容器
    function initgamedom() {
        gameconfig.dom.style.width = gameconfig.width + "px";
        gameconfig.dom.style.height = gameconfig.height + "px";
        gameconfig.dom.style.border = "2px solid #ccc";
        gameconfig.dom.style.position = "relative";
    }

    //初始化小方块数组信息
    function initblocksarray() {
        for (var i = 0; i < gameconfig.row; i++) {
            for (var j = 0; j < gameconfig.cols; j++) {
                // 每个小块的基本信息
                var block = new block(i, j);
                blocks.push(block);
            }
        }
        // blocks.foreach(function (item, index) {
        //     item.sequencenumber = index + 1;
        // });
        // blocks[gameconfig.row * gameconfig.cols - 1].sequencenumber = 0; //最后一个空白块编号为0
    }

    //把小方块打乱顺序
    function randomsort() {
        var step = getrandom(gameconfig.minstep, gameconfig.maxstep);//随机在[30,100)区间里取出一个数,作为打乱拼图的步数
        console.log(step);
        //程序自走step步,将拼图顺序打乱
        for (var i = 0; i < step; i++) {
            // 找到空白块所在的行和列
            var blankblock = blocks.filter(function (item) {
                return item.isdisplay;
            });

            for (var j = 0; j < blocks.length; j++) {
                //判断是否可以交换,横坐标相同则纵坐标相差1||纵坐标相同则横坐标相差为1
                if (blocks[j].row === blankblock[0].row && math.abs(blocks[j].cols - blankblock[0].cols) === 1 ||
                    blocks[j].cols === blankblock[0].cols && math.abs(blocks[j].row - blankblock[0].row) === 1) {
                    exchangeblocks(blocks[j], blankblock[0]);
                    continue; //交换一次后进入下个循环,保障交换次数为step次
                }
            }
        }
        // for (var i = 0; i < (gameconfig.row * gameconfig.cols - 1); i++) {
        //     //1.产生一个随机数
        //     //2.将当前小方块信息和随机选中的小方块信息互换,最后一个空白块位置不变
        //     var index = getrandom(0, blocks.length - 2);
        //     //交换数据
        //     exchangeblocks(blocks[i], blocks[index]);
        // }

        blocks.foreach(function (item) {
            item.show();
        });
        //判断拼图是否有解
        // havesolution();
    }

    //判断乱序的拼图是否有解
    // function havesolution() {
    //     var count = 0;
    //     //计算逆序列个数,逆序数:前面的编号大于后面的编号的个数
    //     for (var i = 0; i < blocks.length; i++) {
    //         for (var j = i + 1; j < (blocks.length - 1 - i); j++) {
    //             console.log(i, j, blocks[i].sequencenumber);
    //             if (blocks[i].sequencenumber > blocks[j].sequencenumber) {
    //                 count++;
    //             }
    //         }
    //     }
    //     console.log(count);

    //     //计算空白块编号为0所在的位置
    //     var blankblock = gameconfig.row * gameconfig.cols - 1;

    //     //奇偶性不同则无解
    //     gameconfig.ishavesolution = (count % 2 != blankblock % 2) ? false : true;
    //     console.log(gameconfig.ishavesolution);
    // }

    //为方块注册事件
    function registerevent() {
        //找到空白块
        var isdisplayblock = blocks.find(function (item) {
            return item.isdisplay;
        });
        blocks.foreach(function (item) {
            item.div.onclick = function () {
                if (gameconfig.isover) { //游戏结束,则不在继续以下操作
                    return;
                }
                //判断是否可以交换,横坐标相同则纵坐标相差1||纵坐标相同则横坐标相差为1
                if (item.row === isdisplayblock.row && math.abs(item.cols - isdisplayblock.cols) === 1 ||
                    item.cols === isdisplayblock.cols && math.abs(item.row - isdisplayblock.row) === 1) {
                    exchangeblocks(item, isdisplayblock);
                }
                //游戏结束
                iswin();
            }
        });
    }

    //交换两个方块的位置
    function exchangeblocks(b1, b2) {
        var temp = b1.row;
        b1.row = b2.row;
        b2.row = temp;

        var temp = b1.cols;
        b1.cols = b2.cols;
        b2.cols = temp;

        // var temp = b1.sequencenumber;
        // b1.sequencenumber = b2.sequencenumber;
        // b2.sequencenumber = temp;

        b1.show();
        b2.show();
    }

    //游戏结束
    function iswin() {
        var wrongblocks = blocks.filter(function (item) { //筛选出位置错误的方块
            return !item.iscorrect();
        });
        if (wrongblocks.length === 0) { //所有方块都在正确位置
            gameconfig.isover = true; //游戏结束
            blocks.foreach(function (item) {
                item.div.style.display = "block";
                item.div.style.border = "none";
            });
        }
    }
    //-------------通用函数----begin-----------//

    //返回一个[min,max)区间的随机数
    function getrandom(min, max) {
        return math.floor(math.random() * (max - min)) + min;
    }

    //-------------通用函数----end-----------//
}

init();

代码中都有简单注释,有什么问题请在评论中提出,这里只讲解拼图初始化时打乱拼图顺序所用的方法。

在网上找了好多拼图的可解算法,都没有看太懂,若读者知道或有实现方法,请赐教。

我这里使用randomsort()方法,让正确的顺序自动走一定的步数去打乱拼图的顺序。

4.图片文件

可以从网上随意找一张图片放到1中的image文件夹下,记得更改图片名称和路径(imageurl),和图片的width和height

12.JavaScript实现拼图游戏源码

 

 上图中是游戏的参数配置,可以自己修改下row,cols,minstep,maxstep看下效果

 

 

效果展示:

12.JavaScript实现拼图游戏源码