zoukankan      html  css  js  c++  java
  • DOM练习小记--一个简单的Web页面游戏

    资料源自《Head first Ajax》 第六章(小时候我也有这么一个游戏板,图片是米奇……)

    这是一个基于DOM的二维拼图游戏,HTML和CSS文档是原书的文档,我只是在initial版本中(没有js文件)添加了自己的js文件。
    游戏规则是点击空白格上、下、左、右四个方向相邻的图片,会把该图片移动到空白格中,然后继续,直到把所有图片的位置按顺序排列,最后一个为空格,就算赢了。

    文档结构并不复杂,静态页面是这个样子:

    静态页面

    id="puzzleGrid"div中建立一个4row*4col的table,图片都放在对应的单元格中;每个单元格的id设置为"cell+行号+列号";每个图片的alt属性也和图片本身显示的数字相同;点击事件注册在表格单元格上。

    这里贴上第一行表格的HTML代码,其他行以此为参照:

       <tr>
         <td id="cell11">
          <img src="images/07.png" alt="7" height="69" width="69">
         </td>
         <td id="cell12">
          <img src="images/06.png" alt="6" height="69" width="69">
         </td>
         <td id="cell13">
          <img src="images/14.png" alt="14" height="69" width="69">
         </td>
         <td id="cell14">
          <img src="images/11.png" alt="11" height="69" width="69">
         </td>
        </tr>
    

    基本的思路:

    1. swapTiles(selectedCell, destinationCell): 主要动作在于交换图片,接收两个参数,点击的单元格和目标单元格(空格);交换图片后判断是否赢得游戏;
    2. initPage: 页面加载完成后初始化页面,先得到所有单元格列表,遍历每个单元格注册点击事件函数 tileClick;
    3. tileClick: 每次点击一个单元格,判断是否为空(isEmpty(cell)),如果是空格则不响应;如果非空格,则得到图片的位置标记并得到上、下、左、右的单元格,找到其中是空格的单元格,与之交换图片,都是非空格则不响应;
    4. isEmpty(cell): 接收单元格为参数,判断单元格内图片是否为空图片,返回true/false
    5. getCell(pos): 接收单元格位置为参数,返回对应单元格,如找不到则返回false;
    6. isCompleted: 遍历图片列表,根据图片顺序判断是否完成游戏,返回true/false
    7. 再加一个增加window.onload事件函数的方法addLoadEvent(func);

    没有按照书上的来,先自己尝试写了下,顺便巩固一下DOM的知识。代码如下:

    function swapTiles(selectCell, destinationCell) {
      //不能直接用firstChild,是回车;
      var selectImage = selectCell.getElementsByTagName("img")[0];
      var destinationImage = destinationCell.getElementsByTagName("img")[0];
      selectCell.replaceChild(destinationImage,selectImage);
      destinationCell.appendChild(selectImage);
      // 检测游戏结果
      if (!isCompleted()) {
        document.getElementById("puzzleGrid").className = "win";
      }
    }
    
    // 初始化页面,找到对应表格并给每个表格绑定点击事件处理函数tileClick;
    function initPage() {
      var puzzleGrid = document.getElementById("puzzleGrid");
      var cells = puzzleGrid.getElementsByTagName("td");
      var i, len = cells.length;
      for (i=0; i < len; i++) {
        var cell = cells[i];
        cell.onclick = tileClick;
      }
    }
    
    function tileClick() {
      if (isEmpty(this)) {
        return false;
      }
      var pos = +(this.id.substr(4));
      var posUpCell = getCell(pos-10), 
          posDownCell = getCell(pos+10), 
          posLeftCell = getCell(pos-1), 
          posRightCell = getCell(pos+1),
          destinationCell; 
      switch(true) {
        case isEmpty(posUpCell):
        destinationCell = posUpCell;
        break;
        case isEmpty(posDownCell):
        destinationCell = posDownCell;
        break;
        case isEmpty(posLeftCell):
        destinationCell = posLeftCell;
        break;
        case isEmpty(posRightCell):
        destinationCell = posRightCell;
        break;
        default: return false;
      }
      swapTiles(this, destinationCell);
    }
    
    function isEmpty(cell) {
      if (!cell) return false;
      var cellimg = cell.getElementsByTagName("img")[0];
      if (cellimg.alt === "empty") {
        return true;
      } else {
        return false;
      }
    }
    
    function getCell(posNum) {
      var cellid = "cell"+posNum;
      if (!document.getElementById(cellid)) {
        return false;
      } else {
        return document.getElementById(cellid);
      }
    }
    
    // 判断是否赢得游戏
    function isCompleted() {
      // 用数组保存每个图片的alt值
      var arr = [],
          div = document.getElementById("puzzleGrid"),
          imgs = div.getElementsByTagName("img"),
          len = imgs.length,
          i;
      for (i=0; i < len; i++) {
        var img = imgs[i],
            imgAlt = img.alt;
            arr.push(imgAlt);
      }
      if (arr.join("") === "123456789101112131415") {
        return true;
      } else {
        return false;
      }
    }
    
    //添加window.onload事件函数;
    function addLoadEvent(func) {
      var oldload = window.onload;
      if (typeof oldload !== "function") {
        window.onload = func;
      } else {
        window.onload = function () {
          oldload();
          func();
        }
      }
    }
    addLoadEvent(initPage);
    

    总结几点经验:

    1. 一个父节点中除了我们想要的元素节点之外,可能浏览器查询到的也包含“回车符”、“空格”这类文本节点,所以node.firstChild/lastChild也许只是回车符,用这个方法获取节点时一定还要再加一层判断,if (node.firstChild.nodeType === 1), 如果不是,就继续找nextSibling.
      在这里我直接用了div.getElementByTagName("img")[0];相比之下也许获取nodeList的方式更容易造成性能问题,DOM扩展中新增的firstElementNode这一类元素版可能会是更好的选择。

    2. 第一次我的getCell(pos)isEmpty(pos)两个函数都是接收单元格位置标记pos作为参数,它们都需要先得到对应的单元格,这样造成了部分重复代码,所以进一步分离,把先把pos传递给getCell(pos)得到单元格,再把它的结果传给isEmpty(cell)就可以达到相同的效果了。而且isEmpty(cell)还可以接收单元格(比如被点击的"this")进行判断;

    3. 在循环遍历得到累加字符串时,和书中不同,我采用数组arr=[]来保存每一项内容并最后用arr.join("")的方式输出;不过根据从网上其他资料了解到的,其实这种方法在现代浏览器(其他及IE6+)不比字符串拼接更高效。(相关链接参考


    生如夏花般绚烂,死如秋叶般静美
  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/muTing/p/9095246.html
Copyright © 2011-2022 走看看