javascript - 九谜游戏在瓷砖对齐上中断

标签 javascript

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

前两次我可以很好地移动一 block 瓷砖。然而,此后电路板就坏了。

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

随机选择一 block 图 block ,但不进行渲染。我的想法是,将您点击的图 block 的坐标和 idx 与隐藏的图 block 交换。然而,它并没有像预期的那样工作,经过几个小时的搜索,我想我需要一双新的眼睛来帮助我发现我的错误。

问题是当你点击一个图 block 来移动它时,所以在 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. 对于要隐藏哪个图 block ,您有两个概念:removedTileIdxnoTileIdx ,还有你的moveTile功能仅更新 noTileIdx 。您实际上应该只使用一个,但为了快速修复,请同时更新两个:

    this.setState({tilesArr: arr, noTileIdx: selectedIdx});
    this.removedTileIdx = selectedIdx;
    
  2. 对于正在考虑的图 block 数组中的索引,您有两个概念:图 block 对象的 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
    

    允许您在隐藏和选定的图 block 水平相邻时交换它们,即使是在自动换行的意义上。这不是你想要的。你真的想要

    ((noTileIdx + 1) % 3 != 0 && (noTileIdx + 1) == selectedIdx) ||
    ((noTileIdx + 1) % 3 != 1 && (noTileIdx - 1) == selectedIdx)
    

这三项更改使图 block 按照我的预期移动。

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"));
.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>

关于javascript - 九谜游戏在瓷砖对齐上中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45022620/

相关文章:

javascript - 如何在不加载页面的情况下为空白选项卡设置 URL?

javascript - 用对象初始化循环数组

php - Ajax 到 php 调用不成功

JavaScript 用 HTML 替换文本不起作用?

javascript - WebGL 帧缓冲区为空白

javascript - 在 JavaScript 中实现图像

javascript - 表单提交后在 Node.js 中发送响应的有效方法

javascript - THREE.JS - Vector3.project 返回奇怪的结果

javascript - React - 状态包含对象数组。带条件的 setState

javascript - 是否可以使用用户的视频卡在浏览器中计算 sha256 哈希值,例如。通过使用 WebGL 或 Flash?