有一个我不明白的错误。当我按<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'))
&#13;
.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;
}
&#13;
<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>
&#13;
答案 0 :(得分:1)
我认为当您尝试计算边缘上的切片的邻居时会出现问题。因为您正在尝试访问不在网格上的切片,所以循环中的某些变量将变为未定义。我建议添加一个if语句来检查这个。类似的东西:
if(x+i >= 0 && y+i >= 0){
neighbors+=board[x+i][y+j].value
}
答案 1 :(得分:1)
你应该循环直到x和y小于board.length - 2,而不是board.length - 1,因为你正在努力确保它不会评估电路板的边缘。我认为你犯了一个相当常见的错误,就是忘记数组的长度会比你给出的数组的最大索引多一个。
例如,如果其中一行看起来像[4,6,2,3],则其长度为4,但如果您尝试访问行[4],则会得到未定义的行。如果你循环到外部循环中的长度为1,那么你的代码会做什么,然后在内部循环中为每个值添加+1(你这样做是因为你在-1和1之间从i / j循环然后将该值添加到外部索引中。)
另外我认为你已经在内部数组中反转了变量 - 你使用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
}