我正在使用React.js开发生命游戏。到目前为止一切都有效,但我想添加额外的功能,这将允许停止游戏(周期)并在需要时恢复它。我不知道怎么办呢。所以在主类中我有一个方法/函数来启动游戏,并在单击render()中定义的按钮后触发:
constructor(props) {
super(props);
this.state = {cellStates: Array(TOTAL_FIELDS).fill(0), cellID: Array(TOTAL_FIELDS), gameRunning: false, counter: 0}; //set and fill initial states
this.changeState = this.changeState.bind(this);
this.resetGame = this.resetGame.bind(this);
this.startGame = this.startGame.bind(this);
this.stopGame = this.stopGame.bind(this);
this.showGameStatus = this.showGameStatus.bind(this);
for (let o = 1; o <= TOTAL_FIELDS; o++)
{
this.state.cellID[o-1] = o;
}
}
startGame() {
function checkZeros(arr) { //check if board is blank
return arr === 0;
}
if (!this.state.cellStates.every(checkZeros)) {
alert ('Game starts!');
let cycle = this.state.counter; //define number of life cycle
this.setState(() => {
return {
gameRunning: true //game is on
};
});
$('#reset-button').attr("disabled", "disabled");
$('#start-button').attr("disabled", "disabled");
$('#stop-button').removeAttr("disabled"); //handle buttons
let goGame = setInterval(() => {
const newStates = [];
for (let x = 0; x < TOTAL_FIELDS; x++) {
if (this.state.cellStates[x] === 0) { //cell is dead
if (this.calculateCellsAround(x) === 3)
{
newStates.push(1);
}
else {
newStates.push(this.state.cellStates[x]);
}
}
else { //cell is alive
if (this.calculateCellsAround(x) === 3 || this.calculateCellsAround(x) === 2)
{
newStates.push(this.state.cellStates[x]);
}
else {
newStates.push(0);
}
}
}
this.setState(() => {
return {cellStates: newStates, counter: cycle++};
});
}, 50);
}
else {
alert ("Please fill at least one cell to launch a game.")
}
}
render() {
return (
<div style={{marginTop:0+"px"}} key="wrap-it-all">
<Header />
<Grid>
<Row>
<Col md={12}>
<div className="board-outline">
{this.createMap(140, TOTAL_FIELDS)}
</div>
</Col>
</Row>
<Row>
<Col md={12}>
<button id="start-button" onClick={() => this.startGame()}>Start</button>
<button id="stop-button" onClick={() => this.stopGame()}>Stop</button>
<button id="reset-button" onClick={() => this.resetGame()}>Reset</button>
<p style={{color:`#fff`}}>Lifecycle: <span className="lifecycle">{this.state.counter}</span>. Game is <span className="gamerun">{this.showGameStatus()}</span>.</p>
<Alert className="disclaimer" bsStyle="warning">
<strong>Instruction:</strong> Select the initial state of cells and press the [Start] button.
</Alert>
</Col>
</Row>
</Grid>
</div>
);
}
我认为这一切与mount / unmount内置函数有关,但我不知道如何使用它们以使它全部工作。
答案 0 :(得分:3)
您需要在停止时使用clearInterval(handle)
取消间隔。
如果您想继续,请再次使用setInterval(callback, tick)
。
此外,只需将您的匿名函数(又名setInterval(() => {...}
)更改为
function onTimerTick() {
//copy everything marked as "..." here
}
并使用setInterval(onTimerTick, 50)
。
答案 1 :(得分:0)
您可以尝试将局部变量(让goGame)更改为全局变量(this._timer),然后可以通过clearInterval(this._timer)取消间隔
答案 2 :(得分:0)
您可以做这样的事情
let intervalHandle: NodeJS.Timeout = null;
const startIntervalTask = () => {
intervalHandle = setInterval(() => {
// execute this code after every 5000 miliseconds
}, 5000);
};
const stopIntervalTask = ()=>{
clearInterval(intervalHandle);
}