我目前正在做一个益智游戏,只是为了好玩。我相信每个人都知道这是如何工作的,所以我可能会跳过解释。
我可以在前两次很好地移动瓷砖。但是,在那之后董事会破裂了。
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>
-
你有两个要隐藏的磁贴的概念:
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"));
.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>