Game of Life with React Native easy grid
Kacha
Posted on August 31, 2018
I have been learning react native over the past month or two and I decided as a way to learn and familiarise myself with it by making some fun little projects.
For my first project I created Conway's Game of Life using react native easy grid and create-react-native-app. First create a CRNA app and install the grid library.
create-react-native-app GameOfLife && cd GameOfLife
npm install react-native-easy-grid
Then in App.js import easy grid and create the following class:
import React from 'react';
import { StyleSheet, View} from 'react-native';
import {Col, Row, Grid} from 'react-native-easy-grid';
export default class App extends React.Component {
gridNum = 40; // The number of rows and columns in our grid
constructor(props){
super(props);
let newBoard = this.setupBoard()
this.state = {
board: newBoard
}
}
setupBoard = () => {
// Create a two dimensional array to represent the grid
let board = new Array(this.gridNum)
for (i = 0; i < this.gridNum; i++){
board[i] = new Array(this.gridNum)
}
for(x=0; x< this.gridNum; x++){
for(y=0; y < this.gridNum; y++){
// Creates a grid square object that holds a random number
// between 0 for a dead cell and 1 for alive
// n represents the number of neighbours a cell has
board[x][y] = {
cell:Math.floor(Math.random()*2),
n:0
}
}
}
return board
}
render(){
return(
<Grid>
// Code To be Done
</Grid>
);
}
}
The above code sets up the board, then I created two functions:
To check for the number of neighbours each cell has and,
A function to get the next generation of cells.
checkNeighbours = () => {
let oldBoard = this.state.board
// Ignores the columns and rows on the outermost edges
for(x=1; x< this.gridNum-1; x++){
for(y=1; y < this.gridNum-1; y++){
\\ For every grid cell check how many neighbours it has
for(i=-1; i< 2; i++){
for(j=-1; j < 2; j++){
oldBoard[x][y].n += oldBoard[(x+i)][(y+j)].cell
}
}
\\ Delete the value of the current cell as it was counted in
\\ the above calculation
oldBoard[x][y].n -= oldBoard[x][y].cell
}
}
this.setState({board: oldBoard})
}
newBoard = () => {
let oldBoard = this.state.board
let board = this.setupBoard()
// Set all new board values to zero
for(let a = 0; a < this.gridNum; a++){
for(let b=0; b<this.gridNum;b++){
board[a][b] = {cell:0, n:0}
}
}
for(x=1; x< this.gridNum-1; x++){
for(y=1; y < this.gridNum-1; y++){
if((oldBoard[x][y].cell == 1) && oldBoard[x][y].n < 2){
board[x][y].cell = 0
} else if((oldBoard[x][y].cell == 1) && oldBoard[x][y].n > 3){
board[x][y].cell = 0
} else if((oldBoard[x][y].cell == 0) && oldBoard[x][y].n == 3)
{
board[x][y].cell = 1
} else if((oldBoard[x][y].cell == 1)&& (oldBoard[x][y].n == 3
|| oldBoard[x][y].n == 2)){
board[x][y].cell = 1
} else{
board[x][y].cell = oldBoard[x][y].cell
}
}
}
this.setState({board: board})
}
For the game of life to update these two functions above must be called continuously. For this I created a helper function called "run" and used setInterval() to have it called every second.
constructor(props){
... // Above code skipped for brevity
setInterval(this.run, 1000);
}
run = () => {
this.checkNeighbours()
this.newBoard()
}
Finally I render the grid to the screen.
render(){
return(
<Grid>
{this.state.board.map((row, key)=>{
return <Col key={key}>{row.map((cell, key)=>{
return <Row style=
// If cell is 1(alive) render a color there
{{backgroundColor:cell.cell==1?'#00FFFF':'#FFF',
margin:1}} key={key}></Row>
})}</Col>
})}
</Grid>
);
}
I know this could probably be done more elegantly in something like three.js but it was a fun experiment. Here is a link to the Github repository. And the final product (which has been sped up slightly).
Posted on August 31, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.