From 9839021bee2b248f180f62345914e0a9da3188e9 Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Mon, 19 Oct 2020 20:44:03 -0700 Subject: [PATCH 1/9] app is mostly working, game of life functional --- game-of-life/.gitignore | 23 +++++ game-of-life/README.md | 68 ++++++++++++++ game-of-life/package.json | 34 +++++++ game-of-life/public/index.html | 43 +++++++++ game-of-life/src/App.js | 157 +++++++++++++++++++++++++++++++++ game-of-life/src/index.js | 10 +++ 6 files changed, 335 insertions(+) create mode 100644 game-of-life/.gitignore create mode 100644 game-of-life/README.md create mode 100644 game-of-life/package.json create mode 100644 game-of-life/public/index.html create mode 100644 game-of-life/src/App.js create mode 100644 game-of-life/src/index.js diff --git a/game-of-life/.gitignore b/game-of-life/.gitignore new file mode 100644 index 000000000..4d29575de --- /dev/null +++ b/game-of-life/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/game-of-life/README.md b/game-of-life/README.md new file mode 100644 index 000000000..9c40dcdc3 --- /dev/null +++ b/game-of-life/README.md @@ -0,0 +1,68 @@ +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `yarn start` + +Runs the app in the development mode.
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
+You will also see any lint errors in the console. + +### `yarn test` + +Launches the test runner in the interactive watch mode.
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `yarn build` + +Builds the app for production to the `build` folder.
+It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
+Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `yarn eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). + +### Code Splitting + +This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting + +### Analyzing the Bundle Size + +This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size + +### Making a Progressive Web App + +This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app + +### Advanced Configuration + +This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration + +### Deployment + +This section has moved here: https://facebook.github.io/create-react-app/docs/deployment + +### `yarn build` fails to minify + +This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify diff --git a/game-of-life/package.json b/game-of-life/package.json new file mode 100644 index 000000000..b43804fc4 --- /dev/null +++ b/game-of-life/package.json @@ -0,0 +1,34 @@ +{ + "name": "game-of-life", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/react": "^9.3.2", + "@testing-library/user-event": "^7.1.2", + "react": "^16.14.0", + "react-dom": "^16.14.0", + "react-scripts": "3.4.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/game-of-life/public/index.html b/game-of-life/public/index.html new file mode 100644 index 000000000..aa069f27c --- /dev/null +++ b/game-of-life/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/game-of-life/src/App.js b/game-of-life/src/App.js new file mode 100644 index 000000000..3298303b0 --- /dev/null +++ b/game-of-life/src/App.js @@ -0,0 +1,157 @@ +import React, { useState, useCallback, useRef } from "react"; +import produce from "immer"; + +const numRows = 25; +const numCols = 25; + +const operations = [ + [0, 1], + [0, -1], + [1, -1], + [-1, 1], + [1, 1], + [-1, -1], + [1, 0], + [-1, 0] +]; + +const generateEmptyGrid = () => { + const rows = []; + for (let i = 0; i < numRows; i++) { + rows.push(Array.from(Array(numCols), () => 0)); + } + + return rows; +}; + +function App () { + const [grid, setGrid] = useState(() => { + return generateEmptyGrid(); + }); + + const [generation, setGeneration] = useState(0) + + const [color, setColor] = useState('orange') + + const [running, setRunning] = useState(false); + + const runningRef = useRef(running); + runningRef.current = running; + + const incrementGen = () => { + setGeneration(generation + 1) + setInterval(incrementGen, 700) + } + + + const runSimulation = useCallback(() => { + if (!runningRef.current) { + return; + } + + setGrid(g => { + return produce(g, gridCopy => { + for (let i = 0; i < numRows; i++) { + for (let k = 0; k < numCols; k++) { + let neighbors = 0; + operations.forEach(([x, y]) => { + const newI = i + x; + const newK = k + y; + if (newI >= 0 && newI < numRows && newK >= 0 && newK < numCols) { + neighbors += g[newI][newK]; + } + }); + + if (neighbors < 2 || neighbors > 3) { + gridCopy[i][k] = 0; + } else if (g[i][k] === 0 && neighbors === 3) { + gridCopy[i][k] = 1; + } + } + } + }); + }); + + incrementGen(); + + setTimeout(runSimulation, 700); + }, []); + + + return ( + <> +

Generations: {generation}

+ + + +
+ {grid.map((rows, i) => + rows.map((col, k) => ( +
{ + const newGrid = produce(grid, gridCopy => { + gridCopy[i][k] = grid[i][k] ? 0 : 1; + }); + setGrid(newGrid); + }} + style={{ + width: 20, + height: 20, + backgroundColor: grid[i][k] ? color : undefined, + border: "solid 1px black" + }} + /> + )) + )} +
+ + + + ); +}; + +export default App; \ No newline at end of file diff --git a/game-of-life/src/index.js b/game-of-life/src/index.js new file mode 100644 index 000000000..c1f31c5f4 --- /dev/null +++ b/game-of-life/src/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); From 13965bfbeb9774365b13001d1f8a2869dba01b88 Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Tue, 20 Oct 2020 18:18:39 -0700 Subject: [PATCH 2/9] commiting reverts for review --- game-of-life/src/App.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/game-of-life/src/App.js b/game-of-life/src/App.js index 3298303b0..c42c77ae6 100644 --- a/game-of-life/src/App.js +++ b/game-of-life/src/App.js @@ -38,11 +38,13 @@ function App () { const runningRef = useRef(running); runningRef.current = running; - const incrementGen = () => { - setGeneration(generation + 1) - setInterval(incrementGen, 700) - } - + const incrementGen = useCallback(() => { + setGeneration(gen => { + return produce(gen, genCopy => { + genCopy + 1 + }) + }) + }) const runSimulation = useCallback(() => { if (!runningRef.current) { @@ -72,6 +74,7 @@ function App () { }); }); + incrementGen(); setTimeout(runSimulation, 700); @@ -146,7 +149,7 @@ function App () { {color === 'green' ? 'change back!' : 'Make boxes green!'} From ab0adf714231ebac13a4d8e8e3b3fcbdfab14bfb Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Wed, 21 Oct 2020 19:39:54 -0700 Subject: [PATCH 3/9] fixes regarding generation counter --- game-of-life/src/App.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/game-of-life/src/App.js b/game-of-life/src/App.js index c42c77ae6..278d3e371 100644 --- a/game-of-life/src/App.js +++ b/game-of-life/src/App.js @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useRef } from "react"; +import React, { useState, useCallback, useRef, useEffect } from "react"; import produce from "immer"; const numRows = 25; @@ -29,22 +29,27 @@ function App () { return generateEmptyGrid(); }); - const [generation, setGeneration] = useState(0) + const [generation, setGeneration] = useState(1) const [color, setColor] = useState('orange') const [running, setRunning] = useState(false); + const [intervalId, setIntervalId] = useState(null); + const runningRef = useRef(running); runningRef.current = running; - const incrementGen = useCallback(() => { - setGeneration(gen => { - return produce(gen, genCopy => { - genCopy + 1 - }) - }) - }) + useEffect(() => { + if (runningRef.current) { + const id = window.setInterval(() => { + setGeneration(generation => generation + 1); + }, 700); + setIntervalId(id); + } else { + window.clearInterval(intervalId); + } + }, [runningRef.current]) const runSimulation = useCallback(() => { if (!runningRef.current) { @@ -73,10 +78,6 @@ function App () { } }); }); - - - incrementGen(); - setTimeout(runSimulation, 700); }, []); @@ -90,7 +91,6 @@ function App () { if (!running) { runningRef.current = true; runSimulation(); - incrementGen(); } }} > @@ -113,6 +113,7 @@ function App () { - From a3aead26396279203d13e90019017ea899a2696a Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Wed, 21 Oct 2020 19:42:42 -0700 Subject: [PATCH 4/9] removing deleted files? --- github-settings.png | Bin 62551 -> 0 bytes objectives/double-buffer/README.md | 39 - objectives/double-buffer/img/life.png | Bin 61680 -> 0 bytes objectives/explain-describe-ca/README.md | 29 - objectives/explain-describe-ca/img/life.png | Bin 61680 -> 0 bytes objectives/rules-game-life/README.md | 50 - objectives/rules-game-life/img/life.png | Bin 61680 -> 0 bytes objectives/turing-complete/README.md | 21 - objectives/turing-complete/img/life.png | Bin 61680 -> 0 bytes pages-source.png | Bin 88248 -> 0 bytes resources/README.md | 5 - resources/ios/README.md | 17 - resources/ios/game-of-life-iOS-mock-1.png | Bin 32183 -> 0 bytes resources/ios/game-of-life-iOS-mock-2.png | Bin 60754 -> 0 bytes resources/python/README.md | 19 - resources/web/README.md | 15 - resources/web/canvas-buffer/Readme.md | 156 -- resources/web/canvas/Readme.md | 194 -- resources/web/deployment/Readme.md | 59 - resources/web/react-setup/README.md | 2250 ------------------- resources/web/simple-components/readme.md | 32 - wireframes/wireframe_1.png | Bin 262509 -> 0 bytes 22 files changed, 2886 deletions(-) delete mode 100644 github-settings.png delete mode 100644 objectives/double-buffer/README.md delete mode 100644 objectives/double-buffer/img/life.png delete mode 100644 objectives/explain-describe-ca/README.md delete mode 100644 objectives/explain-describe-ca/img/life.png delete mode 100644 objectives/rules-game-life/README.md delete mode 100644 objectives/rules-game-life/img/life.png delete mode 100644 objectives/turing-complete/README.md delete mode 100644 objectives/turing-complete/img/life.png delete mode 100644 pages-source.png delete mode 100644 resources/README.md delete mode 100644 resources/ios/README.md delete mode 100644 resources/ios/game-of-life-iOS-mock-1.png delete mode 100644 resources/ios/game-of-life-iOS-mock-2.png delete mode 100644 resources/python/README.md delete mode 100644 resources/web/README.md delete mode 100644 resources/web/canvas-buffer/Readme.md delete mode 100644 resources/web/canvas/Readme.md delete mode 100644 resources/web/deployment/Readme.md delete mode 100644 resources/web/react-setup/README.md delete mode 100644 resources/web/simple-components/readme.md delete mode 100644 wireframes/wireframe_1.png diff --git a/github-settings.png b/github-settings.png deleted file mode 100644 index c2a9fd224853cca290243fff42c809545b5504b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62551 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

-t2KJI5fU$KAo7LY{W?|q#- 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 O0000

- {grid.map((rows, i) => - rows.map((col, k) => ( -
{ - const newGrid = produce(grid, gridCopy => { - gridCopy[i][k] = grid[i][k] ? 0 : 1; - }); - setGrid(newGrid); - }} - style={{ - width: 20, - height: 20, - backgroundColor: grid[i][k] ? color : undefined, - border: "solid 1px black" - }} - /> - )) - )} -
- - - +
+
+ + +
); }; diff --git a/game-of-life/src/components/description.js b/game-of-life/src/components/description.js new file mode 100644 index 000000000..ff3f0c605 --- /dev/null +++ b/game-of-life/src/components/description.js @@ -0,0 +1,40 @@ +import React from 'react' + +function Description () { + return ( +
+

+ About Conway's Game of Life +

+

+ In late 1940, John von Neumann defined life as a creation (as a being or organism) which can reproduce itself and simulate a Turing machine. + Von Neumann was thinking about an engineering solution which would use electromagnetic components floating randomly in liquid or gas.

+ +

Motivated by questions in mathematical logic and in part by work on simulation games by Ulam, + among others, John Conway began doing experiments in 1968 with a variety of different two-dimensional cellular automaton rules. + Conway's initial goal was to define an interesting and unpredictable cell automaton. + For example, he wanted some configurations to last for a long time before dying and other configurations to go on forever without allowing cycles. + It was a significant challenge and an open problem for years before experts on cellular automata managed to prove that, + indeed, the Game of Life admitted of a configuration which was alive in the sense of satisfying Von Neumann's two general requirements. + While the definitions before the Game of Life were proof-oriented, Conway's construction aimed at simplicity without a priori providing proof the automaton was alive.

+
Read More... + +

Rules:

+

The universe of the Game of Life is an infinite, two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead, (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

+
    +
  1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  2. +
  3. Any live cell with two or three live neighbours lives on to the next generation.
  4. +
  5. Any live cell with more than three live neighbours dies, as if by overpopulation.
  6. +
  7. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
  8. +
+

These rules, which compare the behavior of the automaton to real life, can be condensed into the following:

+
    +
  1. Any live cell with two or three live neighbours survives.
  2. +
  3. Any dead cell with three live neighbours becomes a live cell.
  4. +
  5. All other live cells die in the next generation, and all dead cells stay dead.
  6. +
+
+ ) +} + +export default Description \ No newline at end of file diff --git a/game-of-life/src/components/grid.js b/game-of-life/src/components/grid.js new file mode 100644 index 000000000..09bdf3f48 --- /dev/null +++ b/game-of-life/src/components/grid.js @@ -0,0 +1,945 @@ +import React, { useState, useCallback, useRef, useEffect } from "react"; +import produce from "immer"; + +const numRows = 25; +const numCols = 25; + +const operations = [ + [0, 1], + [0, -1], + [1, -1], + [-1, 1], + [1, 1], + [-1, -1], + [1, 0], + [-1, 0] +]; + +const colors = [ + { + "hex": "#EFDECD", + "name": "Almond", + "rgb": "(239, 222, 205)" + }, + { + "hex": "#CD9575", + "name": "Antique Brass", + "rgb": "(205, 149, 117)" + }, + { + "hex": "#FDD9B5", + "name": "Apricot", + "rgb": "(253, 217, 181)" + }, + { + "hex": "#78DBE2", + "name": "Aquamarine", + "rgb": "(120, 219, 226)" + }, + { + "hex": "#87A96B", + "name": "Asparagus", + "rgb": "(135, 169, 107)" + }, + { + "hex": "#FFA474", + "name": "Atomic Tangerine", + "rgb": "(255, 164, 116)" + }, + { + "hex": "#FAE7B5", + "name": "Banana Mania", + "rgb": "(250, 231, 181)" + }, + { + "hex": "#9F8170", + "name": "Beaver", + "rgb": "(159, 129, 112)" + }, + { + "hex": "#FD7C6E", + "name": "Bittersweet", + "rgb": "(253, 124, 110)" + }, + { + "hex": "#000000", + "name": "Black", + "rgb": "(0,0,0)" + }, + { + "hex": "#ACE5EE", + "name": "Blizzard Blue", + "rgb": "(172, 229, 238)" + }, + { + "hex": "#1F75FE", + "name": "Blue", + "rgb": "(31, 117, 254)" + }, + { + "hex": "#A2A2D0", + "name": "Blue Bell", + "rgb": "(162, 162, 208)" + }, + { + "hex": "#0D98BA", + "name": "Blue Green", + "rgb": "(13, 152, 186)" + }, + { + "hex": "#7366BD", + "name": "Blue Violet", + "rgb": "(115, 102, 189)" + }, + { + "hex": "#DE5D83", + "name": "Blush", + "rgb": "(222, 93, 131)" + }, + { + "hex": "#CB4154", + "name": "Brick Red", + "rgb": "(203, 65, 84)" + }, + { + "hex": "#B4674D", + "name": "Brown", + "rgb": "(180, 103, 77)" + }, + { + "hex": "#FF7F49", + "name": "Burnt Orange", + "rgb": "(255, 127, 73)" + }, + { + "hex": "#EA7E5D", + "name": "Burnt Sienna", + "rgb": "(234, 126, 93)" + }, + { + "hex": "#B0B7C6", + "name": "Cadet Blue", + "rgb": "(176, 183, 198)" + }, + { + "hex": "#FFFF99", + "name": "Canary", + "rgb": "(255, 255, 153)" + }, + { + "hex": "#1CD3A2", + "name": "Caribbean Green", + "rgb": "(28, 211, 162)" + }, + { + "hex": "#FFAACC", + "name": "Carnation Pink", + "rgb": "(255, 170, 204)" + }, + { + "hex": "#DD4492", + "name": "Cerise", + "rgb": "(221, 68, 146)" + }, + { + "hex": "#1DACD6", + "name": "Cerulean", + "rgb": "(29, 172, 214)" + }, + { + "hex": "#BC5D58", + "name": "Chestnut", + "rgb": "(188, 93, 88)" + }, + { + "hex": "#DD9475", + "name": "Copper", + "rgb": "(221, 148, 117)" + }, + { + "hex": "#9ACEEB", + "name": "Cornflower", + "rgb": "(154, 206, 235)" + }, + { + "hex": "#FFBCD9", + "name": "Cotton Candy", + "rgb": "(255, 188, 217)" + }, + { + "hex": "#FDDB6D", + "name": "Dandelion", + "rgb": "(253, 219, 109)" + }, + { + "hex": "#2B6CC4", + "name": "Denim", + "rgb": "(43, 108, 196)" + }, + { + "hex": "#EFCDB8", + "name": "Desert Sand", + "rgb": "(239, 205, 184)" + }, + { + "hex": "#6E5160", + "name": "Eggplant", + "rgb": "(110, 81, 96)" + }, + { + "hex": "#CEFF1D", + "name": "Electric Lime", + "rgb": "(206, 255, 29)" + }, + { + "hex": "#71BC78", + "name": "Fern", + "rgb": "(113, 188, 120)" + }, + { + "hex": "#6DAE81", + "name": "Forest Green", + "rgb": "(109, 174, 129)" + }, + { + "hex": "#C364C5", + "name": "Fuchsia", + "rgb": "(195, 100, 197)" + }, + { + "hex": "#CC6666", + "name": "Fuzzy Wuzzy", + "rgb": "(204, 102, 102)" + }, + { + "hex": "#E7C697", + "name": "Gold", + "rgb": "(231, 198, 151)" + }, + { + "hex": "#FCD975", + "name": "Goldenrod", + "rgb": "(252, 217, 117)" + }, + { + "hex": "#A8E4A0", + "name": "Granny Smith Apple", + "rgb": "(168, 228, 160)" + }, + { + "hex": "#1CAC78", + "name": "Green", + "rgb": "(28, 172, 120)" + }, + { + "hex": "#1164B4", + "name": "Green Blue", + "rgb": "(17, 100, 180)" + }, + { + "hex": "#F0E891", + "name": "Green Yellow", + "rgb": "(240, 232, 145)" + }, + { + "hex": "#FF1DCE", + "name": "Hot Magenta", + "rgb": "(255, 29, 206)" + }, + { + "hex": "#B2EC5D", + "name": "Inchworm", + "rgb": "(178, 236, 93)" + }, + { + "hex": "#5D76CB", + "name": "Indigo", + "rgb": "(93, 118, 203)" + }, + { + "hex": "#CA3767", + "name": "Jazzberry Jam", + "rgb": "(202, 55, 103)" + }, + { + "hex": "#3BB08F", + "name": "Jungle Green", + "rgb": "(59, 176, 143)" + }, + { + "hex": "#FEFE22", + "name": "Laser Lemon", + "rgb": "(254, 254, 34)" + }, + { + "hex": "#FCB4D5", + "name": "Lavender", + "rgb": "(252, 180, 213)" + }, + { + "hex": "#FFF44F", + "name": "Lemon Yellow", + "rgb": "(255, 244, 79)" + }, + { + "hex": "#FFBD88", + "name": "Macaroni and Cheese", + "rgb": "(255, 189, 136)" + }, + { + "hex": "#F664AF", + "name": "Magenta", + "rgb": "(246, 100, 175)" + }, + { + "hex": "#AAF0D1", + "name": "Magic Mint", + "rgb": "(170, 240, 209)" + }, + { + "hex": "#CD4A4C", + "name": "Mahogany", + "rgb": "(205, 74, 76)" + }, + { + "hex": "#EDD19C", + "name": "Maize", + "rgb": "(237, 209, 156)" + }, + { + "hex": "#979AAA", + "name": "Manatee", + "rgb": "(151, 154, 170)" + }, + { + "hex": "#FF8243", + "name": "Mango Tango", + "rgb": "(255, 130, 67)" + }, + { + "hex": "#C8385A", + "name": "Maroon", + "rgb": "(200, 56, 90)" + }, + { + "hex": "#EF98AA", + "name": "Mauvelous", + "rgb": "(239, 152, 170)" + }, + { + "hex": "#FDBCB4", + "name": "Melon", + "rgb": "(253, 188, 180)" + }, + { + "hex": "#1A4876", + "name": "Midnight Blue", + "rgb": "(26, 72, 118)" + }, + { + "hex": "#30BA8F", + "name": "Mountain Meadow", + "rgb": "(48, 186, 143)" + }, + { + "hex": "#C54B8C", + "name": "Mulberry", + "rgb": "(197, 75, 140)" + }, + { + "hex": "#1974D2", + "name": "Navy Blue", + "rgb": "(25, 116, 210)" + }, + { + "hex": "#FFA343", + "name": "Neon Carrot", + "rgb": "(255, 163, 67)" + }, + { + "hex": "#BAB86C", + "name": "Olive Green", + "rgb": "(186, 184, 108)" + }, + { + "hex": "#FF7538", + "name": "Orange", + "rgb": "(255, 117, 56)" + }, + { + "hex": "#FF2B2B", + "name": "Orange Red", + "rgb": "(255, 43, 43)" + }, + { + "hex": "#F8D568", + "name": "Orange Yellow", + "rgb": "(248, 213, 104)" + }, + { + "hex": "#E6A8D7", + "name": "Orchid", + "rgb": "(230, 168, 215)" + }, + { + "hex": "#414A4C", + "name": "Outer Space", + "rgb": "(65, 74, 76)" + }, + { + "hex": "#FF6E4A", + "name": "Outrageous Orange", + "rgb": "(255, 110, 74)" + }, + { + "hex": "#1CA9C9", + "name": "Pacific Blue", + "rgb": "(28, 169, 201)" + }, + { + "hex": "#FFCFAB", + "name": "Peach", + "rgb": "(255, 207, 171)" + }, + { + "hex": "#C5D0E6", + "name": "Periwinkle", + "rgb": "(197, 208, 230)" + }, + { + "hex": "#FDDDE6", + "name": "Piggy Pink", + "rgb": "(253, 221, 230)" + }, + { + "hex": "#158078", + "name": "Pine Green", + "rgb": "(21, 128, 120)" + }, + { + "hex": "#FC74FD", + "name": "Pink Flamingo", + "rgb": "(252, 116, 253)" + }, + { + "hex": "#F78FA7", + "name": "Pink Sherbet", + "rgb": "(247, 143, 167)" + }, + { + "hex": "#8E4585", + "name": "Plum", + "rgb": "(142, 69, 133)" + }, + { + "hex": "#7442C8", + "name": "Purple Heart", + "rgb": "(116, 66, 200)" + }, + { + "hex": "#9D81BA", + "name": "Purple Mountain's Majesty", + "rgb": "(157, 129, 186)" + }, + { + "hex": "#FE4EDA", + "name": "Purple Pizzazz", + "rgb": "(254, 78, 218)" + }, + { + "hex": "#FF496C", + "name": "Radical Red", + "rgb": "(255, 73, 108)" + }, + { + "hex": "#D68A59", + "name": "Raw Sienna", + "rgb": "(214, 138, 89)" + }, + { + "hex": "#714B23", + "name": "Raw Umber", + "rgb": "(113, 75, 35)" + }, + { + "hex": "#FF48D0", + "name": "Razzle Dazzle Rose", + "rgb": "(255, 72, 208)" + }, + { + "hex": "#E3256B", + "name": "Razzmatazz", + "rgb": "(227, 37, 107)" + }, + { + "hex": "#EE204D", + "name": "Red", + "rgb": "(238,32 ,77 )" + }, + { + "hex": "#FF5349", + "name": "Red Orange", + "rgb": "(255, 83, 73)" + }, + { + "hex": "#C0448F", + "name": "Red Violet", + "rgb": "(192, 68, 143)" + }, + { + "hex": "#1FCECB", + "name": "Robin's Egg Blue", + "rgb": "(31, 206, 203)" + }, + { + "hex": "#7851A9", + "name": "Royal Purple", + "rgb": "(120, 81, 169)" + }, + { + "hex": "#FF9BAA", + "name": "Salmon", + "rgb": "(255, 155, 170)" + }, + { + "hex": "#FC2847", + "name": "Scarlet", + "rgb": "(252, 40, 71)" + }, + { + "hex": "#76FF7A", + "name": "Screamin' Green", + "rgb": "(118, 255, 122)" + }, + { + "hex": "#9FE2BF", + "name": "Sea Green", + "rgb": "(159, 226, 191)" + }, + { + "hex": "#A5694F", + "name": "Sepia", + "rgb": "(165, 105, 79)" + }, + { + "hex": "#8A795D", + "name": "Shadow", + "rgb": "(138, 121, 93)" + }, + { + "hex": "#45CEA2", + "name": "Shamrock", + "rgb": "(69, 206, 162)" + }, + { + "hex": "#FB7EFD", + "name": "Shocking Pink", + "rgb": "(251, 126, 253)" + }, + { + "hex": "#CDC5C2", + "name": "Silver", + "rgb": "(205, 197, 194)" + }, + { + "hex": "#80DAEB", + "name": "Sky Blue", + "rgb": "(128, 218, 235)" + }, + { + "hex": "#ECEABE", + "name": "Spring Green", + "rgb": "(236, 234, 190)" + }, + { + "hex": "#FFCF48", + "name": "Sunglow", + "rgb": "(255, 207, 72)" + }, + { + "hex": "#FD5E53", + "name": "Sunset Orange", + "rgb": "(253, 94, 83)" + }, + { + "hex": "#FAA76C", + "name": "Tan", + "rgb": "(250, 167, 108)" + }, + { + "hex": "#18A7B5", + "name": "Teal Blue", + "rgb": "(24, 167, 181)" + }, + { + "hex": "#EBC7DF", + "name": "Thistle", + "rgb": "(235, 199, 223)" + }, + { + "hex": "#FC89AC", + "name": "Tickle Me Pink", + "rgb": "(252, 137, 172)" + }, + { + "hex": "#DBD7D2", + "name": "Timberwolf", + "rgb": "(219, 215, 210)" + }, + { + "hex": "#17806D", + "name": "Tropical Rain Forest", + "rgb": "(23, 128, 109)" + }, + { + "hex": "#DEAA88", + "name": "Tumbleweed", + "rgb": "(222, 170, 136)" + }, + { + "hex": "#77DDE7", + "name": "Turquoise Blue", + "rgb": "(119, 221, 231)" + }, + { + "hex": "#FFFF66", + "name": "Unmellow Yellow", + "rgb": "(255, 255, 102)" + }, + { + "hex": "#926EAE", + "name": "Violet (Purple)", + "rgb": "(146, 110, 174)" + }, + { + "hex": "#324AB2", + "name": "Violet Blue", + "rgb": "(50, 74, 178)" + }, + { + "hex": "#F75394", + "name": "Violet Red", + "rgb": "(247, 83, 148)" + }, + { + "hex": "#FFA089", + "name": "Vivid Tangerine", + "rgb": "(255, 160, 137)" + }, + { + "hex": "#8F509D", + "name": "Vivid Violet", + "rgb": "(143, 80, 157)" + }, + // { + // "hex": "#FFFFFF", + // "name": "White", + // "rgb": "(255, 255, 255)" + // }, + { + "hex": "#A2ADD0", + "name": "Wild Blue Yonder", + "rgb": "(162, 173, 208)" + }, + { + "hex": "#FF43A4", + "name": "Wild Strawberry", + "rgb": "(255, 67, 164)" + }, + { + "hex": "#FC6C85", + "name": "Wild Watermelon", + "rgb": "(252, 108, 133)" + }, + { + "hex": "#CDA4DE", + "name": "Wisteria", + "rgb": "(205, 164, 222)" + }, + { + "hex": "#FCE883", + "name": "Yellow", + "rgb": "(252, 232, 131)" + }, + { + "hex": "#C5E384", + "name": "Yellow Green", + "rgb": "(197, 227, 132)" + }, + { + "hex": "#FFAE42", + "name": "Yellow Orange", + "rgb": "(255, 174, 66)" + } +] + + +const generateEmptyGrid = () => { + const rows = []; + for (let i = 0; i < numRows; i++) { + rows.push(Array.from(Array(numCols), () => 0)); + } + + return rows; +}; + +function Grid () { + const [grid, setGrid] = useState(() => { + return generateEmptyGrid(); + }); + + const [generation, setGeneration] = useState(0) + + const [color, setColor] = useState('orange') + + const [running, setRunning] = useState(false); + + const [intervalId, setIntervalId] = useState(null); + + const [speed, setSpeed] = useState(700); + + const [addSpeed, setAddSpeed] = useState(false); + + const [random, setRandom] = useState(false); + + const randomRef = useRef(random); + randomRef.current = randomRef; + + const runningRef = useRef(running); + runningRef.current = running; + + const speedRef = useRef(addSpeed); + speedRef.current = speedRef; + + // useEffect(() => { + // if (runningRef.current) { + // const id = window.setInterval(() => { + // setGeneration(generation => generation + 1); + // }, 700); + // setIntervalId(id); + // } else { + // window.clearInterval(intervalId); + // } + // }, [runningRef.current]) + + const increaseSpeed = () => { + if (runningRef.current) { + setSpeed(speed => speed - 100) + } + } + + const addGen = () => { + if (runningRef.current) { + setGeneration(generation => generation + 1); + // console.log(speed) + } + } + + const randomColors = (arr) => { + return arr[Math.floor(Math.random()*arr.length)].hex + } + + const runStep = useCallback(() => { + + setGrid(g => { + return produce(g, gridCopy => { + for (let i = 0; i < numRows; i++) { + for (let k = 0; k < numCols; k++) { + let neighbors = 0; + operations.forEach(([x, y]) => { + const newI = i + x; + const newK = k + y; + if (newI >= 0 && newI < numRows && newK >= 0 && newK < numCols) { + neighbors += g[newI][newK]; + } + }); + + if (neighbors < 2 || neighbors > 3) { + gridCopy[i][k] = 0; + } else if (g[i][k] === 0 && neighbors === 3) { + gridCopy[i][k] = 1; + } + } + } + }); + }); + + // if (randomRef.current) { + // setColor(randomColors(colors)) + // } + + setGeneration(generation => generation + 1) + // setTimeout(runSimulation, speed); + }, []); + + const runSimulation = useCallback(() => { + if (!runningRef.current) { + return; + } + + setGrid(g => { + return produce(g, gridCopy => { + for (let i = 0; i < numRows; i++) { + for (let k = 0; k < numCols; k++) { + let neighbors = 0; + operations.forEach(([x, y]) => { + const newI = i + x; + const newK = k + y; + if (newI >= 0 && newI < numRows && newK >= 0 && newK < numCols) { + neighbors += g[newI][newK]; + } + }); + + if (neighbors < 2 || neighbors > 3) { + gridCopy[i][k] = 0; + } else if (g[i][k] === 0 && neighbors === 3) { + gridCopy[i][k] = 1; + } + } + } + }); + }); + + addGen(); + // setColor(randomColors(colors)); + setTimeout(runSimulation, speed); + }, []); + + const runRandom = useCallback(() => { + if (!runningRef.current) { + return; + } + + setGrid(g => { + return produce(g, gridCopy => { + for (let i = 0; i < numRows; i++) { + for (let k = 0; k < numCols; k++) { + let neighbors = 0; + operations.forEach(([x, y]) => { + const newI = i + x; + const newK = k + y; + if (newI >= 0 && newI < numRows && newK >= 0 && newK < numCols) { + neighbors += g[newI][newK]; + } + }); + + if (neighbors < 2 || neighbors > 3) { + gridCopy[i][k] = 0; + } else if (g[i][k] === 0 && neighbors === 3) { + gridCopy[i][k] = 1; + } + } + } + }); + }); + + setColor(randomColors(colors)); + + addGen(); + setTimeout(runRandom, 500); + }, []); + + + return ( +
+

Generations: {generation}

+ + + + + +
+ {grid.map((rows, i) => + rows.map((col, k) => ( +
{ + const newGrid = produce(grid, gridCopy => { + gridCopy[i][k] = grid[i][k] ? 0 : 1; + }); + setGrid(newGrid); + }} + style={{ + width: 20, + height: 20, + backgroundColor: grid[i][k] ? color : undefined, + border: "solid 1px black" + }} + /> + )) + )} +
+ {/* + */} +
+ ); +}; + +export default Grid \ No newline at end of file diff --git a/game-of-life/src/components/header.js b/game-of-life/src/components/header.js new file mode 100644 index 000000000..67ae6df82 --- /dev/null +++ b/game-of-life/src/components/header.js @@ -0,0 +1,9 @@ +import React from 'react'; + +function Header () { + return ( +

Welcome to Conway's Game of life!

+ ) +} + +export default Header \ No newline at end of file From 992ddee28e291b7308b9d26bc92aad0f1cf16b37 Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Sat, 24 Oct 2020 09:00:27 -0700 Subject: [PATCH 7/9] adding more styling, going to make live --- game-of-life/src/App.css | 11 ++++ game-of-life/src/App.js | 2 +- game-of-life/src/components/description.js | 62 ++++++++++++---------- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/game-of-life/src/App.css b/game-of-life/src/App.css index ce2d9eba1..5b053cc91 100644 --- a/game-of-life/src/App.css +++ b/game-of-life/src/App.css @@ -1,3 +1,14 @@ .App { text-align: center; +} + +.info { + display: flex; + justify-content: space-evenly; + /* border: 2px solid green; */ + +} + +.box { + width: 50rem } \ No newline at end of file diff --git a/game-of-life/src/App.js b/game-of-life/src/App.js index d2d70c3ad..b5a9ac4c1 100644 --- a/game-of-life/src/App.js +++ b/game-of-life/src/App.js @@ -8,7 +8,7 @@ import './App.css'; function App () { return ( -
+
diff --git a/game-of-life/src/components/description.js b/game-of-life/src/components/description.js index ff3f0c605..dbc51be6b 100644 --- a/game-of-life/src/components/description.js +++ b/game-of-life/src/components/description.js @@ -1,38 +1,42 @@ import React from 'react' +import '../App.css' function Description () { return ( -
-

- About Conway's Game of Life -

-

- In late 1940, John von Neumann defined life as a creation (as a being or organism) which can reproduce itself and simulate a Turing machine. - Von Neumann was thinking about an engineering solution which would use electromagnetic components floating randomly in liquid or gas.

+
+
+

+ About Conway's Game of Life +

+

+ In late 1940, John von Neumann defined life as a creation (as a being or organism) which can reproduce itself and simulate a Turing machine. + Von Neumann was thinking about an engineering solution which would use electromagnetic components floating randomly in liquid or gas.

-

Motivated by questions in mathematical logic and in part by work on simulation games by Ulam, - among others, John Conway began doing experiments in 1968 with a variety of different two-dimensional cellular automaton rules. - Conway's initial goal was to define an interesting and unpredictable cell automaton. - For example, he wanted some configurations to last for a long time before dying and other configurations to go on forever without allowing cycles. - It was a significant challenge and an open problem for years before experts on cellular automata managed to prove that, - indeed, the Game of Life admitted of a configuration which was alive in the sense of satisfying Von Neumann's two general requirements. - While the definitions before the Game of Life were proof-oriented, Conway's construction aimed at simplicity without a priori providing proof the automaton was alive.

+

Motivated by questions in mathematical logic and in part by work on simulation games by Ulam, + among others, John Conway began doing experiments in 1968 with a variety of different two-dimensional cellular automaton rules. + Conway's initial goal was to define an interesting and unpredictable cell automaton. + For example, he wanted some configurations to last for a long time before dying and other configurations to go on forever without allowing cycles. + It was a significant challenge and an open problem for years before experts on cellular automata managed to prove that, + indeed, the Game of Life admitted of a configuration which was alive in the sense of satisfying Von Neumann's two general requirements. + While the definitions before the Game of Life were proof-oriented, Conway's construction aimed at simplicity without a priori providing proof the automaton was alive.

Read More... - -

Rules:

-

The universe of the Game of Life is an infinite, two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead, (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

-
    -
  1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  2. -
  3. Any live cell with two or three live neighbours lives on to the next generation.
  4. -
  5. Any live cell with more than three live neighbours dies, as if by overpopulation.
  6. -
  7. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
  8. -
-

These rules, which compare the behavior of the automaton to real life, can be condensed into the following:

-
    -
  1. Any live cell with two or three live neighbours survives.
  2. -
  3. Any dead cell with three live neighbours becomes a live cell.
  4. -
  5. All other live cells die in the next generation, and all dead cells stay dead.
  6. -
+
+
+

Rules:

+

The universe of the Game of Life is an infinite, two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead, (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

+
    +
  1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  2. +
  3. Any live cell with two or three live neighbours lives on to the next generation.
  4. +
  5. Any live cell with more than three live neighbours dies, as if by overpopulation.
  6. +
  7. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
  8. +
+

These rules, which compare the behavior of the automaton to real life, can be condensed into the following:

+
    +
  1. Any live cell with two or three live neighbours survives.
  2. +
  3. Any dead cell with three live neighbours becomes a live cell.
  4. +
  5. All other live cells die in the next generation, and all dead cells stay dead.
  6. +
+
) } From 6cc64d7851509922d6509f44a022671d5075560f Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Sat, 24 Oct 2020 11:25:59 -0700 Subject: [PATCH 8/9] corrected state when clear button was clicked --- game-of-life/src/components/grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game-of-life/src/components/grid.js b/game-of-life/src/components/grid.js index 09bdf3f48..3725458bb 100644 --- a/game-of-life/src/components/grid.js +++ b/game-of-life/src/components/grid.js @@ -876,7 +876,7 @@ function Grid () { onClick={() => { setGrid(generateEmptyGrid()); setGeneration(0) - setRunning(!running) + setRunning(false) }} > clear From a71da08624ceb448d4430bba4697afceb7ca704a Mon Sep 17 00:00:00 2001 From: Joshua Chinchilla Date: Wed, 24 Feb 2021 20:15:05 -0800 Subject: [PATCH 9/9] fixed styling for mobile screens --- game-of-life/src/App.css | 14 ++++++++++++++ game-of-life/src/components/grid.js | 8 +------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/game-of-life/src/App.css b/game-of-life/src/App.css index 5b053cc91..ac6e0d52c 100644 --- a/game-of-life/src/App.css +++ b/game-of-life/src/App.css @@ -2,6 +2,14 @@ text-align: center; } +.grid { + /* border: 10px solid orange; */ + margin-left: 42rem; + margin-top: 2rem; + display: grid; + grid-template-columns: repeat(25, 20px); +} + .info { display: flex; justify-content: space-evenly; @@ -11,4 +19,10 @@ .box { width: 50rem +} + +@media screen and (max-width: 900px) { + .grid { + margin-left: 0; + } } \ No newline at end of file diff --git a/game-of-life/src/components/grid.js b/game-of-life/src/components/grid.js index 3725458bb..6923acca2 100644 --- a/game-of-life/src/components/grid.js +++ b/game-of-life/src/components/grid.js @@ -896,13 +896,7 @@ function Grid () { randomize colors!
{grid.map((rows, i) => rows.map((col, k) => (