Javascript: 实现拼图游戏

来源:互联网 发布:tomcat和apache的区别 编辑:程序博客网 时间:2024/06/05 23:55

注:本人网页项目github:linwh8

需求规格:

1.UI(10分): UI与效果图完全一致;或者,自由发挥,设计出更加漂亮、合理的UI(可以使用其他图片);
2.正常移动(20分): 点击空白旁边的图块,图块移动空白处。点击其他图块,不会移动;
3.图块图片正常(20分):无论如何移动 ,每个图块上的图片都保持不变;
4.拼图结束(10分): 当拼回原图时,提示用户游戏获胜;
5.重新开始(10分):点击重新开始,打乱、重新洗牌;
6.增加趣味性(10分):发挥想象力,增加内容或者功能,让游戏更加好玩。

软件质量要求:

Soc:(5分) 正确运用适当的语言分别定义网页的内容、外观和行为,没有侵入式代码
HTML代码符合课程要求(5分)
CSS代码符合课程要求(5分)
JavaScipt代码符合课程要求(5分)

效果如下:
puzzle

实现算法:
1. JavaScript动态生成拼图:通过生成16个div,且除最后一个div不使用背景图片以外,其他div都设置拼图图片为背景。然后通过调整background-position来实现效果图中的拼图效果;
2. 打乱拼图:定义一个大小为15的数组,且其中的值依次为1-15,然后通过定义一个比较函数,利用sort(cmp)实现随机打乱,也就生成了一个随机数组,然后根据这个数组改变类名,定义拼图分块的位置;

function cmp() {    return 0.5-Math.random();}

但是,生成的拼图不一定能恢复到原来的样子,必须进行验证,如果没有通过验证,则需要重新生成随机数组,对于这个验证,可以详见这篇博文: 15迷问题的证明(15 puzzle)
3 .非常重要:id用来代表图片的特定位置,如第一行第一个,第二行第三个等,然后通过类来定义left与top属性,即可以通过改变类名来实现元素的移动。
4. 元素的移动:需要判断点击的方格是否与空方格相邻,可以通过offsetTop与offsetLeft属性进行比较判断,然后通过交换被点击方格与空白方格的类名来实现;
5. 检查是否结束游戏:生成拼图时,id与position是一一对应的,因此只需要判断所有元素是否都一一对应,如果都一一对应,游戏结束,否则,继续。

代码如下:

HTML:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Fifteen_puzzle</title>    <link rel="stylesheet" type="text/css" href="CSS/puzzle.css">    <script type="text/javascript" src="JS/puzzle.js"></script></head><body>    <h1> 拼图游戏 </h1>    <div id="result"></div>    <div id="picture"></div>    <div id="restart">重新开始</div>    <div id="change_image">更换图片</div></body></html>

CSS:

/* 大布局定位 */html, body {    width: 100%;    height: 100%;    margin: 0px;    padding: 0px;    overflow: hidden;}/* 元素居中 */body {    text-align: center;}/* 结果显示 */#result {    width: 200px;    height: 50px;    font-size: 40px;    color: red;    font-family: Courier, "Andale Mono", Arial, sans-serif;}#picture, #restart, #result, #change_image {    margin-top: 30px;    margin-left: auto;    margin-right: auto; }/* 拼图容器 */#picture {    position: relative;    width: 350px;    height: 355px;    margin-bottom: 30px;}/* 重新开始按钮 */#restart, #change_image {    cursor: pointer;    width: 120px;    height: 40px;    line-height: 40px;    background-color: #4286F5;    box-shadow: 3px 4px 15px black;    color: white;    font-size: 18px;    opacity: 0.7;}#restart:hover, #change_image:hover {    opacity: 1;    transform: scale(1.1);}/* 图片分块 */.picture_part0 {    background: url("../Image/1.jpg") no-repeat;}.picture_part1 {    background: url("../Image/2.jpg") no-repeat;}.picture_part0, .picture_part1 {    transition-duration: 0.2s;    position: absolute;    border: solid 1px #969696;    display: inline-block;    width: 83px;    height: 83px;    margin-bottom: -4px;    opacity: 0.9;}.picture_part:hover {    opacity: 1;    transform: scale(1.05);}/* 类名 position_x 代表了位置 */.position_1, .position_2, .position_3, .position_4 {    top: 0px;}.position_5, .position_6, .position_7, .position_8 {    top: 85px;}.position_9, .position_10, .position_11, .position_12 {    top: 170px;}.position_13, .position_14, .position_15, .position_16 {    top: 255px;}.position_1, .position_5, .position_9, .position_13 {    left: 0px;}.position_2, .position_6, .position_10, .position_14 {    left: 85px;}.position_3, .position_7, .position_11, .position_15 {    left: 170px;}.position_4, .position_8, .position_12, .position_16 {    left: 255px;}/* id _position_x 代表每一个分块 */#_position_1 {    background-position: 0px 0px;}#_position_2 {    background-position: -85px 0px;}#_position_3 {    background-position: -169px 0px;}#_position_4 {    background-position: -253px 0px;}#_position_5 {    background-position: 0px -84px;}#_position_6 {    background-position: -85px -84px;}#_position_7 {    background-position: -169px -84px;}#_position_8 {    background-position: -253px -84px;  }#_position_9 {    background-position: 0px -168px;}#_position_10 {    background-position: -85px -168px;}#_position_11 {    background-position: -169px -168px; }#_position_12 {    background-position: -253px -168px;}#_position_13 {    background-position: 0px -252px;}#_position_14 {    background-position: -85px -252px;}#_position_15 {    background-position: -169px -252px; }#_position_16 {    opacity: 0;    background-position: -253px -252px;    background-image: none;}

