<div id="app"></div>
.App {
font-family: sans-serif;
text-align: center;
}
.game {
display: flex;
justify-content: center;
align-items: center;
height: 600px;
}
button {
background-color: lightblue;
border: none;
border-radius: 5px;
padding: 20px;
font-size: 18px;
box-shadow: none;
width: 150px;
}
.cards {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 10px;
}
.card {
height: 30px;
width: 30px;
background-color: lightblue;
padding: 10px;
font-size: 24px;
}
.hidden {
color: rgba(0, 0, 0, 0);
}
.show {
color: black;
}
.removed {
visibility: hidden;
}
.win {
margin-bottom: 30px;
}
/*
* https://frontendeval.com/questions/memory-game
*
* Create a card-matching memory game
*/
const NUM_LIST = () => {
let list = [];
for (let i = 1; i <= 18; i++) {
list.push(i);
list.push(i);
}
return list;
};
const App = () => {
const [start, setStart] = React.useState("init");
const [nums, setNums] = React.useState(NUM_LIST);
const [solved, setSolved] = React.useState([]);
const [opened, setOpened] = React.useState(null);
const handleStart = () => {
setStart("start");
setNums(radomNums());
setSolved([]);
};
const radomNums = () => {
return nums.sort(() => Math.random() - 0.5);
};
const getClassName = (num, index) => {
if (solved.includes(num)) return "removed";
if (opened && opened[index] === num) return "show";
return "hidden";
};
const openCard = (num, index) => {
if (opened && Object.keys(opened).length === 2) return;
if (opened === null) {
setOpened({ [index]: num });
} else if (Object.values(opened)[0] === num) {
setOpened((pre) => ({ ...pre, [index]: num }));
setTimeout(() => {
setSolved((pre) => [...pre, num]);
setOpened(null);
}, 1000);
} else {
setOpened((pre) => ({ ...pre, [index]: num }));
setTimeout(() => {
setOpened(null);
}, 1000);
}
};
React.useEffect(() => {
setNums(radomNums());
}, []);
React.useEffect(() => {
if (solved.length === 18) {
setStart("win");
}
}, [solved]);
return (
<div className="App">
<h1>Memory game</h1>
<div className="game">
{start === "start" && (
<div className="cards">
{nums.map((num, index) => (
<div
key={index}
className={`card ${getClassName(num, index)}`}
onClick={() => openCard(num, index)}
>
{num}
</div>
))}
</div>
)}
<div>
{start === "win" && (
<div className="win">Congrats, you win the game!!!!</div>
)}
{start !== "start" && (
<button onClick={handleStart}>
{start === "win" ? "Play again" : "Play"}
</button>
)}
</div>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
View Compiled
This Pen doesn't use any external CSS resources.