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

function cmp() {
return 0.5-Math.random();
}
1
2
3
但是,生成的拼图不一定能恢复到原来的样子,必须进行验证,如果没有通过验证,则需要重新生成随机数组,对于这个验证,可以详见这篇博文: 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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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!";
}

拼图游戏js的更多相关文章

  1. 拼图游戏(js,C#,java三种语言)

    <html> <head> <meta charset="utf-8"> <style type="text/css" ...

  2. 利用Vue.js实现拼图游戏

    之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5 ...

  3. Vue.js实现拼图游戏

    Vue.js实现拼图游戏 之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/ ...

  4. html+css+js实现网页拼图游戏

    代码地址如下:http://www.demodashi.com/demo/14449.html 项目描述 使用 html+js+css 实现一个网页拼图游戏,可支持简单,中等,困难三种难度. 演示效果 ...

  5. 原生JS实现拼图游戏

    最近无聊,练练原生JS:实现拼图游戏.两种玩法:第一种是单击元素进行交换位置:第二种是拖拽元素进行位置交换.首先需要上传图片并进行回显(需要用到FileReader):下面是部分截图: 可以自行设置切 ...

  6. Flexbox + js实现滑动拼图游戏

    滑动拼图就是把一张图片分成几等份,打乱顺序(下图),然后通过滑动拼凑成一张完整的图片. 要实现一个拼图游戏,需要考虑怎样随机的打乱顺序,怎样交换两张图片的位置,等等.但是,使用了Flexbox布局以后 ...

  7. JavaScript写一个拼图游戏

    拼图游戏的代码400行, 有点多了, 在线DEMO的地址是:打开: 因为使用canvas,所以某些浏览器是不支持的: you know: 为什么要用canvas(⊙o⊙)?  因为图片是一整张jpg或 ...

  8. 微信小程序开发的游戏《拼图游戏》

    微信小程序开发的游戏<拼图游戏> 代码直接考进去就能用 pintu.js // pintu.js Page({ /** * 页面的初始数据 */ data: { }, initGame: ...

  9. 一款html拼图游戏详解

    本文是爱编程原创翻译,转载请看清文末的转载要求,谢谢合作! 游戏介绍 这篇文章是献给web游戏开发者用简单的开发工具开发一款游戏.此文介绍了用html.css.javascript只需简单和几个步骤开 ...

随机推荐

  1. EXCEL FAQ

    1.win7双击打开EXCEL07时显示停止工作,但是在打开方式中可以打开,怎么破? 加载项的问题,在选项-信任中心-信任中心设置-加载项-禁用所有应用程序加载项即可,但是这样会丧失一些功能,也可以把 ...

  2. 2019.1.10 L223

    Heavy rains that brought additional pollution downstream last year contributed to the first decline ...

  3. Myecilpse web +tomcat 项目: JSP在mysql中创建表

    <%@ page language="java" import="java.util.*" import="com.mysql.jdbc.Dri ...

  4. Uboot中start.S源码的指令级的详尽解析

    Uboot中start.S源码的指令级的详尽解析 https://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html ...

  5. [转]一种让超大banner图片不拉伸、全屏宽、居中显示的方法

    现在很多网站的Banner图片都是全屏宽度的,这样的网站看起来显得很大气.这种Banner一般都是做一张很大的图片,然后在不同分辨率下都是显示图片的中间部分.实现方法如下: <html> ...

  6. opencv-原图基础上添加指定颜色

    前言 项目中需要将某些区域使用不同的颜色表示出来,同时能够看到原图作为底色. 代码 #include "opencv2/highgui/highgui.hpp" #include ...

  7. liunx中安装包及其应用

    1. dpkg -i <package>  安装包 dpkg -r <package>   删除包 dpkg -P <package> 移除包和配置文件 dpkg ...

  8. null 与 undefinded

    null表示"没有对象",即该处不应该有值.典型用法是: (1) 作为函数的参数,表示该函数的参数不是对象. (2) 作为对象原型链的终点. Object.getPrototype ...

  9. CTF密码学之凯撒加密

    在加密的各种算法中,凯撒加密是最简单的也是最常见的一种加密方法,它的中心思想是替换,ROT加密其实就是凯斯加密的变种. 即明文的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文 ...

  10. Microsoft - Get Course Order

    // "static void main" must be defined in a public class. public class Main { public static ...