我目前正在玩益智游戏,只是为了好玩。我相信每个人都知道这是如何工作的,所以我可以跳过解释。
我可以在前两次移动瓷砖。然而,董事会在此之后休息。
idx
属性应指向网格中的位置。左上角为0,右下角为8。 x
和y
坐标基本相同,但我只使用它们进行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>
答案 0 :(得分:1)
您有两个隐藏哪个图块的概念:removedTileIdx
和noTileIdx
,而您的moveTile
函数仅更新noTileIdx
。你应该只使用一个,但为了快速修复,更新两个:
this.setState({tilesArr: arr, noTileIdx: selectedIdx});
this.removedTileIdx = selectedIdx;
您有两个关于您正在考虑的切片阵列中哪个索引的概念:切片对象的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
允许您在隐藏和选定的图块水平相邻时交换,即使在自动换行中也是如此。这不是你想要的。你真的想要
((noTileIdx + 1) % 3 != 0 && (noTileIdx + 1) == selectedIdx) ||
((noTileIdx + 1) % 3 != 1 && (noTileIdx - 1) == selectedIdx)
这三个变化使得瓷砖按预期移动。
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;