情况GIF:
情况:
完全没有错误。我放入一些单元格,单击“开始”,无论配置如何,它们都消失了。我还尝试了滑翔机配置,它立即消失了。
如果您发现我做错了什么,并且我们能够使“人生游戏”发挥作用,我将在可接受的答案的基础上再给您50英镑的赏金。
更新:
现在,我可以放点,它们会不断发展,但并非像《人生游戏》那样。例如,查看滑翔机配置会发生什么。
这是滑翔机应该如何表现:
这是发生了什么:
有关滑翔机的更多信息:https://en.wikipedia.org/wiki/Glider_(Conway%27s_Life)
码:
游戏
var Game = createReactClass({
getInitialState() {
return {
start: false
}
},
handleStartClick() {
this.setState({
start: true
})
},
handleStopClick() {
this.setState({
start: false
})
},
render() {
return (
<div>
<h1>React.js Game of Life</h1>
<div className="buttons">
<button className="btn btn-danger" onClick={this.handleStopClick}>Stop</button>
<button className="btn btn-success" onClick={this.handleStartClick}>Start</button>
</div>
<Board start={this.state.start}/>
</div>
)
}
});
板
var Board = createReactClass({
getInitialState() {
var array = [];
for (var i = 0; i < 400; i++) {
array.push(<Cell key={i} id={i} cells={array} start={this.props.start} />);
}
return {
cells: array
};
},
render() {
var that = this;
return (
<div className="board">
{
this.state.cells.map(function(item, i) {
return <Cell key={i} id={i} cells={that.state.cells} start={that.props.start}/>
})
}
</div>
);
}
});
细胞
var Cell = createReactClass ({
getInitialState() {
return {
alive: false,
nextAlive: false,
started: false
}
},
componentWillReceiveProps(nextProps) {
var evolution;
if(nextProps.start && this.state.started == false) {
let evolution = setInterval(() => {
this.life();
this.nextLife();
}, 500);
this.setState({
started: true,
evolution
})
}
else {
clearInterval(this.state.evolution);
this.setState({
started: false
})
}
},
isAlive(r, c){
var size = Math.sqrt(this.props.cells.length)
if (r == -1) {
r = size - 1
}
if (r == size) {
r = 0
}
if (c == -1) {
c = size - 1
}
if (c == size) {
c = 0
}
var id = r * size + c
return this.props.cells[id].state.alive
},
life() {
var neighbours = 0
var size = Math.sqrt(this.props.cells.length)
var row = Math.floor( this.props.id / size )
var col = this.props.id - row * size
if (this.isAlive(row - 1, col)) {
neighbours++
}
if (this.isAlive(row - 1, col + 1)) {
neighbours++
}
if (this.isAlive(row - 1, col - 1)) {
neighbours++
}
if (this.isAlive(row, col + 1)) {
neighbours++
}
if (this.isAlive(row, col - 1)) {
neighbours++
}
if (this.isAlive(row + 1, col)) {
neighbours ++
}
if (this.isAlive(row + 1, col + 1)) {
neighbours ++
}
if (this.isAlive(row + 1, col - 1)) {
neighbours ++
}
this.state.nextState = false
if (this.state.alive){
if( neighbours < 2) {
this.setState ({
nextAlive: false
})
}
if (neighbours > 3) {
this.setState ({
nextAlive: false
})
}
if (neighbours == 3 || neighbours == 2) {
this.setState ({
nextAlive: true
})
}
}
else{
if (neighbours == 3) {
this.setState ({
nextAlive: true
})
}
}
},
nextLife () {
this.setState({
alive: this.state.nextAlive
})
},
componentDidMount() {
this.props.cells[this.props.id] = this;
},
toggleLife() {
this.setState({
alive: !this.state.alive
})
},
render() {
return (
<div className={this.state.alive ? "cell alive" : "cell"} onClick={this.toggleLife}></div>
);
}
});
最佳答案
我会分别回答您的更新。
下一个错误更加棘手:您无需任何同步即可独立更新单元。这意味着,根据您的运气,邻居可能会处于完全不同的世代。因此,当您点击开始时得到的是随机的。
为了解决此问题,您需要通过以下方式将裁决代码移动到Board
元素:
var Board = React.createClass({
componentWillReceiveProps(nextProps) { // <- from here ...
var evolution;
if(nextProps.start && this.state.started == false) {
let evolution = setInterval(() => {
this.state.cells.forEach( cell => cell.life() )
this.state.cells.forEach( cell => cell.nextLife() )
}, 500);
this.setState({
started: true,
evolution
})
}
else {
clearInterval(this.state.evolution);
this.setState({
started: false
})
}
}, // <- ... to here
getInitialState() {
var array = [];
for (var i = 0; i < 400; i++) {
array.push(<Cell key={i} id={i} cells={array} start={this.props.start} />);
}
return {
cells: array,
started: false
};
},
render() {
var that = this;
return (
<div className="board">
{
this.state.cells.map(function(item, i) {
return <Cell key={i} id={i} cells={that.state.cells} start={that.props.start}/>
})
}
</div>
);
}
});
然后,您应该从cells元素中删除
componentWillReceiveProps()
:var Cell = createReactClass ({
getInitialState() {
return {
alive: false,
nextAlive: false,
started: false
}
},
componentWillReceiveProps(nextProps) { /* I'm useless now */ },
isAlive(r, c){
var size = Math.sqrt(this.props.cells.length)
if (r == -1) {
r = size - 1
}
if (r == size) {
r = 0
}
if (c == -1) {
c = size - 1
}
if (c == size) {
c = 0
}
var id = r * size + c
return this.props.cells[id].state.alive
},
life() {
var neighbours = 0
var size = Math.sqrt(this.props.cells.length)
var row = Math.floor( this.props.id / size )
var col = this.props.id - row * size
if (this.isAlive(row - 1, col)) {
neighbours++
}
if (this.isAlive(row - 1, col + 1)) {
neighbours++
}
if (this.isAlive(row - 1, col - 1)) {
neighbours++
}
if (this.isAlive(row, col + 1)) {
neighbours++
}
if (this.isAlive(row, col - 1)) {
neighbours++
}
if (this.isAlive(row + 1, col)) {
neighbours ++
}
if (this.isAlive(row + 1, col + 1)) {
neighbours ++
}
if (this.isAlive(row + 1, col - 1)) {
neighbours ++
}
this.state.nextState = false
if (this.state.alive){ // bug 2
if( neighbours < 2) {
this.setState ({
nextAlive: false
})
}
if (neighbours > 3) {
this.setState ({
nextAlive: false
})
}
if (neighbours == 3 || neighbours == 2) {
this.setState ({
nextAlive: true
})
}
}
else{
if (neighbours == 3) {
this.setState ({
nextAlive: true
})
}
}
},
nextLife () {
this.setState({
alive: this.state.nextAlive
})
},
componentDidMount() {
this.props.cells[this.props.id] = this;
},
toggleLife() {
this.setState({
alive: !this.state.alive
})
},
render() {
return (
<div className={this.state.alive ? "cell alive" : "cell"} onClick={this.toggleLife}></div>
);
}
});
另外,您也可以从
started
中删除start
状态和Cell
道具。