扫雷html实现思路

举报
兔老大 发表于 2021/04/22 00:38:39 2021/04/22
【摘要】 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="C...

  
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>扫雷网页游戏</title>
  6. <meta content="" name="keywords" />
  7. <meta content="" name="description" />
  8. <style type="text/css">
  9. table{TABLE-LAYOUT: fixed;cursor:pointer}
  10. td{width: 20px; height: 20px; font-size: 12px; font-family: Verdana;font-weight:bold; text-align:center;background:#CECECE;}
  11. td.Normal, .Flag{border-left:2px solid #F5F5F5; border-right:2px outset #F5F5F5; border-top:2px solid #F5F5F5; border-bottom:2px outset #F5F5F5; font-weight:bold}
  12. .Mine, .Boom, .M0, .M1, .M2, .M3, .M4, .M5, .M6, .M7, .M8{background:#C5C5C5;border-right:1px solid #B4B4B4; border-bottom:1px solid #B4B4B4;}
  13. td.Mine{background: url(img/mine.gif) no-repeat center}
  14. td.Boom{background:#F00 url(img/mine.gif) no-repeat center}
  15. td.Flag, td.ErrFlag{background-image: url(img/flag.gif);background-repeat: no-repeat; background-position: center;}
  16. td.ErrFlag{background:#0F0}
  17. td.M1 {color: #00f}
  18. td.M2 {color: #008000}
  19. td.M3 {color: #f00}
  20. td.M4 {color: #000080}
  21. td.M5 {color: #800000}
  22. td.M6 {color: #008080}
  23. td.M7 {color: #000}
  24. td.M8 {color: #808080}
  25. </style>
  26. <script>
  27. var $=function(id){return document.getElementById(id)},
  28. MouseButton=LeftMouse=0,//作为双键单击的计数,mouseup事件置0,mousedown事件+1,当MouseButton=2说明双键同时单击;鼠标左键是否按下,当鼠标左键按下时为1,松开为0
  29. FlagImg=new Image(),
  30. HappyImg=new Image(),
  31. MineImg=new Image(),
  32. SadImg=new Image(),
  33. SuccessImg=new Image(),
  34. WhichButton=function(e){
  35. e=e||window.event;
  36. var b=getOs();
  37. if(b!=2){ //非FF
  38. switch(e.button){
  39. case 2:
  40. return 0;
  41. case 0:
  42. return b==1?0:1; //b==1,IE
  43. default:
  44. return 1;
  45. }
  46. }else{ //FF
  47. return e.which==3?0:1;
  48. }
  49. },
  50. OMine={
  51. MaxX:9,MaxY:9,//最大的坐标
  52. MineCount:10,//定义雷的个数,可改
  53. FlagCount:0, //已经标记的旗子的数量
  54. OpenedCount:0, //已经打开的地区的数量
  55. MaxOpenCount:0,//应该要打开的最大地区数量
  56. //当OpenedCount=MaxOpenCount&&FlagCount=MineCount的时候,判断游戏成功结束
  57. Mine:[],
  58. GameOver:false, //true代表游戏失败结束
  59. Success:false, //true代表游戏成功结束
  60. aClear:[],//临时开雷的数组
  61. //刷新网页的时候初始化
  62. fInit:function(){
  63. var T=this,MaxX=T.MaxX,MaxY=T.MaxY,nX,nY=MaxY,MineCount=T.MineCount,
  64. AStr=['<table bordercolor="#000000" border="0" cellpadding="0" cellspacing="0" height="'+20*MaxY+'px" width="'+20*MaxX+'px" style="border: 10px inset #a0a0a0">'],
  65. i=0,TAr,TMine=T.Mine;
  66. T.MaxOpenCount=MaxX*MaxY-MineCount;
  67. while(nY--){
  68. AStr[++i]='<tr>';
  69. TAr=TMine[nY]=[];
  70. nX=MaxX;
  71. while(nX--){
  72. AStr[++i]='<td class="Normal" onmousedown="OMine.fMouseDown('+nX+','+nY+',event);" onmouseup="OMine.fMouseUp('+nX+','+nY+',event);" onmouseover="OMine.fButtonMouseOver('+nX+','+nY+')" onmouseout="OMine.fButtonMouseOut('+nX+','+nY+')" id="Img'+nX+'_'+nY+'"> </td>';
  73. TAr[nX]={
  74. Mine:0, //0表示没有雷,1表示有雷
  75. State:0,//0表示未开启,1表示左键开启,2表示右键标记
  76. MineCount:0//周围有几个雷
  77. }
  78. }
  79. AStr[++i]='</tr>';
  80. }
  81. AStr[++i]='</table>';
  82. $('dMap').innerHTML=T.InitStr=AStr.join('');
  83. $('txtFlagCount').value=MineCount;
  84. T.fInitMine();
  85. $('btnRefreshMap').src='img/happy.gif';
  86. T.GameOver=T.Success=false;
  87. T.OpenedCount=T.FlagCount=T.aClear.lenght=0;
  88. },
  89. //为了方便循环赋值,给表格数组赋值的时候是XY倒过来循环的,所以调用的时候要倒回去
  90. //比如要获得该格子是否有雷,用OMine.fGetMine(x,y).Mine;
  91. fGetMine:function(X,Y){return this.Mine[Y][X]},
  92. //仅当按重新开始的按钮,不初始化大表格字符
  93. fRefreshMap:function(){
  94. var T=this;
  95. $('dMap').innerHTML=T.InitStr;
  96. T.fResetOMine();//必须先重置OMine,再重置99个雷
  97. T.fInitMine();
  98. T.GameOver=T.Success=false;
  99. $('btnRefreshMap').src='img/happy.gif';
  100. $('txtFlagCount').value=T.MineCount;
  101. T.OpenedCount=T.FlagCount=T.aClear.lenght=0;
  102. },
  103. //重置OMine.Mine数组
  104. fResetOMine:function(){
  105. var T=this,MaxY=T.MaxY,MaxX=T.MaxX,X,Y=MaxY,M,Mine=T.Mine,TAr;
  106. while(Y--){
  107. X=MaxX;
  108. TAr=Mine[Y];
  109. while(X--)(M=TAr[X]).Mine=M.State=M.MineCount=0;
  110. }
  111. },
  112. //初始化雷的数组
  113. fInitMine:function(){
  114. var T=this,MaxX=T.MaxX,MaxY=T.MaxY,a,fGetMine=T.fGetMine,
  115. aOld=[],x,y=MaxY,n=0,l=T.MineCount,xRand; //一个随机数字
  116. while(y--){
  117. x=MaxX;
  118. while(x--)aOld[n++]=[x,y];
  119. }
  120. while(l--){
  121. a=aOld[xRand=Math.floor(Math.random()*(n-1))];
  122. T.fGetMine(a[0],a[1]).Mine=1;
  123. aOld.splice(xRand,1);
  124. --n;
  125. }
  126. },
  127. //鼠标移动到某格子的时候
  128. fButtonMouseOver:function(X,Y){
  129. var T=this;
  130. switch(MouseButton){
  131. case 2://双键按下的状态
  132. var arr=T.fGetAround(X,Y),i=arr.length,TAr;
  133. while(i--)T.fButtonDown((TAr=arr[i])[0],TAr[1]);
  134. case 1:
  135. LeftMouse==1&&T.fButtonDown(X,Y); //左键是按下的
  136. }
  137. },
  138. //鼠标移出某格子的时候
  139. fButtonMouseOut:function(X,Y){
  140. var T=this;
  141. switch(MouseButton){
  142. case 2://双键按下的状态
  143. var arr=T.fGetAround(X,Y),i=arr.length,TAr;
  144. while(i--)T.fButtonUp((TAr=arr[i])[0],TAr[1]);
  145. case 1:
  146. LeftMouse==1&&T.fButtonUp(X,Y); //左键是按下的
  147. }
  148. },
  149. //鼠标按下时没被开启的格子呈现被按下
  150. fButtonDown:function(X,Y){
  151. var srcEle=$('Img'+X+'_'+Y);
  152. srcEle.className=='Normal'&&(srcEle.className='M0');
  153. },
  154. //让没被开启并且已经呈现被按下的格子回复Normal
  155. fButtonUp:function(X,Y){
  156. var srcEle=$('Img'+X+'_'+Y);
  157. srcEle.className=='M0'&&!this.fGetMine(X,Y).State&&(srcEle.className='Normal');
  158. },
  159. //获取8个方向的坐标
  160. fGetAround:function(X,Y){
  161. var TX,TY,i=8,MX=this.MaxX-1,MY=this.MaxY-1,
  162. Arr=[[-1,0],[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1]],
  163. newArr=[],TAr;
  164. while(i--){
  165. TX=X+(TAr=Arr[i])[0];
  166. TY=Y+TAr[1];
  167. !(TX<0||TX>MX||TY<0||TY>MY)&&newArr.push([TX,TY]);
  168. }
  169. return newArr;
  170. },
  171. //鼠标在格子按下
  172. fMouseDown:function(X,Y,evt){
  173. var T=this;
  174. if(T.GameOver){
  175. alert('游戏失败,再接再厉!');
  176. return;
  177. }
  178. if(T.Success){
  179. alert('恭喜游戏成功!再来一局吧?');
  180. return;
  181. }
  182. var srcEle=$('Img'+X+'_'+Y),ObXY=T.fGetMine(X,Y),arr,i,TAr;
  183. ++MouseButton;
  184. evt=evt||window.event;
  185. switch(MouseButton){
  186. case 2:
  187. arr=T.fGetAround(X,Y);i=arr.length;
  188. while(i--)T.fButtonDown((TAr=arr[i])[0],TAr[1]);
  189. break;
  190. case 1:
  191. if(WhichButton(evt)){
  192. LeftMouse=1;
  193. T.fButtonDown(X,Y);
  194. }else{
  195. switch(ObXY.State){
  196. case 0:
  197. ObXY.State=2;
  198. srcEle.className='Flag';
  199. --$('txtFlagCount').value;
  200. ++T.FlagCount;
  201. break;
  202. case 2:
  203. ObXY.State=0;
  204. srcEle.className='Normal';
  205. ++$('txtFlagCount').value;
  206. --T.FlagCount;
  207. }
  208. }
  209. }
  210. },
  211. //鼠标在格子弹起
  212. fMouseUp:function(X,Y,evt){
  213. var T=this;
  214. evt=evt||window.event;
  215. var srcEle=$('Img'+X+'_'+Y),ObXY=T.fGetMine(X,Y),arr,i,TAr;
  216. switch(MouseButton){
  217. case 2: //MouseDown为两个键都单击按下,任意一个键弹起都判断为双键弹起
  218. LeftMouse=0;
  219. //鼠标弹起,把呈现被按下状态的格子恢复
  220. arr=T.fGetAround(X,Y);i=arr.length;
  221. while(i--)T.fButtonUp((TAr=arr[i])[0],TAr[1]);
  222. !ObXY.State&&T.fButtonUp(X,Y);
  223. ObXY.State==1&&ObXY.MineCount&&T.fOpenFlagMine(X,Y);
  224. break;
  225. case 1: //当MouseDown为一个键单击时,MouseUp才判断为一个键弹起
  226. if(WhichButton(evt)){
  227. //只有在State=0才起作用,跟是否有雷没关系
  228. LeftMouse=0;
  229. if(ObXY.State){break;}
  230. ObXY.Mine?(
  231. //触雷,结束该局
  232. T.fFail(),
  233. srcEle.className='Boom'
  234. ):(
  235. ObXY.State=1, //压栈之前就要设置为已经开启
  236. T.aClear.push([X,Y]),
  237. T.fClearMine()
  238. )
  239. }
  240. }
  241. MouseButton=0;
  242. if(T.OpenedCount==T.MaxOpenCount&&T.FlagCount==T.MineCount){
  243. T.fSuccess();
  244. alert('恭喜游戏成功!再来一局吧?');
  245. return;
  246. }
  247. //当剩余未开启的格子数=剩余的旗子数,自动完成
  248. T.MaxOpenCount+T.MineCount-T.OpenedCount-T.FlagCount==$('txtFlagCount').value&&(
  249. T.fSuccess(),
  250. T.fAutoFlag(),
  251. alert('恭喜游戏成功!再来一局吧?')
  252. )
  253. },
  254. //自动填充未开启的地区的雷
  255. fAutoFlag:function(){
  256. var T=this,nX,nY=T.MaxY,MaxX=T.MaxX,Mine=T.Mine,TAr;
  257. while(nY--){
  258. nX=MaxX;
  259. TAr=Mine[nY];
  260. while(nX--)!TAr[nX].State&&($('Img'+nX+'_'+nY).className='Flag');
  261. }
  262. $('txtFlagCount').value=0;
  263. },
  264. //递归开雷
  265. fClearMine:function(){
  266. var T=this;
  267. if(T.aClear.length==0){return}
  268. ++T.OpenedCount;
  269. var aXY=T.aClear.pop(),X=aXY[0],Y=aXY[1],TX,TY,
  270. aTmpClear=[], //一个临时数组
  271. srcEle=$('Img'+X+'_'+Y),
  272. ObXY,ObTXTY,
  273. countMine=0, //获取周围雷的个数
  274. //从正左开始的8个方向
  275. arr=T.fGetAround(X,Y),i=arr.length,TAr;
  276. while(i--){
  277. //TX,TY获得本格周围的坐标
  278. (ObTXTY=T.fGetMine(TX=(TAr=arr[i])[0],TY=TAr[1])).Mine==1&&++countMine;
  279. !ObTXTY.State&&aTmpClear.push([TX,TY]);
  280. }
  281. ObXY=T.fGetMine(X,Y);
  282. ObXY.MineCount=countMine;
  283. srcEle.className='M'+countMine;
  284. if(!countMine){
  285. Array.prototype.push.apply(T.aClear,aTmpClear);
  286. i=aTmpClear.length;
  287. while(i--)T.fGetMine((TAr=aTmpClear[i])[0],TAr[1]).State=1;
  288. }else{
  289. getOs()==2?
  290. srcEle.textContent=countMine
  291. :srcEle.innerText=countMine
  292. }
  293. T.fClearMine();
  294. },
  295. //获得双键辅助开启
  296. fOpenFlagMine:function(X,Y){
  297. var T=this,FlagCount=0,TX,TY,ObXY,ObTXTY,aTmpClear=[],FlagErr=false,
  298. arr=T.fGetAround(X,Y),i=arr.length,TAr;
  299. while(i--){
  300. //TX,TY获得本格周围的坐标
  301. ObTXTY=T.fGetMine(TX=(TAr=arr[i])[0],TY=TAr[1]);
  302. switch(ObTXTY.State){
  303. case 0: //未开启未标记
  304. !ObTXTY.Mine&&aTmpClear.push([TX,TY]); //没雷也没旗子的时候加入到被辅助开启的数组}
  305. break;
  306. case 2: //标记了旗子
  307. ++FlagCount; //只要标记了旗子,无论对错,都记录标记数+1
  308. !ObTXTY.Mine&&(FlagErr=true); //没有雷但是标记了旗子,标记错误
  309. }
  310. }
  311. if(FlagCount<T.fGetMine(X,Y).MineCount||aTmpClear.length==0)return;
  312. //旗子比实际雷少,无论标记对错,不开启
  313. //没有可以提供开启的空格
  314. if(FlagErr){ //有错误则进行结束游戏处理
  315. T.fFail();
  316. return;
  317. }
  318. Array.prototype.push.apply(T.aClear,aTmpClear);
  319. i=aTmpClear.length;
  320. while(i--)T.fGetMine((TAr=aTmpClear[i])[0],TAr[1]).State=1;
  321. T.fClearMine();
  322. },
  323. //显示所有的雷
  324. fShowMine:function(){
  325. var T=this,X=0,Y=T.MaxY,MaxX=T.MaxX,Mine=T.Mine,TAr,TArX;
  326. while(Y--){
  327. X=MaxX;
  328. TAr=Mine[Y];
  329. while(X--){
  330. TArX=TAr[X];
  331. switch(TArX.Mine){
  332. case 0:
  333. TArX.State==2&&($('Img'+X+'_'+Y).className='ErrFlag');
  334. break;
  335. case 1:
  336. $('Img'+X+'_'+Y).className='Mine';
  337. }
  338. }
  339. }
  340. },
  341. //游戏成功结束
  342. fSuccess:function(){
  343. this.Success=true;
  344. $('btnRefreshMap').src='img/success.gif';
  345. },
  346. //游戏失败结束
  347. fFail:function(){
  348. this.GameOver=true;
  349. $('btnRefreshMap').src='img/sad.gif';
  350. this.fShowMine();
  351. }
  352. },
  353. //换地图
  354. ChangeMap=function(Map){
  355. var O=OMine;
  356. switch(Map){
  357. case 1:
  358. O.MaxX=O.MaxY=9;
  359. O.MineCount=10;
  360. break;
  361. case 2:
  362. O.MaxX=O.MaxY=16;
  363. O.MineCount=40;
  364. break;
  365. case 3:
  366. O.MaxX=30;
  367. O.MaxY=16;
  368. O.MineCount=99;
  369. }
  370. O.fInit();
  371. },
  372. getOs=function(){
  373. if(navigator.userAgent.indexOf("MSIE")>0)return 1;
  374. if(isFirefox=navigator.userAgent.indexOf("Firefox")>0)return 2;
  375. if(isSafari=navigator.userAgent.indexOf("Safari")>0)return 3;
  376. if(isCamino=navigator.userAgent.indexOf("Camino")>0)return 4;
  377. if(isMozilla=navigator.userAgent.indexOf("Gecko/")>0)return 5;
  378. return 0;
  379. };
  380. FlagImg.src='img/flag.gif';
  381. HappyImg.src='img/happy.gif';
  382. MineImg.src='img/mine.gif';
  383. SadImg.src='img/sad.gif';
  384. SuccessImg.src='img/success.gif';
  385. </script>
  386. </head>
  387. <body topmargin="0" oncontextmenu="return false" ondragstart="return false" onselectstart="return false" onload="OMine.fInit()" bgcolor="#808080">
  388. <center>
  389. <div id="dTop" align="center" style="border-style: inset; border-width: 10px;width:400px">
  390. <table cellpadding="0" cellspacing="0" style="border-collapse: collapse;" width="380" height="44">
  391. <tr>
  392. <td style="width: 102px; height:50px">
  393. <input type="text" id="txtFlagCount" size="20" style="width: 60px; height: 30px; color:#FF0000; text-align:center; font-family:Verdana; font-weight:bold; background-color:#000000; font-size:13pt" value=""></td>
  394. <td style="width: 136px; height:50px">
  395. <input onclick="OMine.fRefreshMap()" type="image" id="btnRefreshMap" src="img/happy.gif"><input onclick="OMine.fShowMine();" type="button" name="B3" value="显雷"style="display:none"></td>
  396. <td style="width: 142px; height:50px">
  397. <input type="radio" value="V1" checked name="R1" id="R1" onclick="ChangeMap(1)">初级<input type="radio" value="V1" name="R1" id="R2" onclick="ChangeMap(2)">中级<input type="radio" value="V1" name="R1" id="R3" onclick="ChangeMap(3)">高级</td>
  398. </tr>
  399. </table>
  400. </div>
  401. <div id="dMap" align="center"></div>
  402. </center>
  403. </body>
  404. </html>

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/103935207

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。