Skip to content

Instantly share code, notes, and snippets.

@zevaverbach
Last active October 1, 2018 01:54
Show Gist options
  • Save zevaverbach/e36fbe1c7ec81e66834f3c4f84e8b62d to your computer and use it in GitHub Desktop.
Save zevaverbach/e36fbe1c7ec81e66834f3c4f84e8b62d to your computer and use it in GitHub Desktop.
Conway's Game of Life implemented in a single file using React.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title></head>
<body>
<script src="https://unpkg.com/react@16.5.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.5.2/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script>
<script type="text/babel">
const sum = (nums) => nums.reduce((total, i) => total + i);
const generation = (rows) => {
const numRows = rows.length;
const numCols = rows[0].length;
const newState = [];
for (let row = 0; row < numRows; row++) {
const newRow = [];
for (let col = 0; col < numCols; col++) {
let currentState = rows[row][col];
let newCell = nextState(currentState, row, col, rows);
newRow.push(newCell);
}
newState.push(newRow);
}
return newState;
};
const nextState = (currentState, rowNum, colNum, rows) => {
const neighborsTotal = sum(getNeighbors(rowNum, colNum, rows).map(neighbor => neighbor ? 1 : 0));
if (neighborsTotal === 3) {
return true;
}
if (neighborsTotal >= 4
|| neighborsTotal < 2) {
return false
}
return currentState;
};
const getNeighbors = (rowNum, colNum, rows) => {
const neighbors = [];
for (let r of [rowNum - 1, rowNum, rowNum + 1]) {
if (rows[r] === undefined) {
continue;
}
for (let c of [colNum - 1, colNum, colNum + 1]) {
if (rows[r][c] === undefined) {
continue;
}
if (r === rowNum && c === colNum) {
continue;
}
neighbors.push(rows[r][c])
}
}
return neighbors;
};
class Board extends React.Component {
state = {rows: Array.from({length: this.props.numRows}, () => Array.from({length: this.props.numCols}, () => Math.round(Math.random()) === 1))};
componentDidMount() {
this.interval = setInterval(() => this.setState({rows: generation(this.state.rows)}), 100);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return <table>
<tbody>
{Array.from(this.state.rows).map((row, index) => <Row height={screen.height / (Math.round(this.props.numRows * 1.15))}
key={index}
cells={row}/>)}
</tbody>
</table>
}
}
const Row = (props) => {
return <tr>
{Array.from(props.cells).map((cell, index) => <Cell height={props.height}
width={screen.width / props.cells.length}
key={index}
alive={cell}/>)}
</tr>;
};
const Cell = (props) => {
return <td style={{height: props.height, width: props.width, backgroundColor: props.alive ? '#333' : '#DDD'}}></td>
};
ReactDOM.render(<Board numRows={30} numCols={45}/>,
document.getElementById('root'));
</script>
<div id="root"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment