检查滑动拼图javascript的功能

时间:2015-06-13 10:54:31

标签: javascript html css puzzle

我创建了一个不同格式的滑动拼图:3x3,3x4,4x3和4x4。当您运行我的代码时,您可以在右侧看到一个选择框,您可以在其中选择4种格式。滑动枪几乎完成了。 但是我需要一个功能,如果解决了这个难题,我会在每次移动后进行检查,如果是这样的话,它应该给出一条像“你已经解决了它的祝贺!”这样的行。或者“你赢了!”知道如何做到这一点吗?

在javascript代码中,您可以看到第一个函数loadFunc()是用空白代码替换每个部分,之后的函数是选择格式并将格式更改为它。 Shiftpuzzlepieces功能使您可以将每个部件移动到空白区域。函数shuffle随机化每个片段的位置。如果您有任何疑问或理解问题,请随时在评论中提问。非常感谢提前。

由于我的声誉不足,我会在此处发布图片链接:http://imgur.com/a/2nMlt。这些图片现在只是占位符。

Here is the jsfiddle:

    http://jsfiddle.net/Cuttingtheaces/vkyxgwo6/19/

2 个答案:

答案 0 :(得分:1)

与往常一样,有一种“hacky”,简单的方法可以做到这一点,然后更优雅,但需要对代码进行重大更改。

Hacky方式

为了尽可能快速和肮脏地实现这一点,我会解析id - s的碎片以检查它们是否处于正确的顺序,因为它们具有这种方便的模式"position" + it's expected index or "blank"

function isFinished() {
    var puzzleEl = document.getElementById('slidingpuzzleContainer').children[0];
    // convert a live list of child elements into regular array
    var pieces = [].slice.call(puzzleEl.children);

    return pieces
        .map(function (piece) {
            return piece.id.substr(8); // strip "position" prefix
        })
        .every(function (id, index, arr) {
            if (arr.length - 1 == index) {
                // last peace, check if it's blank
                return id == "blank";
            }
            // check that every piece has an index that matches its expected position
            return index == parseInt(id);
        });
}

现在我们需要在某处检查它,自然最好的位置是每次移动后,所以shiftPuzzlepieces()应该更新为调用isFinished()函数,并在返回时显示完成消息{{ 1}}:

true

瞧:live version

我将如何实施此游戏

对我来说,实现这个的正确方法是跟踪某些数据结构中片段的当前位置,并以类似的方式检查它,但不遍历DOM或检查节点的id-s。此外,它允许实现类似React.js应用程序的东西:onclick处理程序将改变当前游戏的状态,然后将其呈现到DOM中。

这是我如何实施游戏:

function shiftPuzzlepieces(el) {
    // ...
    if (isFinished()) {
        alert("You won!");
    }
}
/**
 * Provides an initial state of the game
 * with default size 4x4
 */
function initialState() {
  return {
    x: 4,
    y: 4,
    started: false,
    finished: false
  };
}

/**
 * Inits a game
 */
function initGame() {
  var gameContainer = document.querySelector("#slidingpuzzleContainer");
  var gameState = initialState();

  initFormatControl(gameContainer, gameState);
  initGameControls(gameContainer, gameState);

  // kick-off rendering
  render(gameContainer, gameState);
}

/**
 * Handles clicks on the container element
 */
function initGameControls(gameContainer, gameState) {
  gameContainer.addEventListener("click", function hanldeClick(event) {
    if (!gameState.started || gameState.finished) {
      // game didn't started yet or already finished, ignore clicks
      return;
    }
    if (event.target.className.indexOf("piece") == -1) {
      // click somewhere not on the piece (like, margins between them)
      return;
    }

    // try to move piece somewhere
    movePiece(gameState, parseInt(event.target.dataset.index));

    // check if we're done here
    checkFinish(gameState);

    // render the state of game
    render(gameContainer, gameState);

    event.stopPropagation();
    return false;
  });
}

/**
 * Checks whether game is finished
 */
function checkFinish(gameState) {
  gameState.finished = gameState.pieces.every(function(id, index, arr) {
    if (arr.length - 1 == index) {
      // last peace, check if it's blank
      return id == "blank";
    }
    // check that every piece has an index that matches its expected position
    return index == id;
  });
}

/**
 * Moves target piece around if there's blank somewhere near it
 */
function movePiece(gameState, targetIndex) {
  if (isBlank(targetIndex)) {
    // ignore clicks on the "blank" piece
    return;
  }

  var blankPiece = findBlankAround();
  if (blankPiece == null) {
    // nowhere to go :(
    return;
  }

  swap(targetIndex, blankPiece);


  function findBlankAround() {
    var up = targetIndex - gameState.x;
    if (targetIndex >= gameState.x && isBlank(up)) {
      return up;
    }
    var down = targetIndex + gameState.x;
    if (targetIndex < ((gameState.y - 1) * gameState.x) && isBlank(down)) {
      return down;
    }
    var left = targetIndex - 1;
    if ((targetIndex % gameState.x) > 0 && isBlank(left)) {
      return left;
    }
    var right = targetIndex + 1;
    if ((targetIndex % gameState.x) < (gameState.x - 1) && isBlank(right)) {
      return right;
    }
  }

  function isBlank(index) {
    return gameState.pieces[index] == "blank";
  }

  function swap(i1, i2) {
    var t = gameState.pieces[i1];
    gameState.pieces[i1] = gameState.pieces[i2];
    gameState.pieces[i2] = t;
  }
}

