React Native中setInterval变量重复更新与游戏重启失效问题求助
嘿,我来帮你搞定这两个问题!咱们逐个分析清楚:
问题1:flash变量被意外递增两次
你现在的问题出在play()方法的循环调用+compTurn()里的定时器逻辑上。举个例子,当round=1时,你调用一次compTurn(),这个方法会创建一个每隔1500ms执行的定时器:
- 第一次执行回调时,
flash从0变成1,此时还没触发clearInterval - 等1500ms后第二次执行回调,才会触发
clearInterval,但这时候flash已经被递增到2了!
如果round>1,循环会创建多个独立的setInterval,它们会同时操作同一个flash变量,情况会更混乱。
修复方案:
让compTurn()用单个定时器处理整个回合的闪烁序列,而不是循环调用它;同时每次开始回合前重置flash为0。
问题2:点击START无法重启游戏
游戏结束后,你没有重置关键的游戏状态(比如flash、playerSeq),而且可能还有未清理的旧定时器在后台运行,导致新的游戏逻辑被干扰,看起来像是play()没被调用。
修复方案:
在play()方法开头,先重置所有需要初始化的变量,并且强制清理掉旧的定时器。
修改后的完整代码
export default class App extends Component{ constructor (props){ super(props); this.flash=0 this.round=1 this.seq=[1,2,3,1,4] //will be random, this is just for testing this.playerSeq=[] this.win=false this.ok=true this.score=0 this.intervalId = null; // 新增:存储定时器ID,方便后续清理 this.state = { renderView: false, greenB: { backgroundColor: 'darkgreen' }, yellowB: { backgroundColor: 'orange' }, blueB: { backgroundColor: 'blue' }, redB: { backgroundColor: 'red' } } this.play=this.play.bind(this) this.greenFlash=this.greenFlash.bind(this) this.blueFlash=this.blueFlash.bind(this) this.redFlash=this.redFlash.bind(this) this.compTurn=this.compTurn.bind(this) // 新增:绑定compTurn的this上下文 } play(){ // 重置游戏状态,准备新游戏/新回合 this.flash=0 this.playerSeq=[] this.win=false // 清理旧的定时器,避免新旧定时器冲突 if(this.intervalId){ clearInterval(this.intervalId); this.intervalId = null; } // 单次调用compTurn,让它处理整个回合的闪烁逻辑 this.compTurn(); } playerTurn(){ // 这里写玩家回合的逻辑 } compTurn() { this.intervalId = setInterval(()=> { // 当flash达到round数时,停止定时器 if (this.flash >= this.round) { clearInterval(this.intervalId); this.intervalId = null; // 闪烁完成后切换到玩家回合 // this.playerTurn(); return; } // 用switch替代多个if,逻辑更清晰 switch(this.seq[this.flash]){ case 1: this.greenFlash(); break; case 2: this.yellowFlash(); break; case 3: this.blueFlash(); break; case 4: this.redFlash(); break; default: break; } this.flash++; } , 1500); } greenFlash(){ setTimeout(() => { this.setState( { greenB:{ backgroundColor: 'lightgreen' } }) }, 200); setTimeout(() => { this.setState( { greenB:{ backgroundColor: 'darkgreen' } }) }, 1000); } yellowFlash(){ setTimeout(() => { this.setState( { yellowB:{ backgroundColor: 'yellow' } }) }, 200); setTimeout(() => { this.setState( { yellowB:{ backgroundColor: 'orange' } }) }, 1000); } blueFlash(){ setTimeout(() => { this.setState( { blueB:{ backgroundColor: 'lightblue' } }) }, 200); setTimeout(() => { this.setState( { blueB:{ backgroundColor: 'blue' } }) }, 1000); } redFlash(){ setTimeout(() => { this.setState( { redB:{ backgroundColor: 'pink' } }) }, 200); setTimeout(() => { this.setState( { redB:{ backgroundColor: 'red' } }) }, 1000); } render(){ return ( <View> <TouchableOpacity style={styles.playB} onPress={this.play}> <Text style={{ color:'white', height: 30, width:60, }}>START</Text> </TouchableOpacity> <TouchableOpacity style={[styles.greenB, this.state.greenB]}></TouchableOpacity> <TouchableOpacity style={[styles.yellowB, this.state.yellowB]}></TouchableOpacity> <TouchableOpacity style={[styles.blueB, this.state.blueB]}></TouchableOpacity> <TouchableOpacity style={[styles.redB, this.state.redB]}></TouchableOpacity> </View> ); } } const styles = StyleSheet.create({ greenB:{ padding: 5, height: 80, width: 80, borderRadius:160, }, yellowB:{ padding: 5, height: 80, width: 80, borderRadius:160, }, blueB:{ padding: 5, height: 80, width: 80, borderRadius:160, }, redB:{ padding: 5, height: 80, width: 80, borderRadius:160, }, playB:{ alignSelf: 'center', backgroundColor: 'blue', padding: 10, // 增加padding让按钮更易点击 } });
关键修改点说明:
- 解决flash重复递增:
- 移除
play()里的for循环,改为单次调用compTurn(),让单个定时器处理整个回合的闪烁 - 把停止条件从
this.flash==this.round改成this.flash>=this.round,避免最后一次不必要的递增
- 移除
- 解决重启问题:
- 在
play()开头重置flash、playerSeq等核心状态 - 新增
this.intervalId管理定时器,每次开始游戏前强制清理旧定时器 - 给
compTurn()绑定了this,避免上下文丢失导致的错误
- 在
这样修改后,你应该就能顺利解决这两个问题了!
内容的提问来源于stack exchange,提问作者Shiranox
相关产品推荐
相关产品推荐

