├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── img │ ├── angular.png │ ├── css.png │ ├── game-preview.png │ ├── html.png │ ├── js.png │ ├── nodejs.png │ ├── react.png │ ├── scss.png │ └── vue.png ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.js ├── components ├── Card.js └── Cards.js ├── index.css └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Memory Game 2 | ## Step by step tutorial available on [YouTube](https://youtu.be/qhOZoJPMg6w) 3 | 4 | ![React Memory Game](public/img/game-preview.png) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memory-game", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.15.1", 7 | "@testing-library/react": "^11.2.7", 8 | "@testing-library/user-event": "^12.8.3", 9 | "react": "^17.0.2", 10 | "react-dom": "^17.0.2", 11 | "react-scripts": "4.0.3", 12 | "web-vitals": "^1.1.2" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/favicon.ico -------------------------------------------------------------------------------- /public/img/angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/angular.png -------------------------------------------------------------------------------- /public/img/css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/css.png -------------------------------------------------------------------------------- /public/img/game-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/game-preview.png -------------------------------------------------------------------------------- /public/img/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/html.png -------------------------------------------------------------------------------- /public/img/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/js.png -------------------------------------------------------------------------------- /public/img/nodejs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/nodejs.png -------------------------------------------------------------------------------- /public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/react.png -------------------------------------------------------------------------------- /public/img/scss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/scss.png -------------------------------------------------------------------------------- /public/img/vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/img/vue.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0shuvo0/react-memory-game/7d15e0352b76c06a2208ed6db92b370021bad792/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import Cards from './components/Cards' 2 | 3 | function App() { 4 | return ( 5 |
6 |

Memory Game - React

7 | 8 |
9 | ); 10 | } 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /src/components/Card.js: -------------------------------------------------------------------------------- 1 | function Card({item, id, handleClick}){ 2 | const itemClass = item.stat ? " active " + item.stat : "" 3 | 4 | return ( 5 |
handleClick(id)}> 6 | 7 |
8 | ) 9 | } 10 | 11 | export default Card -------------------------------------------------------------------------------- /src/components/Cards.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import Card from './Card' 3 | 4 | function Cards(){ 5 | const [items, setItems] = useState([ 6 | { id: 1, img: '/img/html.png', stat: "" }, 7 | { id: 1, img: '/img/html.png', stat: "" }, 8 | { id: 2, img: '/img/css.png', stat: "" }, 9 | { id: 2, img: '/img/css.png', stat: "" }, 10 | { id: 3, img: '/img/js.png', stat: "" }, 11 | { id: 3, img: '/img/js.png', stat: "" }, 12 | { id: 4, img: '/img/scss.png', stat: "" }, 13 | { id: 4, img: '/img/scss.png', stat: "" }, 14 | { id: 5, img: '/img/react.png', stat: "" }, 15 | { id: 5, img: '/img/react.png', stat: "" }, 16 | { id: 6, img: '/img/vue.png', stat: "" }, 17 | { id: 6, img: '/img/vue.png', stat: "" }, 18 | { id: 7, img: '/img/angular.png', stat: "" }, 19 | { id: 7, img: '/img/angular.png', stat: "" }, 20 | { id: 8, img: '/img/nodejs.png', stat: "" }, 21 | { id: 8, img: '/img/nodejs.png', stat: "" } 22 | ].sort(() => Math.random() - 0.5)) 23 | 24 | const [prev, setPrev] = useState(-1) 25 | 26 | function check(current){ 27 | if(items[current].id == items[prev].id){ 28 | items[current].stat = "correct" 29 | items[prev].stat = "correct" 30 | setItems([...items]) 31 | setPrev(-1) 32 | }else{ 33 | items[current].stat = "wrong" 34 | items[prev].stat = "wrong" 35 | setItems([...items]) 36 | setTimeout(() => { 37 | items[current].stat = "" 38 | items[prev].stat = "" 39 | setItems([...items]) 40 | setPrev(-1) 41 | }, 1000) 42 | } 43 | } 44 | 45 | function handleClick(id){ 46 | if(prev === -1){ 47 | items[id].stat = "active" 48 | setItems([...items]) 49 | setPrev(id) 50 | }else{ 51 | check(id) 52 | } 53 | } 54 | 55 | return ( 56 |
57 | { items.map((item, index) => ( 58 | 59 | )) } 60 |
61 | ) 62 | } 63 | 64 | export default Cards -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | } 5 | html, body{ 6 | height: 100%; 7 | } 8 | body{ 9 | font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; 10 | background-color: #fae19d; 11 | display: flex; 12 | justify-content: center; 13 | align-items: center; 14 | } 15 | 16 | h1{ 17 | text-align: center; 18 | margin-bottom: 1em; 19 | } 20 | .container{ 21 | height: 700px; 22 | width: 700px; 23 | display: grid; 24 | grid-template-columns: repeat(4, 1fr); 25 | grid-template-rows: repeat(4, 1fr); 26 | gap: 1em; 27 | } 28 | 29 | .card{ 30 | background-color: #fff; 31 | display: flex; 32 | justify-content: center; 33 | align-items: center; 34 | border-radius: 5px; 35 | transform: rotateY(180deg); 36 | animation: 2s hideCard linear; 37 | transition: transform 0.5s; 38 | } 39 | @keyframes hideCard{ 40 | 0%, 70%{ 41 | transform: rotateY(0); 42 | } 43 | 100%{ 44 | transform: rotateY(180deg); 45 | } 46 | } 47 | .card img{ 48 | max-width: 80%; 49 | max-height: 80%; 50 | transition: transform 0.5s; 51 | transform: scale(0); 52 | animation: 2s hideImage linear; 53 | } 54 | @keyframes hideImage{ 55 | 0%, 70%{ 56 | transform: scale(1); 57 | } 58 | 100%{ 59 | transform: scale(0); 60 | } 61 | } 62 | 63 | .card.active{ 64 | transform: rotateY(0); 65 | } 66 | .card.correct{ 67 | background-color: #65e469; 68 | } 69 | .card.wrong{ 70 | background-color: #fd245a; 71 | } 72 | .card.active img{ 73 | transform: scale(1); 74 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | --------------------------------------------------------------------------------