/**
 * Handles form for selecting and starting the game
 */
function initFormatControl(gameContainer, state) {
  var formatContainer = document.querySelector("#formatContainer");
  var formatSelect = formatContainer.querySelector("select");
  var formatApply = formatContainer.querySelector("button");

  formatSelect.addEventListener("change", function(event) {
    formatApply.disabled = false;
  });

  formatContainer.addEventListener("submit", function(event) {
    var rawValue = event.target.format.value;
    var value = rawValue.split("x");

    // update state
    state.x = parseInt(value[0], 10);
    state.y = parseInt(value[1], 10);
    state.started = true;
    state.pieces = generatePuzzle(state.x * state.y);

    // render game
    render(gameContainer, state);

    event.preventDefault();
    return false;
  });
}

/**
 * Renders game's state into container element
 */
function render(container, state) {
  var numberOfPieces = state.x * state.y;
  updateClass(container, state.x, state.y);
  clear(container);

  var containerHTML = "";
  if (!state.started) {
    for (var i = 0; i < numberOfPieces; i++) {
      containerHTML += renderPiece("", i) + "\n";
    }
  } else if (state.finished) {
    containerHTML = "<div class='congratulation'><h2 >You won!</h2><p>Press 'Play!' to start again.</p></div>";
  } else {
    containerHTML = state.pieces.map(renderPiece).join("\n");
  }

  container.innerHTML = containerHTML;

  function renderPiece(id, index) {
    return "<div class='piece' data-index='" + index + "'>" + id + "</div>";
  }

  function updateClass(container, x, y) {
    container.className = "slidingpuzzleContainer" + x + "x" + y;
  }

  function clear(container) {
    container.innerHTML = "";
  }
}

/**
 * Generates a shuffled array of id-s ready to be rendered
 */
function generatePuzzle(n) {
  var pieces = ["blank"];
  for (var i = 0; i < n - 1; i++) {
    pieces.push(i);
  }

  return shuffleArray(pieces);

  function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
      var j = Math.floor(Math.random() * (i + 1));
      var temp = array[i];
      array[i] = array[j];
      array[j] = temp;
    }
    return array;
  }
}
body {
  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Helvetica, Arial, sans-serif;
  font-size: 12px;
  color: #000;
}
#formatContainer {
  position: absolute;
  top: 50px;
  left: 500px;
}
#formatContainer label {
  display: inline-block;
  max-width: 100%;
  margin-bottom: 5px;
}
#formatContainer select {
  display: block;
  width: 100%;
  margin-top: 10px;
  margin-bottom: 10px;
}
#formatContainer button {
  display: inline-block;
  width: 100%;
}
.piece {
  width: 96px;
  height: 96px;
  margin: 1px;
  float: left;
  border: 1px solid black;
}
.slidingpuzzleContainer3x3,
.slidingpuzzleContainer3x4,
.slidingpuzzleContainer4x3,
.slidingpuzzleContainer4x4 {
  position: absolute;
  top: 50px;
  left: 50px;
  border: 10px solid black;
}
.slidingpuzzleContainer3x3 {
  width: 300px;
  height: 300px;
}
.slidingpuzzleContainer3x4 {
  width: 300px;
  height: 400px;
}
.slidingpuzzleContainer4x3 {
  width: 400px;
  height: 300px;
}
.slidingpuzzleContainer4x4 {
  width: 400px;
  height: 400px;
}
.congratulation {
  margin: 10px;
}
}

这里我们有<body onload="initGame();"> <div id="slidingpuzzleContainer"></div> <form id="formatContainer"> <label for="format">select format:</label> <select name="format" id="format" size="1"> <option value="" selected="true" disabled="true"></option> <option value="3x3">Format 3 x 3</option> <option value="3x4">Format 3 x 4</option> <option value="4x3">Format 4 x 3</option> <option value="4x4">Format 4 x 4</option> </select> <button type="submit" disabled="true">Play!</button> </form> </body>函数启动一切。调用时,它将创建游戏的初始状态(我们有默认的大小和状态属性来关注那里),在控件上添加侦听器并使用当前状态调用initGame()函数。

render()设置了一个监听器,用于点击该字段,1)调用initGameControls(),如果前者位于某处,将尝试在空白处移动点击的片段,2)检查是否在移动游戏以movePiece()完成,3)使用更新状态调用checkFinish()

现在render()是一个非常简单的函数:它只是获取状态并相应地更新页面上的DOM。

实用程序功能render()处理表单上的点击和更新,以便选择字段大小,以及何时“播放!”按下按钮将生成字段上的片段的初始顺序,并以新状态调用initFormatControl()

这种方法的主要好处是几乎所有的功能都是相互分离的:你可以调整逻辑来寻找目标件周围的空白区域,例如,允许与相邻的ID交换件,甚至然后用于渲染,初始化和点击处理将保持不变。

答案 1 :(得分:0)

    $(document).on('click','.puzzlepiece', function(){
        var count = 0;
         var imgarray = []; 
        var test =[0,1,2,3,4,5,6,7,8,'blank']
        $('#slidingpuzzleContainer img').each(function(i){
          var imgalt =  $(this).attr('alt');             
            imgarray[i] = imgalt;            
            count++;

        });
        var is_same = (imgarray.length == test.length) &&   imgarray.every(function(element, index) {
        return element === array2[index]; 
    });

        console.log(is_same);    ///it will true if two array is same           
    });

尝试这个...这只是3 * 3 ..你传递参数并将数值作为动态传递..