瓷砖对齐上的九拼图游戏中断

时间:2017-07-10 22:29:37

标签: javascript

我目前正在玩益智游戏,只是为了好玩。我相信每个人都知道这是如何工作的,所以我可以跳过解释。

我可以在前两次移动瓷砖。然而,董事会在此之后休息。

idx属性应指向网格中的位置。左上角为0,右下角为8。 xy坐标基本相同,但我只使用它们进行css定位。

拾取随机图块并且不呈现。我的想法是,我用隐藏的瓷砖交换你点击的瓷砖的坐标和idx。然而,它没有按预期工作,经过几个小时的搜索,我想我需要一双新眼睛来帮助我发现我的错误。

问题是当你点击一个瓷砖移动它时,所以moveTile()中的某个地方......

class NinePuzzle extends React.Component {
    constructor() {
    super();
    let q = [["0% 0%"], ["0% 50%"], ["0% 100%"], ["50% 0%"], ["50% 50%"], ["50% 100%"], ["100% 0%"], ["100% 50%"], ["100% 100%"]];
    this.removedTileIdx = Math.floor(Math.random() * 9);
    this.state = {
    	bg: "https://media.wired.com/photos/595693e45992c54331ac2031/1:1/w_2400,c_limit/Porsche911_HP.jpg",
      tilesArr: [
      	{idx: 0, bgPos: q.splice(Math.floor(Math.random()*9), 1)[0], x: 0, y: 0},
        {idx: 1, bgPos: q.splice(Math.floor(Math.random()*8), 1)[0], x: 33.333, y: 0},
        {idx: 2, bgPos: q.splice(Math.floor(Math.random()*7), 1)[0], x: 66.666, y: 0},
        {idx: 3, bgPos: q.splice(Math.floor(Math.random()*6), 1)[0], x: 0, y: 33.333},
        {idx: 4, bgPos: q.splice(Math.floor(Math.random()*5), 1)[0], x: 33.333, y: 33.333},
        {idx: 5, bgPos: q.splice(Math.floor(Math.random()*4), 1)[0], x: 66.666, y: 33.333},
        {idx: 6, bgPos: q.splice(Math.floor(Math.random()*3), 1)[0], x: 0, y: 66.666},
        {idx: 7, bgPos: q.splice(Math.floor(Math.random()*2), 1)[0], x: 33.333, y: 66.666},
        {idx: 8, bgPos: q.splice(Math.floor(Math.random()*1), 1)[0], x: 66.666, y: 66.666},
      ],
      noTileIdx: this.removedTileIdx,
    };
  }
  
  moveTile = (selectedIdx) => {
  	let flag = false;
  	let {noTileIdx} = this.state;
  	let arr = this.state.tilesArr.slice();
    
    let selectedTile = Object.assign({}, arr[selectedIdx]);
    let hiddenTile = Object.assign({}, arr[noTileIdx]);
    
    let hX = hiddenTile.x;
    let hY = hiddenTile.y;
    
    if(noTileIdx+1 == selectedIdx || noTileIdx-1 == selectedIdx) {
    	hiddenTile.x = selectedTile.x;
      selectedTile.x = hX;
      flag = true;
    } else if(noTileIdx+3 == selectedIdx || noTileIdx-3 == selectedIdx) {
    	hiddenTile.y = selectedTile.y;
      selectedTile.y = hY;
      flag = true;
    }
    if(!flag) return;
    
    selectedTile.idx = noTileIdx;    
    hiddenTile.idx = selectedIdx;

    arr[selectedIdx] = selectedTile;    
    arr[noTileIdx] = hiddenTile;
    
    this.setState({tilesArr: arr, noTileIdx: selectedIdx});
  }
  
  render() {
  	return(
    	<div className="board">
        {this.state.tilesArr.map(
        	(item, i) => {
          	if(i === this.removedTileIdx) return null;
          	return (
            	<div
                key={item.idx}
                onClick={this.moveTile.bind(this, item.idx)}
                style={{
                	backgroundImage: "url('"+ this.state.bg +"')",
                	backgroundPosition: item.bgPos,
                	left: item.x + "%",
                	top: item.y + "%"
              	}}
              />
            );
          }
        )}
    	</div>
    );
  }
}

ReactDOM.render(<NinePuzzle />, document.getElementById("app"));
.board {
  width: 300px;
  height: 300px;
  border: 3px solid #5F5F22;
  border-radius: 5px;
  background-color: #FFFFC2;
  line-height: 0;
  position: relative;
}

