单击按钮时尝试更改游戏动作但它不起作用
Trying to change game move when clicked on a button but it doesn't work
我正在 react.js 中构建棋盘游戏,现在我正在尝试添加一项允许用户轻弹游戏的功能。我以为我钉了它,但它不起作用。我检查了我的对象是否是不可变的(它们应该是),我还检查了 return 游戏步骤的函数是否被调用,并且完全没有问题。我不知道为什么它不起作用。我该如何解决?
这是带有游戏数据的构造函数:
constructor(props) {
super(props);
this.state = {
// The Game Data Comes Here
history: [{
squares: [
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null),
[null,null,null,'black','white',null,null,null],
[null,null,null,'white','black',null,null,null],
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null)
]
}],
stepNumber: 0,
blackIsNext: true,
winner: null
}
}
这是我渲染的地方:
render() {
// datas that will be rendered regularly come here
const history = this.state.history
const current = history[this.state.stepNumber]
const moves = history.map((_, move) => {
const desc = move ? 'Go to move #' + move : 'Go to game start';
return (
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
// Return the game scene here
return (
<div className="master-container">
<GameBoard squares={current.squares} onClick={(row,col) => {
if (!this.state.winner) {
const elems = this.checkElementsAround(this.checkEmptySpaces())
for (let el=0;el<elems.length;el++) {
const turning = this.checkTurningStones(elems[el].directions, this.state.blackIsNext)
if (turning.length !== 0) {
turning.unshift([row,col])
if (row === elems[el].coordinates[0] && col === elems[el].coordinates[1]) {
this.handleMove(turning)
this.setWinnerAndTurn()
// Debug
//console.log(history.length)
console.log(moves)
break
}
}
}
}
}}/>
<div>{(!this.state.winner) ? "Player Turn: " + `${(this.state.blackIsNext) ? 'Black' : 'White'}` : 'WINNER: ' + this.state.winner}</div>
<div>{(this.state.winner) ? moves : null}</div>
</div>
)
}
有些函数我就不放了,因为它们所做的几乎无关紧要,它们不会改变数据。而且我也不会放置 setWinnerAndTurn 函数,因为它只在游戏结束或切换玩家回合时定义游戏获胜者,但这里的问题必须与我处理 history
数据的方式有关。
处理移动和跳转到游戏另一步骤的函数
handleMove(cords) {
// You'll return if the game is already over or the value of the square is NOT null
if (this.state.winner) {
return
}
// Handle the recently made move here
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[this.state.stepNumber];
const squares = current.squares.slice()
// You'll handle the click here
for (var i=0;i<cords.length;i++) {
squares[cords[i][0]][cords[i][1]] = (this.state.blackIsNext) ? "black" : "white"
}
this.setState({
history: history.concat([{squares: squares}]),
stepNumber: history.length,
});
}
jumpTo(step) {
this.setState({
stepNumber: step,
blackIsNext: (step % 2) === 0,
});
}
如果您认为在解决问题方面有什么遗漏,请告诉我。
这一行中的赋值操作是组件状态的突变。
squares[cords[i][0]][cords[i][1]] = (this.state.blackIsNext) ? "black" : "white"
这是一个突变,因为 squares
是 this.state
数组的浅表副本。 squares
数组是新的,但正方形内的数组是相同的。
您正在处理深度嵌套的数据,因此很难update without mutation. I would honestly recommend a helper like immer允许您对草稿状态进行赋值操作。
如果没有助手,您必须通过 squares
进行映射并修改内部数组(至少是元素已更改的数组)。我认为这是正确的,但仔细检查我没有混淆行和列。
// Handle the recently made move here
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[this.state.stepNumber];
// Apply changes to every square
const color = this.state.blackIsNext ? "black" : "white";
const nextSquares = current.squares.map((row, y) =>
row.map((square, x) =>
// find if this [x,y] is in the cords array and replace it if it is
cords.some((cord) => cord[0] === x && cord[1] === y) ? color : square
)
);
// Update the state
this.setState({
history: history.concat({ squares: nextSquares }),
stepNumber: history.length
});
我正在 react.js 中构建棋盘游戏,现在我正在尝试添加一项允许用户轻弹游戏的功能。我以为我钉了它,但它不起作用。我检查了我的对象是否是不可变的(它们应该是),我还检查了 return 游戏步骤的函数是否被调用,并且完全没有问题。我不知道为什么它不起作用。我该如何解决?
这是带有游戏数据的构造函数:
constructor(props) {
super(props);
this.state = {
// The Game Data Comes Here
history: [{
squares: [
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null),
[null,null,null,'black','white',null,null,null],
[null,null,null,'white','black',null,null,null],
Array(8).fill(null),
Array(8).fill(null),
Array(8).fill(null)
]
}],
stepNumber: 0,
blackIsNext: true,
winner: null
}
}
这是我渲染的地方:
render() {
// datas that will be rendered regularly come here
const history = this.state.history
const current = history[this.state.stepNumber]
const moves = history.map((_, move) => {
const desc = move ? 'Go to move #' + move : 'Go to game start';
return (
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
// Return the game scene here
return (
<div className="master-container">
<GameBoard squares={current.squares} onClick={(row,col) => {
if (!this.state.winner) {
const elems = this.checkElementsAround(this.checkEmptySpaces())
for (let el=0;el<elems.length;el++) {
const turning = this.checkTurningStones(elems[el].directions, this.state.blackIsNext)
if (turning.length !== 0) {
turning.unshift([row,col])
if (row === elems[el].coordinates[0] && col === elems[el].coordinates[1]) {
this.handleMove(turning)
this.setWinnerAndTurn()
// Debug
//console.log(history.length)
console.log(moves)
break
}
}
}
}
}}/>
<div>{(!this.state.winner) ? "Player Turn: " + `${(this.state.blackIsNext) ? 'Black' : 'White'}` : 'WINNER: ' + this.state.winner}</div>
<div>{(this.state.winner) ? moves : null}</div>
</div>
)
}
有些函数我就不放了,因为它们所做的几乎无关紧要,它们不会改变数据。而且我也不会放置 setWinnerAndTurn 函数,因为它只在游戏结束或切换玩家回合时定义游戏获胜者,但这里的问题必须与我处理 history
数据的方式有关。
处理移动和跳转到游戏另一步骤的函数
handleMove(cords) {
// You'll return if the game is already over or the value of the square is NOT null
if (this.state.winner) {
return
}
// Handle the recently made move here
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[this.state.stepNumber];
const squares = current.squares.slice()
// You'll handle the click here
for (var i=0;i<cords.length;i++) {
squares[cords[i][0]][cords[i][1]] = (this.state.blackIsNext) ? "black" : "white"
}
this.setState({
history: history.concat([{squares: squares}]),
stepNumber: history.length,
});
}
jumpTo(step) {
this.setState({
stepNumber: step,
blackIsNext: (step % 2) === 0,
});
}
如果您认为在解决问题方面有什么遗漏,请告诉我。
这一行中的赋值操作是组件状态的突变。
squares[cords[i][0]][cords[i][1]] = (this.state.blackIsNext) ? "black" : "white"
这是一个突变,因为 squares
是 this.state
数组的浅表副本。 squares
数组是新的,但正方形内的数组是相同的。
您正在处理深度嵌套的数据,因此很难update without mutation. I would honestly recommend a helper like immer允许您对草稿状态进行赋值操作。
如果没有助手,您必须通过 squares
进行映射并修改内部数组(至少是元素已更改的数组)。我认为这是正确的,但仔细检查我没有混淆行和列。
// Handle the recently made move here
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[this.state.stepNumber];
// Apply changes to every square
const color = this.state.blackIsNext ? "black" : "white";
const nextSquares = current.squares.map((row, y) =>
row.map((square, x) =>
// find if this [x,y] is in the cords array and replace it if it is
cords.some((cord) => cord[0] === x && cord[1] === y) ? color : square
)
);
// Update the state
this.setState({
history: history.concat({ squares: nextSquares }),
stepNumber: history.length
});