-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle matching pairs #7
Conversation
@@ -2,36 +2,25 @@ import { useEffect, useMemo, useState } from 'react'; | |||
import { SignContent } from '../../types'; | |||
import './PicketSign.css'; | |||
|
|||
export const PicketSign = ({ content }: { content: SignContent }) => { | |||
const [flipped, setFlipped] = useState(true); | |||
const [showContent, setShowContent] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exists to prevent the card contents from flashing when the page loads. However I think you're on to something. I'll make a suggestion below that can prevent the image flash without extra JS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The suggestions feature in github won't let me suggest the entire code change, so I made #8 instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! I wound up having to request changes in the form of a PR into your PR for some silly reason, but it's just a fix for a minor vqa bug.
@@ -2,36 +2,25 @@ import { useEffect, useMemo, useState } from 'react'; | |||
import { SignContent } from '../../types'; | |||
import './PicketSign.css'; | |||
|
|||
export const PicketSign = ({ content }: { content: SignContent }) => { | |||
const [flipped, setFlipped] = useState(true); | |||
const [showContent, setShowContent] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The suggestions feature in github won't let me suggest the entire code change, so I made #8 instead.
src/App.tsx
Outdated
|
||
const handleCardClick = (card: Card) => { | ||
// do nothing if card is already face up or matched: | ||
if (card.isFaceUp || card.isMatched) { | ||
return; | ||
} | ||
|
||
// do nothing if there's already two actively face-up cards: | ||
const faceUpCards = cards.filter(c => c.isFaceUp && !c.isMatched); // TODO: do we care about O(N) here? probably not | ||
if (faceUpCards.length >= 2) { | ||
return; | ||
} | ||
|
||
// flip the card face-up: | ||
const newCards = cards.map(c => | ||
c.id === card.id ? { ...c, isFaceUp: true } : c | ||
); | ||
setCards(newCards); | ||
|
||
// is this the second flip, and if so is it a match for the first? | ||
const newFaceUpCards = newCards.filter(c => c.isFaceUp && !c.isMatched); | ||
if (newFaceUpCards.length === 2) { | ||
const [firstCard, secondCard] = newFaceUpCards; | ||
if (firstCard.value === secondCard.value) { | ||
// cards match, mark them as matched and keep them face up: | ||
setCards(newCards.map(c => | ||
c.value === firstCard.value ? { ...c, isMatched: true } : c | ||
)); | ||
} else { | ||
// cards don't match, flip them back face-down after a delay: | ||
setTimeout(() => { | ||
setCards(cards => cards.map(c => | ||
c.id === firstCard.id || c.id === secondCard.id | ||
? { ...c, isFaceUp: false } | ||
: c | ||
)); | ||
}, 1000); | ||
} | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const handleCardClick = (card: Card) => { | |
// do nothing if card is already face up or matched: | |
if (card.isFaceUp || card.isMatched) { | |
return; | |
} | |
// do nothing if there's already two actively face-up cards: | |
const faceUpCards = cards.filter(c => c.isFaceUp && !c.isMatched); // TODO: do we care about O(N) here? probably not | |
if (faceUpCards.length >= 2) { | |
return; | |
} | |
// flip the card face-up: | |
const newCards = cards.map(c => | |
c.id === card.id ? { ...c, isFaceUp: true } : c | |
); | |
setCards(newCards); | |
// is this the second flip, and if so is it a match for the first? | |
const newFaceUpCards = newCards.filter(c => c.isFaceUp && !c.isMatched); | |
if (newFaceUpCards.length === 2) { | |
const [firstCard, secondCard] = newFaceUpCards; | |
if (firstCard.value === secondCard.value) { | |
// cards match, mark them as matched and keep them face up: | |
setCards(newCards.map(c => | |
c.value === firstCard.value ? { ...c, isMatched: true } : c | |
)); | |
} else { | |
// cards don't match, flip them back face-down after a delay: | |
setTimeout(() => { | |
setCards(cards => cards.map(c => | |
c.id === firstCard.id || c.id === secondCard.id | |
? { ...c, isFaceUp: false } | |
: c | |
)); | |
}, 1000); | |
} | |
} | |
}; | |
const faceUpCards = useMemo( | |
() => cards.filter((c) => c.isFaceUp && !c.isMatched), | |
[cards] | |
); | |
useEffect(() => { | |
if (faceUpCards.length !== 2) { | |
return; | |
} | |
const [firstCard, secondCard] = faceUpCards; | |
if (firstCard.value === secondCard.value) { | |
// cards match, mark them as matched and keep them face up: | |
setCards((cards) => | |
cards.map((c) => | |
c.value === firstCard.value ? { ...c, isMatched: true } : c | |
) | |
); | |
} else { | |
// cards don't match, flip them back face-down after a delay: | |
setTimeout(() => { | |
setCards((cards) => | |
cards.map((c) => | |
c.id === firstCard.id || c.id === secondCard.id | |
? { ...c, isFaceUp: false } | |
: c | |
) | |
); | |
}, 1000); | |
} | |
}, [cards, faceUpCards]); | |
const handleCardClick = (card: Card) => { | |
// do nothing if card is already face up or matched | |
// or if there's already two actively face-up cards: | |
if (card.isFaceUp || card.isMatched || faceUpCards.length >= 2) { | |
return; | |
} | |
// flip the card face-up: | |
const newCards = cards.map((c) => | |
c.id === card.id ? { ...c, isFaceUp: true } : c | |
); | |
setCards(newCards); | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This suggestion isn't strictly necessary but does move state management out of the click handler and slightly deduplicates code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Updated.
Remove content flash on page load
When two cards are flipped, checks if they’re a match, and if so, marks them as such and ignores them for the rest of the game; otherwise, flips them back over after a delay.
Also:
handleCardClick
could probably use a close look from someone who understands state management in React better than me.