.board div {
  width: 100px;
  height: 100px;
  display: inline-block;
  background-size: 300px;
  position: absolute;
  transition: top .25s, left .25s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

1 个答案:

答案 0 :(得分:1)

  1. 您有两个隐藏哪个图块的概念:removedTileIdxnoTileIdx,而您的moveTile函数仅更新noTileIdx。你应该只使用一个,但为了快速修复,更新两个:

    this.setState({tilesArr: arr, noTileIdx: selectedIdx});
    this.removedTileIdx = selectedIdx;
    
  2. 您有两个关于您正在考虑的切片阵列中哪个索引的概念:切片对象的idx属性及其在数组中的实际位置。更新第二个的方式是向后的。而不是

    selectedTile.idx = noTileIdx;    
    hiddenTile.idx = selectedIdx;
    
    arr[selectedIdx] = selectedTile;
    arr[noTileIdx] = hiddenTile;
    

    你想要

    selectedTile.idx = noTileIdx;    
    hiddenTile.idx = selectedIdx;
    
    arr[selectedIdx] = hiddenTile;    
    arr[noTileIdx] = selectedTile;
    

    同样,同步这两件事是对正确性的任意约束,并且最好摆脱它。

  3. 您的情况

    noTileIdx+1 == selectedIdx || noTileIdx-1 == selectedIdx
    

    允许您在隐藏和选定的图块水平相邻时交换,即使在自动换行中也是如此。这不是你想要的。你真的想要

    ((noTileIdx + 1) % 3 != 0 && (noTileIdx + 1) == selectedIdx) ||
    ((noTileIdx + 1) % 3 != 1 && (noTileIdx - 1) == selectedIdx)
    
  4. 这三个变化使得瓷砖按预期移动。

    &#13;
    &#13;
    class NinePuzzle extends React.Component {
        constructor() {
        super();
        let q = [["0% 0%"], ["0% 50%"], ["0% 100%"], ["50% 0%"], ["50% 50%"], ["50% 100%"], ["100% 0%"], ["100% 50%"], ["100% 100%"]];
        this.removedTileIdx = Math.floor(Math.random() * 9);
        this.state = {
        	bg: "https://media.wired.com/photos/595693e45992c54331ac2031/1:1/w_2400,c_limit/Porsche911_HP.jpg",
          tilesArr: [
          	{idx: 0, bgPos: q.splice(Math.floor(Math.random()*9), 1)[0], x: 0, y: 0},
            {idx: 1, bgPos: q.splice(Math.floor(Math.random()*8), 1)[0], x: 33.333, y: 0},
            {idx: 2, bgPos: q.splice(Math.floor(Math.random()*7), 1)[0], x: 66.666, y: 0},
            {idx: 3, bgPos: q.splice(Math.floor(Math.random()*6), 1)[0], x: 0, y: 33.333},
            {idx: 4, bgPos: q.splice(Math.floor(Math.random()*5), 1)[0], x: 33.333, y: 33.333},
            {idx: 5, bgPos: q.splice(Math.floor(Math.random()*4), 1)[0], x: 66.666, y: 33.333},
            {idx: 6, bgPos: q.splice(Math.floor(Math.random()*3), 1)[0], x: 0, y: 66.666},
            {idx: 7, bgPos: q.splice(Math.floor(Math.random()*2), 1)[0], x: 33.333, y: 66.666},
            {idx: 8, bgPos: q.splice(Math.floor(Math.random()*1), 1)[0], x: 66.666, y: 66.666},
          ],
          noTileIdx: this.removedTileIdx,
        };
      }
      
      moveTile = (selectedIdx) => {
      	let flag = false;
      	let {noTileIdx} = this.state;
      	let arr = this.state.tilesArr.slice();
        
        let selectedTile = Object.assign({}, arr[selectedIdx]);
        let hiddenTile = Object.assign({}, arr[noTileIdx]);
        
        let hX = hiddenTile.x;
        let hY = hiddenTile.y;
        
        if(((noTileIdx + 1) % 3 != 0 && (noTileIdx + 1) == selectedIdx) ||
    ((noTileIdx + 1) % 3 != 1 && (noTileIdx - 1) == selectedIdx)) {
        	hiddenTile.x = selectedTile.x;
          selectedTile.x = hX;
          flag = true;
        } else if(noTileIdx+3 == selectedIdx || noTileIdx-3 == selectedIdx) {
        	hiddenTile.y = selectedTile.y;
          selectedTile.y = hY;
          flag = true;
        }
        if(!flag) return;
        
        selectedTile.idx = noTileIdx;    
        hiddenTile.idx = selectedIdx;
    
        arr[selectedIdx] = hiddenTile;    
        arr[noTileIdx] = selectedTile;
        
        this.removedTileIdx = selectedIdx;
        this.setState({tilesArr: arr, noTileIdx: selectedIdx});
      }
      
      render() {
      	return(
        	<div className="board">
            {this.state.tilesArr.map(
            	(item, i) => {
              	if(i === this.removedTileIdx) return null;
              	return (
                	<div
                    key={item.idx}
                    onClick={this.moveTile.bind(this, item.idx)}
                    style={{
                    	backgroundImage: "url('"+ this.state.bg +"')",
                    	backgroundPosition: item.bgPos,
                    	left: item.x + "%",
                    	top: item.y + "%"
                  	}}
                  />
                );
              }
            )}
        	</div>
        );
      }
    }
    
    ReactDOM.render(<NinePuzzle />, document.getElementById("app"));
    &#13;
    .board {
      width: 300px;
      height: 300px;
      border: 3px solid #5F5F22;
      border-radius: 5px;
      background-color: #FFFFC2;
      line-height: 0;
      position: relative;
    }
    
    .board div {
      width: 100px;
      height: 100px;
      display: inline-block;
      background-size: 300px;
      position: absolute;
      transition: top .25s, left .25s;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="app"></div>
    &#13;
    &#13;
    &#13;