游戏分析
说起华容道游戏,可真的是经典游戏了,记得小时候有那种塑料的拼图板,能让人玩上一整天,有时候半天搞不定,光想给每个块块抠出来重新组上去,现在有电脑了,自己还是个从业多年的菜鸟程序员,是时候学习一下实现这个东西了。
今天就先实现一下数字华容道。数字华容道,一般是正方形的,9宫格,16宫格,25宫格,总之横竖行数量一致。
图形上来说:
- 绘制地图
- 绘制数字
- 定位数字位置
- 开始结束按钮
- 计时显示
- 结果展示
逻辑上来说:
- 初始化数字位置告知玩家成功的样子
- 点击开始结束按钮触发事件,开始时乱序排序数字位置开始计时,结束时停止计时,给出完成情况
- 移动数字,判断数字是否满足移动条件并进行移动
- 验证是否完成游戏
代码实现
先创建个.html文件引入jquery,设置样式,设置容器
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>华容道</title>
7 <script src="http://lib.sinaapp.com/js/jquery/3.1.0/jquery-3.1.0.min.js"></script>
8 </head>
9 <style>
10 .box {
11 width: 300px;
12 height: 300px;
13 border: 1px solid #ccc;
14 margin: 0 auto;
15 position: relative;
16 }
17
18 .box .sz {
19 width: 90px;
20 height: 90px;
21 background: #ecc;
22 border: 2px #cec solid;
23 position: absolute;
24 font-size: 40px;
25 line-height: 90px;
26 text-align: center;
27 }
28
29 .box .sz.kong {
30 border: 2px transparent solid;
31 background: transparent
32 }
33
34 .btnbox {
35 text-align: center;
36 padding-top: 20px;
37 }
38
39 .btnbox .time {
40 color: teal
41 }
42
43 .btnbox .jieguo {
44 color: red
45 }
46 #btn {
47 text-align: center;
48 margin: 0 auto;
49 }
50 </style>
51 <body>
52 <div class="box">
53 </div><!--游戏容器-->
54 <div class="btnbox">
55 <div class="time">0</div><!--计时展示区-->
56 <div class="jieguo"></div><!--结果展示区-->
57 <button id="btn"></button><!--开始结束按钮-->
58 </div>
59 </body>
60 </html>
开始正式的代码部分
1 $(function (k) {
2 let state = false;//初始化游戏状态true为在游戏,false为已结束或未开始
3 let second = 0;//初始化游戏用时
4 let itemWidth = 100;//初始化元素宽度
5 let gongge = 9;//初始化宫格数量,默认九宫格
6 let offset = 3;//元素偏移,用于界面展示
7 var map = [];//地图数据变量
8 function initMap(total) { //初始化地图
9 gongge = total;
10 let rowCount = Math.pow(total, 1 / 2);
11 let colCount = rowCount;
12 let itemHeight = itemWidth;
13 for (var i = 0; i < rowCount; i++) {
14 map[i] = [];
15 for (var j = 0; j < colCount; j++) {
16 var eq = i * rowCount + j;//计算出当前UI元素的索引值
17 if (eq < total - 1) {
18 $('.box').append('<div class="sz">' + (eq + 1) + '</div>');
19 }
20 else {
21 $('.box').append('<div class="sz kong">' + '</div>');
22 }
23 map[i][j] = [i * itemWidth, j * itemWidth, eq + 1, eq + 1];//初始化地图记录每个数字的坐标当前数值,正确数值 map[i][j]=[0,0,3,1],表示x=0,y=0,当前显示为3,正确数值为1
24 //元素UI定位展示
25 $('.box .sz').eq(eq).css("top", map[i][j][0] + offset);
26 $('.box .sz').eq(eq).css("left", map[i][j][1] + offset);
27
28 }
29 }
30 }
31 function move(total) {
32 let rowCount = Math.pow(total, 1 / 2);
33 let colCount = rowCount;
34 let currnum = 0;
35 let winnum = 0;
36 let index = 0;
37 if (state) {
38 $(".box .sz").click(function (e) {
39 currnum = parseInt($(this).text() == '' ? gongge : $(this).text());
40 if (currnum == gongge) return;
41 Spance = findNum(total, gongge);//找到空位的地图信息
42 curr = findNum(total, currnum);//找到当前数字的地图信息
43 //判断当前数字是否可以移动到空位如果满足条件点击移动
44 if (Spance[0] == curr[0] && Math.abs(Spance[1] - curr[1]) == itemWidth || Spance[1] == curr[1] && Math.abs(Spance[0] - curr[0]) == itemWidth) {
45 let tmp = Spance[2];
46 Spance[2] = curr[2];
47 curr[2] = tmp;
48 DrowUI(total);
49 CheckWin(total);
50 }
51 })
52 }
53 }
54 //查找某数字的地图信息
55 function findNum(total, currnum) {
56 let rowCount = Math.pow(total, 1 / 2);
57 let colCount = rowCount;
58 for (let x = 0; x < rowCount; x++) {
59 for (let y = 0; y < colCount; y++) {
60 if (map[x][y][2] == currnum) {
61 return map[x][y];
62 }
63 }
64 }
65 }
66 //初始化界面
67 function initUI() {
68 let rowCount = Math.pow(gongge, 1 / 2);
69 $("#btn").text("开始");
70 $(".box").width(rowCount * itemWidth);
71 $(".box").height(rowCount * itemWidth);
72 }
73 //判断是否完成游戏
74 function CheckWin(total) {
75 let rowCount = Math.pow(total, 1 / 2);
76 let colCount = rowCount;
77 let itemWidth = 100;
78 let itemHeight = itemWidth;
79 let wincount = 0;
80 for (var i = 0; i < rowCount; i++) {
81 for (var j = 0; j < colCount; j++) {
82 if (map[i][j][2] == map[i][j][3]) {
83 wincount++;
84 }
85 }
86 }
87 if (wincount == total) { //完成游戏条件,每个地图里的当前数字等于正确数字
88 Stop(true);
89 }
90 }
91 //每次移动后的界面绘制
92 function DrowUI(total) {
93 let rowCount = Math.pow(total, 1 / 2);
94 let colCount = rowCount;
95 let itemHeight = itemWidth;
96 for (var i = 0; i < rowCount; i++) {
97 for (var j = 0; j < colCount; j++) {
98 var eq = map[i][j][2] - 1;
99 $('.box .sz').eq(eq).css("top", map[i][j][0] + offset);
100 $('.box .sz').eq(eq).css("left", map[i][j][1] + offset);
101
102 }
103 }
104 }
105 var t = null;
106 //乱序数字顺序开始游戏时触发
107 function DoRandom(total) {
108 let i = 0;
109 while (i < total) {
110 let rowCount = Math.pow(total, 1 / 2);
111 let colCount = rowCount;
112 let x = Math.floor(Math.random() * rowCount);
113 let y = Math.floor(Math.random() * colCount);
114 let x1 = Math.floor(Math.random() * rowCount);
115 let y1 = Math.floor(Math.random() * colCount);
116 let tmp = 0;
117 tmp = map[x][y][2];
118 map[x][y][2] = map[x1][y1][2];
119 map[x1][y1][2] = tmp;
120 i++;
121 }
122 }
123 //开始游戏的一些设置
124 function Start(total) {
125 DoRandom(total);
126 DrowUI(total);
127 state = true;
128 move(total);
129 $("#btn").text("结束");
130 t = setInterval(function () {
131 if (state) {
132 second++;
133 }
134 $(".btnbox .time").text(second + 'S');
135 }, 1000);
136 CheckWin(total);
137 }
138 //游戏结束时的一些设置
139 function Stop(win) {
140 if (win) {
141 $(".btnbox .jieguo").text("恭喜过关!用时:" + second + "S");
142 }
143 else {
144 $(".btnbox .jieguo").text("很遗憾,没有完成!用时:" + second + "S");
145 }
146 $("#btn").text("开始");
147 $(".box .sz").off('click');
148 state = false;
149 clearInterval(t);
150 second = 0;
151 $(".btnbox .time").text(second);
152 t = null;
153 }
154 $("#btn").click(function () {
155 if (state) {
156 Stop();
157 }
158 else {
159 Start(gongge);
160 }
161 })
162 initMap(16);//这里的数字用于切换宫格数量,可以为9,16,25,36,49,64 可以修改程序让界面上点击或输入难易重构界面
163 initUI();
164 })