我是react.js的新手,我开始尝试创建一个简单的Tic-Tac Toe应用程序,但我的逻辑存在问题。
当我在console.log中当前转弯时,我有正确的“X”或“O”字符拼贴。但是,当我在render()函数中调试它时,我得到相反的字符区块(即如果获胜者是“X”,则获胜者在模板上呈现为“O”)。
我尝试在render()函数中交换当前值的值,但它给了我一个错误。关于我在这里做错了什么想法?
我的github回购链接在这里,或者检查代码如下。 https://github.com/jchan922/tic-react-toe/blob/master/src/App.js
谢谢!
编辑:
CodePen
问题澄清
- 即使我的逻辑是其他地方正确的控制台记录,如果获胜者是“X”,则获胜者在视图上呈现为“O”,反之亦然。我无法让我的模板呈现正确的“X”或“O”播放器。
class App extends Component {
// Component Initialization
constructor(props){
super(props)
this.state = {
player_one: "X",
player_two: "O",
currentTurn: "X",
board: [
"", "", "", "", "", "", "", "", ""
],
winner: null,
moveCount: 0
}
}
handleClick(index){
if(this.state.board[index] === "" && !this.state.winner) {
var currentBoard = this.state.board,
count = this.state.moveCount;
currentBoard[index] = this.state.currentTurn;
count += 1;
this.setState({
board: this.state.board,
winner: this.checkForWinner(),
currentTurn: this.state.currentTurn === this.state.player_one ? this.state.player_two : this.state.player_one,
moveCount: count
});
}
}
handleReset(){
console.log("RESET")
this.setState({
player_one: "X",
player_two: "O",
currentTurn: "X",
board: [
"", "", "", "", "", "", "", "", ""
],
winner: null,
moveCount: 0
})
}
checkForWinner(moveCount) {
var currentTurn = this.state.currentTurn;
var symbols = this.state.board;
var winningCombos = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]];
return winningCombos.find(function(combo) {
if(symbols[combo[0]] !== "" && symbols[combo[1]] !== "" && symbols[combo[2]] !== "" && symbols[combo[0]] === symbols[combo[1]] && symbols[combo[1]] === symbols[combo[2]]) {
console.log("Found a winner", currentTurn, [combo[0],combo[1],combo[2]]);
return currentTurn;
}
else {
return null;
}
})
}
// Component Render
render() {
console.log(this.state.currentTurn);
return (
<div className="app-container">
{this.state.winner ? <h2>{`The winner is ${this.state.currentTurn}`}</h2> : null}
<div className="board">
{this.state.board.map((cell, index) => {
return <div onClick={() => this.handleClick(index)} key={index} className="square"><p className="playerSymbol">{cell}</p></div>
})}
</div>
<div className="reset">
<button onClick={() => this.handleReset()} className="resetButton">RESET</button>
</div>
</div>
)
}
}
export default App;
答案 0 :(得分:1)
首先,您不需要在您的州内player_one
和player_two
,只需将它们作为常量,以防您希望player_one
为&#39; O&# 39;有时我更喜欢有一个布尔道具来控制谁先播放并让父组件处理它们(除非App
是唯一呈现的组件但我在UI中看不到任何选择第一个的组件玩)。
其次,因为moveCount
根本没有呈现,为什么你的状态呢?也许你想稍后为它添加一些渲染。
现在问题,让我们假装它是&#39; X&#39;然后,玩家点击获胜的点击,&#39; X&#39;赢了但在此之前,点击会在最后一个语句handleClick
this.setState(...)
等于currentturn
之前触发您的this.state.player_one
函数,这是&#39; X&#39;但你这样做:
this.setState({... , currentturn : this.state.currentturn === this.state.player_one ? this.state.player_two : this.state.player_one,...});
这意味着&#34;如果currentturn是X然后将其设置为O,否则将其设置为X&#34;之后因为状态更改了UI重新呈现currentturn='O'
,现在在你的渲染函数中the winner is {currentturn}
所以它呈现the winner is O
。
解决方案很简单,只需将{currentturn}
替换为{currentturn===player_one ? player_two : player_one}
,只需在声明获胜者的位置进行更改。
以下是codepen的更新:http://codepen.io/abnud1/pen/KajpWN?editors=0010
答案 1 :(得分:0)
例如,如果您想要某种可重用的代码,那么如果有4x4或5x5的木板而不是3x3的木板可以使用的代码,则需要这样的东西
只需生成一个包含X
和O
的矩阵,其中X
将是true
,而O
将是false
https://gist.github.com/Hovakimyan/342d579aa22a567d84d92798bf2667a6
这里的大小将是您的董事会SIZE
,例如3 | 4 | 5...
checkMatrixForWin = (matrix) => {
const angl = [], antiAngl = []
for (let i = 0; i < SIZE; i++) {
let rowvalue = null
for (let j = 0; j < SIZE; j++) {
if (typeof matrix[j][i] !== 'boolean') break
if (j === 0) rowvalue = matrix[j][i]
if (rowvalue !== matrix[j][i]) {
break
}
if (j === SIZE - 1) {
return matrix[j][i]
}
}
angl.push(matrix[i][i])
antiAngl.push(matrix[i][SIZE - 1 - i])
if (matrix[i].every(item => item === matrix[i][0])) {
return matrix[i][0]
}
}
if (angl.every(item => item === angl[0])) {
return angl[0]
}
if (antiAngl.every(item => item === antiAngl[0])) {
return antiAngl[0]
}
}