-
Notifications
You must be signed in to change notification settings - Fork 0
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
[7주차 기본 과제] 🌈 카드게임 리팩토링 #8
base: main
Are you sure you want to change the base?
Changes from all commits
e35befe
2efb097
bd7ade0
7ae5cb3
77171db
ef39127
50f84e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module.exports = { | ||
env: { browser: true, es2020: true, node: true }, | ||
extends: [ | ||
"eslint:recommended", | ||
"plugin:react/recommended", | ||
"plugin:react/jsx-runtime", | ||
"plugin:react-hooks/recommended", | ||
], | ||
parserOptions: { ecmaVersion: "latest", sourceType: "module" }, | ||
settings: { react: { version: "18.2" } }, | ||
plugins: ["react-refresh"], | ||
rules: { | ||
"react-refresh/only-export-components": "warn", | ||
"react/prop-types": "off", | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Cats Rule!</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "matchthecard", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0", | ||
"preview": "vite preview" | ||
}, | ||
"dependencies": { | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"recoil": "^0.7.7", | ||
"styled-components": "^5.3.10", | ||
"tsc": "^2.0.4" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.0.28", | ||
"@types/react-dom": "^18.0.11", | ||
"@vitejs/plugin-react": "^4.0.0", | ||
"eslint": "^8.38.0", | ||
"eslint-plugin-react": "^7.32.2", | ||
"eslint-plugin-react-hooks": "^4.6.0", | ||
"eslint-plugin-react-refresh": "^0.3.4", | ||
"typescript": "^5.1.3", | ||
"vite": "^4.3.2" | ||
}, | ||
"resolutions": { | ||
"styled-components": "^5" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#root { | ||
width: 100%; | ||
min-height: 800px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
background-color: rgba(0, 0, 0, 0.877); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { useEffect } from "react"; | ||
import "./App.css"; | ||
import styled from "styled-components"; | ||
import Header from "./components/Header"; | ||
import Mode from "./components/Mode"; | ||
import cat from "./assets/cat"; | ||
import CardSection from "./components/CardSection"; | ||
import Score from "./components/Score"; | ||
import Reset from "./components/Reset"; | ||
import { useRecoilState } from "recoil"; | ||
import { selectedMode } from "./recoil/atom/selectedMode"; | ||
import { totalCardNum } from "./recoil/atom/totalCardNum"; | ||
import { | ||
totalCards, | ||
currentCards, | ||
matchedCards, | ||
} from "./recoil/atom/cardArrays"; | ||
import React from "react"; | ||
|
||
function App() { | ||
const [mode, setMode] = useRecoilState(selectedMode); | ||
const [totalCard, setTotalCard] = useRecoilState(totalCards); | ||
|
||
const [currentCard, setCurrentCard] = useRecoilState(currentCards); | ||
const [matchedCard, setMatchedCard] = useRecoilState(matchedCards); | ||
const [totalCardCount, setTotalCardCount] = useRecoilState(totalCardNum); | ||
|
||
//mode가 변경될 때마다 자동으로 게임 리셋해서 카드 재생성 | ||
useEffect(() => { | ||
resetGame(); | ||
}, [mode]); | ||
|
||
//변경된 모드에 따라 생성될 총 카드 짝의 갯수 지정 | ||
function handleModeChange(mode: string) { | ||
setMode(mode); | ||
if (mode === "EASY") { | ||
setTotalCardCount(5); | ||
} else if (mode === "NORMAL") { | ||
setTotalCardCount(7); | ||
} else if (mode === "HARD") { | ||
setTotalCardCount(9); | ||
} | ||
resetGame(); | ||
} | ||
|
||
//카드 클릭 시 이미 선택된 카드인지, 선택된 카드가 이미 1개 있는지 확인 후 맞다면 카드 짝을 확인하는 함수 호출 아니라면 이미 짝이 맞춰진 카드에 있는지 확인 후 없다면 선택된 카드 array에 담는다 | ||
function handleCardClick(index: number) { | ||
if (currentCard.length === 1 && !currentCard.includes(index)) { | ||
checkCardMatched(index); | ||
} else if (!matchedCard.includes(index)) { | ||
setCurrentCard([index]); | ||
} | ||
} | ||
|
||
//카드 짝 확인하는 함수 | ||
//카드 짝이 맞다면 matchedCard 에 담고 아니라면 1초 후 다시 선택해제되고 선택된 카드 array를 비워준다 | ||
function checkCardMatched(index: number) { | ||
const cardName = totalCard[index]; | ||
if (totalCard[currentCard[0]] === cardName) { | ||
setMatchedCard([...matchedCard, index, currentCard[0]]); | ||
setCurrentCard([]); | ||
} else { | ||
setCurrentCard([...currentCard, index]); | ||
setTimeout(() => { | ||
setCurrentCard([]); | ||
}, 1000); | ||
} | ||
} | ||
|
||
function resetGame() { | ||
const allCatsRandom: string[] = cat | ||
.sort(() => Math.random() - 0.5) | ||
.slice(0, totalCardCount) | ||
.map((eachCat) => eachCat.name); | ||
|
||
setTotalCard( | ||
[...allCatsRandom, ...allCatsRandom].sort(() => Math.random() - 0.5) | ||
); | ||
Comment on lines
+71
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 크 넘조타 |
||
setMatchedCard([]); | ||
setCurrentCard([]); | ||
} | ||
|
||
return ( | ||
<> | ||
<Reset resetGame={resetGame}></Reset> | ||
<Header> | ||
<Score /> | ||
</Header> | ||
<Body> | ||
<Mode handleModeChange={handleModeChange} /> | ||
<CardSection handleCardClick={handleCardClick} /> | ||
</Body> | ||
</> | ||
); | ||
} | ||
|
||
export default App; | ||
|
||
const Body = styled.section` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
declare module "*.jpeg"; | ||
declare module "*.png"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import cat1 from "./images/cat1.jpeg"; | ||
import cat2 from "./images/cat2.jpeg"; | ||
import cat3 from "./images/cat3.jpeg"; | ||
import cat4 from "./images/cat4.jpeg"; | ||
import cat5 from "./images/cat5.jpeg"; | ||
import cat6 from "./images/cat6.jpeg"; | ||
import cat7 from "./images/cat7.jpeg"; | ||
import cat8 from "./images/cat8.png"; | ||
import cat9 from "./images/cat9.jpeg"; | ||
|
||
export interface catInfo { | ||
name: string; | ||
src: string; | ||
} | ||
const cat: catInfo[] = [ | ||
{ | ||
name: "cat1", | ||
src: cat1, | ||
}, | ||
{ | ||
name: "cat2", | ||
src: cat2, | ||
}, | ||
{ | ||
name: "cat3", | ||
src: cat3, | ||
}, | ||
{ | ||
name: "cat4", | ||
src: cat4, | ||
}, | ||
{ | ||
name: "cat5", | ||
src: cat5, | ||
}, | ||
{ | ||
name: "cat6", | ||
src: cat6, | ||
}, | ||
{ | ||
name: "cat7", | ||
src: cat7, | ||
}, | ||
{ | ||
name: "cat8", | ||
src: cat8, | ||
}, | ||
{ | ||
name: "cat9", | ||
src: cat9, | ||
}, | ||
]; | ||
|
||
export default cat; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import styled, { css } from "styled-components"; | ||
import React from "react"; | ||
|
||
interface CardProps { | ||
imageSrc?: string; | ||
imageName: string; | ||
onClick: () => void; | ||
isOpen: boolean; | ||
} | ||
|
||
function Card({ imageSrc, onClick, isOpen, imageName }: CardProps) { | ||
return ( | ||
<CardWrapper isOpen={isOpen} onClick={onClick}> | ||
<CardInner isOpen={isOpen}> | ||
<FrontArticle> | ||
<Image src={imageSrc} alt={imageName} isOpen={isOpen} /> | ||
</FrontArticle> | ||
<BackArticle> | ||
<Image | ||
src="https://www.svgrepo.com/show/454281/cat-halloween-kitty.svg" | ||
alt="default cat" | ||
/> | ||
</BackArticle> | ||
</CardInner> | ||
</CardWrapper> | ||
); | ||
} | ||
Comment on lines
+4
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 머야 넘 깔꼼쓰!! |
||
|
||
export default Card; | ||
|
||
const CardWrapper = styled.section` | ||
perspective: 1000px; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 옹 3D요소 원근효과 주는 속성!!!!! 첨 알았땅!!! |
||
&:hover { | ||
cursor: pointer; | ||
} | ||
&.open { | ||
box-shadow: 7px 7px papayawhip; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이색깔 처음봥 ㅋㅋㅋㅋㅋ 이름 귀엽다 ㅜㅜ |
||
} | ||
`; | ||
|
||
const Image = styled.img` | ||
border-radius: 10px; | ||
width: 180px; | ||
height: 220px; | ||
`; | ||
|
||
const BackArticle = styled.article` | ||
position: absolute; | ||
display: flex; | ||
justify-content: center; | ||
width: 200px; | ||
height: 240px; | ||
padding: 5px; | ||
transform: rotateY(180deg); | ||
backface-visibility: hidden; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헐 일케 앞뒷면 보이게 구현한거구나....... 대박 이것도 첨알았어 너무신기해!!!!!3D!!!!!!!!!! |
||
`; | ||
const FrontArticle = styled.article` | ||
position: absolute; | ||
display: flex; | ||
justify-content: center; | ||
padding: 10px; | ||
backface-visibility: hidden; | ||
`; | ||
|
||
const CardInner = styled.article` | ||
position: relative; | ||
transition: transform 0.6s; | ||
transform-style: preserve-3d; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 폼 미쳤다... 이런거 대체 어디서!!!!! 찾는거야!!!!!!! |
||
width: 200px; | ||
height: 243px; | ||
border-radius: 10px; | ||
${(props) => | ||
props.isOpen | ||
? css` | ||
transform: rotateY(0); | ||
background-color: #ffbd52; | ||
box-shadow: 7px 7px #9d7434; | ||
` | ||
: css` | ||
transform: rotateY(180deg); | ||
background-color: papayawhip; | ||
box-shadow: -7px 7px #f4ab4c; | ||
`} | ||
`; |
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.
요거 switch-case 써두 되겠당!!!ㅎㅎ