JavaScript:

/*    项目:拼图游戏*/window.onload = function() {    create_pic();    document.getElementById("restart").addEventListener("click", random_pos);    document.getElementById("change_image").addEventListener("click", change_img);};/* 检查产生的随机数列是否是合理的,因为有可能出现恢复不到原图的情况 */function check_random_isValid() {    var count = 0;    for (var i = 0; i < 16; i++) {        for (var j = i+1; j < 16; j++) {            if (random_arr[j] < random_arr[i]) {                count++;            }        }    }    return count%2===0;}/* 产生拼图 */function create_pic() {    picture = document.getElementById("picture");    for (var i = 1; i <= 16; i++) {        var part = document.createElement("div");        part.addEventListener("click", pic_move);        part.className = "picture_part" + count + " position_"+i;        picture.appendChild(part);        part.id = "_position_"+i;    }}/* 改变图片 */var count = 0;function change_img(event) {    if (count < 1) count++;    else return;    for (var i = 0; i < 16; i++) {        picture.childNodes[i].className += " picture_part" + count;    }}/* 产生随机数列定义位置 */function random_pos(event) {    document.getElementById("result").innerText = "";    /* 产生随机数列前先将拼图块对应的位置复位 */    for (var k = 1; k <= 16; k++) {        document.getElementById("_position_"+k).className="picture_part"+count+" position_"+k;    }    var part = document.getElementById("picture").childNodes;    random_arr = [];    for (var j = 0; j < 15; j++) {        random_arr[j] = j+1;    }    /* 利用sort和cmp进行随机打散 */    function cmp() { return 0.5-Math.random(); }    while(1) {        random_arr.sort(cmp);        if (check_random_isValid()) {            break;        }    }    /* 通过更改类名来改变位置 */    for (var i = 0; i < 15; i++) {        part[i].className = "picture_part" + count + " position_" + random_arr[i];    }}/* 点击图片触发的事件处理器 */function pic_move(event) {    var blank_pic_offset = document.getElementById("_position_16");    var blank_pic_offset_top = blank_pic_offset.offsetTop;    var blank_pic_offset_left = blank_pic_offset.offsetLeft;    var _offset_top = this.offsetTop;    var _offset_left = this.offsetLeft;    /* 判断点击的图片块是否与空格块相邻 */    if ((Math.abs(blank_pic_offset_top-_offset_top) == 85 && blank_pic_offset_left == _offset_left) ||        (Math.abs(blank_pic_offset_left-_offset_left) == 85 && blank_pic_offset_top == _offset_top)) {        var str = blank_pic_offset.className;        blank_pic_offset.className = this.className;        this.className = str;        check(); // 检查是否还原原图    }}/* 检查是否还原原图 */function check() {    for (var i = 1; i <= 16; i++) {        var item = document.getElementById("_position_"+i);        if (item.className != "picture_part" + count +" position_"+i &&            item.className != "picture_part0" + " position_" + i + " picture_part1") {            document.getElementById("result").innerText = "Continue...";            return;        }    }    document.getElementById("result").innerText = "You Win!";}

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


0 0
原创粉丝点击