1.写作背景
快过春节了,又是一年要过去了,技术差的要命,最近工作不是很忙,借此机会搞个小游戏练练手提升一下逻辑思维能力。(咳咳,编不下去了,也没怎么写过文章,不知道都是怎么起手下笔的!)
最近玩了几个密室逃脱的小游戏,发现华容道游戏基本上都会在游戏中出现,对于没有做过小游戏的我来说,这貌似是个不错的入门方向。于是就有了这个创造代码
2.游戏分析
说起华容道游戏,可真的是经典游戏了,记得小时候有那种塑料的拼图板,能让人玩上一整天,有时候半天搞不定,光想给每个块块抠出来重新组上去,现在有电脑了,自己还是个从业多年的菜鸟程序员,是时候学习一下实现这个东西了。
今天就先实现一下数字华容道。数字华容道,一般是正方形的,9宫格,16宫格,25宫格,总之横竖行数量一致。
图形上来说:
- 绘制地图
- 绘制数字
- 定位数字位置
- 开始结束按钮
- 计时显示
- 结果展示
逻辑上来说:
- 初始化数字位置告知玩家成功的样子
- 点击开始结束按钮触发事件,开始时乱序排序数字位置开始计时,结束时停止计时,给出完成情况
- 移动数字,判断数字是否满足移动条件并进行移动
- 验证是否完成游戏
3.代码实现
先创建个.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 })
小小的一次练手。希望自己的技术能不断进步!