我目前正在制作一款益智游戏,只是为了好玩。我确信每个人都知道这是如何工作的,所以我可能可以跳过解释。
前两次我可以很好地移动一 block 瓷砖。然而,此后电路板就坏了。
idx
属性应指向网格中的位置。 0 表示左上角,8 表示右下角。 x
和 y
坐标基本上是相同的,但我只将它们用于 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>
最佳答案
对于要隐藏哪个图 block ,您有两个概念:
removedTileIdx
和noTileIdx
,还有你的moveTile
功能仅更新noTileIdx
。您实际上应该只使用一个,但为了快速修复,请同时更新两个:this.setState({tilesArr: arr, noTileIdx: selectedIdx}); this.removedTileIdx = selectedIdx;
对于正在考虑的图 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;
同样,同步这两个东西是对正确性的任意限制,最好摆脱它。
您的状况
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/