there is an error which I don't understand. When I press <button>50x70</button>
and press <button>run</button>
I get this error.
I can't see why, since it works with the standard 50x50 board.
Why is this line of code causing an error? 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>