This project was completed as part of a group learning exercise.
https://memorization.netlify.app/
- ✅ User can see a grid with n x n cards (n is an integer). All the cards are faced down initially (hidden state)
- ✅ User can click on any card to unveil the image that is underneath it (change it to visible state). The image will be displayed until the user clicks on a 2nd card
- ✅ If there is a match, the 2 cards will be eliminated from the game (either hide/remove them or leave them in the visible state)
- ✅ If there isn't a match, the 2 cards will flip back to their original state (hidden state)
- ✅ When all the matches have been found, the User can see a dialog box showing a Congratulations message with a counter displaying the time it took to finish the game
- typescript
- react
- remix
- xstate
- tailwindcss
Decided to use xstate for the game mechanics.
The diagram for the game state machine was created at https://statecharts.io/. Keeping track of this type of state can be complicated, and a state machine helps organize the possible transitions in the game.
{
id: "memorize",
initial: "choice",
/* context represents the state we want to store within the machine */
context: {
cards: [],
flipped: [],
found: [],
turns: 0,
done: false,
start: null,
end: null,
},
/* a hierarchy of states can be defined */
states: {
choice: {
initial: "first",
always: [
{
target: "done",
/* a function is defined as a "guard" with the name "isDone"
this transition to target "done" will only happen if the
cond guard returns true */
cond: "isDone",
},
],
states: {
first: {
on: {
/* events can be sent to the machine, this one would be send("flip") */
flip: { target: "second", actions: "flipCard" },
},
},
second: {
on: {
flip: {
target: "check",
actions: "flipCard",
cond: "isUnflipped",
},
},
},
check: {
invoke: {
id: "checker",
src: "checkMatch",
onDone: {
target: "first",
actions: "matched",
},
onError: {
target: "first",
actions: "unmatched",
},
},
},
},
},
done: {
/* at the end when we enter the "done" state trigger an action
that sets the end time */
onEntry: "endTimer",
},
},
}
The animation that is shown when the game is won is using the <marquee>
tag.
<div className="w-full bg-yellow-400 text-2xl py-6 flex justify-center">
<marquee>
{(time / 1000).toFixed(2)} seconds - Congratulations
</marquee>
</div>
It looks like this tag is no longer supported, better use it while we still can.
The Netlify CLI starts your app in development mode, rebuilding assets on file changes.
npm run dev
Open up http://localhost:3000, and you should be ready to go!
npm run build
netlify deploy
netlify deploy --prod