[英]What is going wrong on this line of code? (React, Game Of Life)
有一個我不明白的錯誤。 當我按下<button>50x70</button>
並按下<button>run</button>
此錯誤。 我不明白為什么,因為它可以與標准50x50板一起使用。
為什么這行代碼會導致錯誤? neighbors+=board[x+i][y+j].value
https://codepen.io/anon/pen/OjoZKX
TypeError: Cannot read property '0' of undefined
evaluateGen
C:/Www/Projects/gameoflife/src/App.js:65
62 |
63 | for(let i=-1; i <= 1; i++){
64 | for(let j=-1; j<= 1; j++){
> 65 | neighbors+=board[x+i][y+j].value
66 | }
67 | }
68 | neighbors-=board[x][y].value
View compiled
(anonymous function)
C:/Www/Projects/gameoflife/src/App.js:108
105 |
106 | run(){
107 | this.interval = setInterval(() => {
> 108 | const nextState = evaluateGen(this.state.board)
109 | this.setState({paused: false, generation: this.state.generation + 1, board: nextState})
110 | }, 50)
111 | }
// creates the board with random 1/0 value. const createBoard = function(width, height) { let board = [] for(var x = 0; x < width; x++){ board.push([]) for(var y = 0; y < height; y++){ if(x === 0 || y === 0) { board[x].push({value: 0}) } else if (x === width-1 || y === height-1){ board[x].push({value: 0}) } else { let number = Math.round(Math.random()) board[x].push({value: number}) } } } return board } // Game Of Life rules. const evaluateCell = function(x, cell){ let value = x if(x < 2){ value = 0 } else if(x === 2){ value = cell } else if(x === 3){ value = 1 } else if(x > 3){ value = 0 } else { console.log('error: default case evaluateCell()') value = 0 } return value } // evaluates a generation of board state by going through each cell and counting neighbors and calling evaluateCell accordingly. const evaluateGen = function(board){ let nextGen = JSON.parse(JSON.stringify(board)); for(let y = 1; y < board.length - 1; y++){ for(let x = 1; x < board[y].length - 1; x++){ let neighbors = 0 for(let i=-1; i <= 1; i++){ for(let j=-1; j<= 1; j++){ neighbors+=board[x+i][y+j].value } } // remove current cell from neighbors. neighbors-=board[x][y].value let nextvalue = evaluateCell(neighbors, board[x][y].value) nextGen[x][y].value = nextvalue } } return nextGen } class App extends React.Component { constructor(){ super() this.state = { width: 50, height: 50, board: createBoard(50, 50), paused: false, generation: 0 } } generateBoard(width, height) { this.pause() const board = createBoard(width, height) this.setState({board, generation: 0, width, height }) } pause(){ clearInterval(this.interval) this.setState({paused: true}) } run(){ this.interval = setInterval(() => { const nextState = evaluateGen(this.state.board) this.setState({paused: false, generation: this.state.generation + 1, board: nextState}) }, 50) } componentDidMount() { this.run() } componentWillUnmount() { clearInterval(this.interval) } render() { let {board, generation, width, height} = this.state return ( <div className="App"> <h3>generation:{generation}</h3> {board.map(x => x.map(item => { return ( <div className={`state-${item.value}`}></div> ) }))} <button onClick={()=> this.run()}>run</button> <button onClick={()=> this.pause()}>pause </button> <button onClick={()=> this.generateBoard(width, height)}>generate</button> <button onClick={()=> this.generateBoard(50, 70)}>50 x 70</button> </div> ); } } ReactDOM.render(<App />, document.getElementById('root'))
.App div { width: 10px; height: 10px; outline: 1px solid black; } .App { display: flex; flex-wrap: wrap; width: 500px; height: 500px; } .state-1{ background-color: red; }
<div id='root'></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
我認為當您嘗試計算邊緣上的圖塊的鄰居時會出現問題。 因為您正在嘗試訪問不在網格上的圖塊,所以循環中的某些變量變得不確定。 我建議添加一個if語句來檢查這一點。 就像是:
if(x+i >= 0 && y+i >= 0){
neighbors+=board[x+i][y+j].value
}
您應該一直循環播放,直到x和y小於board.length-2,而不是board.length-1,因為您試圖確保它不會評估木板的邊緣。 我認為您犯了一個相當普遍的錯誤,即忘記了數組的長度會比數組的最大索引多一個。
例如,如果其中一行看起來像[4,6,2,3],則其.length為4,但是如果您嘗試訪問row [4],則會得到未定義。 如果循環直到外循環中的長度為1,然后再向內循環中的每個值加+1,則代碼將執行此操作(因為從i / j在-1與1之間循環,然后將該值添加到外部索引中)。
另外,我認為您已經在內部數組中反轉了這些變量-您在外部循環中使用y
作為行循環變量,在循環中使用x
作為列循環變量,但在內部循環中將它們反轉。 因此,如果不是正方形,它將最終碰到不存在的行。
您的總體代碼應如下所示:
const evaluateGen = function(board){
let nextGen = JSON.parse(JSON.stringify(board));
for(let x = 1; x < board.length - 2; x++){
for(let y = 1; y < board[y].length - 2; y++){
let neighbors = 0
for(let i=-1; i <= 1; i++){
for(let j=-1; j<= 1; j++){
neighbors+=board[x+i][y+j].value
}
}
// remove current cell from neighbors.
neighbors-=board[x][y].value
let nextvalue = evaluateCell(neighbors, board[x][y].value)
nextGen[x][y].value = nextvalue
}
}
return nextGen
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.