九个谜题游戏在瓷砖对齐上休息



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

我可以在前两次很好地移动瓷砖。但是,在那之后董事会破裂了。

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>

  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)
    

这三个变化使瓷砖如我预期的那样移动。

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>

最新更新