forest-im / minesweeper

πŸ’£React Class μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΄μš©ν•΄ λ§Œλ“  지뒰 μ°ΎκΈ° κ²Œμž„μž…λ‹ˆλ‹€. Easy, Medium, Hard, Extream 4κ°€μ§€μ˜ λͺ¨λ“œλ₯Ό κ²½ν—˜ν•΄λ³Ό 수 있고, μ›Ή λΈŒλΌμš°μ €, λͺ¨λ°”μΌμ—μ„œ κ²Œμž„μ„ 즐길 수 μžˆμŠ΅λ‹ˆλ‹€.

Home Page:https://minesweeper-by-alex.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

지뒰 μ°ΎκΈ° κ²Œμž„

mines

μΆ”μ–΅μ˜ 지뒰 μ°ΎκΈ° κ²Œμž„μž…λ‹ˆλ‹€. Easy, Medium, Hard, Extream 4κ°€μ§€μ˜ λͺ¨λ“œλ₯Ό κ²½ν—˜ν•΄λ³Ό 수 있고, μ›Ή λΈŒλΌμš°μ €, λͺ¨λ°”μΌμ—μ„œ κ²Œμž„μ„ 즐길 수 μžˆμŠ΅λ‹ˆλ‹€.


Table of contents


Build & Installation

배포 μ‚¬μ΄νŠΈλ‘œ κ°€κΈ°

npm install
npm start

Introduction

React의 Class component와 React-Redux connect(mapStateToProps, mapDispatchToProps)λ₯Ό μ‚¬μš©ν•œ ν”„λ‘œμ νŠΈμž…λ‹ˆλ‹€.


Goal

ν˜„μž¬ ꢌμž₯ν•˜λŠ” 방법이 μ•„λ‹Œ 이전에 많이 썼던 방법을 κ²½ν—˜ν•΄λ΄„μœΌλ‘œμ¨ React와 Reduxκ°€ μ–΄λ–€ λ°©ν–₯으둜 μ—…λ°μ΄νŠΈλ˜κ³  μ–΄λ–€ 점을 κ°œμ„ ν–ˆλŠ”μ§€ 더 이해할 수 μžˆλŠ” 것을 λͺ©ν‘œλ‘œ μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€. 그리고 ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ™€ Redux νˆ΄ν‚· μ‚¬μš©μ„ 주둜 ν•˜λ©΄μ„œ λ†“μ³€λ˜ κΈ°λ³ΈκΈ°λ₯Ό λ‹€μ§€λŠ” 것도 ν•¨κ»˜ λͺ©ν‘œλ‘œ μ„€μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


Motivation

React에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ‹€ 보면 Class μ»΄ν¬λ„ŒνŠΈμ™€ ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλ₯Ό λΉ„κ΅ν•˜λ©° μ„€λͺ…ν•˜λŠ” 글이 λ§Žμ•˜μŠ΅λ‹ˆλ‹€. ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλ₯Ό 주둜 μ“°λ‹€ λ³΄λ‹ˆ Class μ»΄ν¬λ„ŒνŠΈμ™€μ˜ 비ꡐ가 잘 와 닿지 μ•ŠλŠ” 뢀뢄이 생겨 κ·Έ ν‹ˆμ„ λ©”κΎΈκ³ μž Class μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚¬μš©ν•œ λ―Έλ‹ˆ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이전에 μ‚¬μš©ν–ˆλ˜ 방식을 κ²½ν—˜ν•΄λ³΄κ³  λ‚˜λ©΄, μ§€κΈˆμ˜ 방법과 μ΄μ „μ˜ λ°©λ²•μ˜ 차이λ₯Ό 더 λͺ…ν™•νžˆ μ•Œ 수 μžˆμ„ 것 κ°™μ•„ 쒋은 κ²½ν—˜μ΄ 될 κ²ƒμœΌλ‘œ μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.


기술 μŠ€νƒ

  • React 18, cra(create-react-app)λ₯Ό ν™œμš©ν–ˆμŠ΅λ‹ˆλ‹€.

  • React Router Dom을 μ΄μš©ν•΄ λΌμš°νŒ…μ„ μ²˜λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

  • Redux, React-Redux μ „μ—­ μƒνƒœ 관리 νˆ΄μ„ μ΄μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

  • Tailwind CSS ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

    Dependencies Version
    react ^18.2.0
    react-redux ^8.0.5
    redux ^4.2.0
    react-router-dom ^6.7.0
    tailwindcss ^3.2.4

Schedule

Date Schedule
23.01.23 μŠ€μΌ€μ€„ μ„€μ • 및 κΈ°λŠ₯ κ΅¬ν˜„ 방법 탐색
23.01.24 κΈ°λŠ₯ κ΅¬ν˜„
23.01.25 κΈ°λŠ₯ κ΅¬ν˜„
23.01.25 버그 μˆ˜μ •, 배포
23.01.26 버그 μˆ˜μ •

Feature

μƒνƒœ 관리

// status reducer
const initialState = {
  gameStatus: GAME_STATUS.START,
  mode: "easy",
  table: [],
  row: 0,
  col: 0,
  minesCount: 0,
  minesIndexObj: {},
  finishCellCount: 0,
};

...
// base reducer
const initialState = {
  isModalShowing: false,
};
  • κ²Œμž„κ³Ό κ΄€λ ¨λœ μƒνƒœ, κ΄€λ ¨λ˜μ§€ μ•Šμ€ μƒνƒœ 두 κ°€μ§€λ‘œ λ‚˜λˆ„μ–΄ μƒνƒœ 관리λ₯Ό ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.
  • minesIndexObj: 지뒰가 μœ„μΉ˜ν•œ indexλ₯Ό object에 κΈ°λ‘ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€. λΉ λ₯Έ 탐색을 μœ„ν•΄ 배열이 μ•„λ‹Œ 객체λ₯Ό μ„ νƒν–ˆμŠ΅λ‹ˆλ‹€.

지뒰 생성

import React from "react";
import { useParams } from "react-router-dom";

const withParams = Child => {
  return function hoc(props) {
    const params = useParams();

    return <Child {...props} params={params} />;
  };
};

export default withParams;
  • μ„ νƒν•œ κ²Œμž„ λͺ¨λ“œμ— λ§žλŠ” 지뒰 개수둜 랜덀 λ‚œμˆ˜λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. μœ μ €κ°€ 처음 셀을 ν΄λ¦­ν–ˆμ„ λ•Œ 지뒰λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. μ‚¬μš©μž κ²½ν—˜μ„ μœ„ν•΄ 처음 μ„ νƒλœ 셀은 랜덀 λ‚œμˆ˜μ—μ„œ μ œμ™Έν–ˆμŠ΅λ‹ˆλ‹€. μ„ νƒν•œ κ²Œμž„ λͺ¨λ“œλŠ” μƒνƒœ 관리 ν•˜μ§€ μ•Šκ³  paramsλ₯Ό μ΄μš©ν•΄ action의 인자둜 μ „λ‹¬ν–ˆμŠ΅λ‹ˆλ‹€. class componentμ—μ„œ react router의 useParams 훅을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ withParamsλΌλŠ” HOCλ₯Ό λ§Œλ“€μ–΄ μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.

ν΄λ¦­ν•œ μ…€ μ£Όμœ„ 탐색 (DFS ν™œμš©)

  • μœ μ €κ°€ ν΄λ¦­ν•œ 셀이 지뒰가 아닐 경우 μ£Όμœ„ 지뒰 개수λ₯Ό ν‘œμ‹œν•˜κ³ , μ£Όμœ„μ— 지뒰가 μ—†μœΌλ©΄ 지뒰가 μžˆλŠ” κ³³κΉŒμ§€ 셀을 μ—΄μ–΄μ€λ‹ˆλ‹€. DFS μ•Œκ³ λ¦¬μ¦˜μ„ μ΄μš©ν•΄ μ£Όμœ„ μ…€ ν•˜λ‚˜λ₯Ό ν™•μΈν•˜κ³  μ£Όμœ„μ— 지뒰가 μžˆμ„ λ•ŒκΉŒμ§€ 깊이 νƒμƒ‰ν•œ ν›„ 탐색을 마치면 λ‹€μŒ 셀을 νƒμƒ‰ν•˜λŠ” 방법을 μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.
  1. ν΄λ¦­ν•œ μ…€μ˜ μ£Όμœ„ μ…€ 데이터λ₯Ό aroundCellDataλΌλŠ” 배열에 push ν•©λ‹ˆλ‹€.
  2. aroundCellData을 μˆœνšŒν•˜λ©° ν•˜λ‚˜μ”© popν•΄μ€€ ν›„ cell이 지뒰인지 빈 셀인지 ν™•μΈν•˜κ³  빈 셀이라면 aroundEmptyCellArray 배열에 pushν•΄μ€λ‹ˆλ‹€.
  3. aroundEmptyCellArray λ°°μ—΄μ˜ κ°œμˆ˜κ°€ 8개라면 μ£Όμœ„ 셀이 λ‹€ λΉ„μ–΄μžˆλŠ” κ²ƒμ΄λ―€λ‘œ forEachλ₯Ό μ΄μš©ν•΄ μž¬κ·€λ₯Ό μ‹€ν–‰μ‹œν‚΅λ‹ˆλ‹€.
  4. aroundEmptyCellArray λ°°μ—΄μ˜ κ°œμˆ˜κ°€ 8κ°œκ°€ μ•„λ‹ˆλΌλ©΄ μ£Όμœ„ 셀에 지뒰가 μžˆλŠ” κ²ƒμ΄λ―€λ‘œ aroundEmptyCellArray λ°°μ—΄μ˜ 지뒰 개수λ₯Ό νŒλ³„ν•΄ ν΄λ¦­ν•œ μ…€μ˜ λ°μ΄ν„°λ‘œ μž…λ ₯ν•©λ‹ˆλ‹€.

μ–΄λ €μ› λ˜ 점


  • 셀이 쀑간에 μžˆλŠ” 경우 μœ„ μ…€, μ–‘μ˜†μ˜ μ…€, μ•„λž˜ 셀이 λͺ¨λ‘ μ‘΄μž¬ν•˜μ§€λ§Œ, 셀이 제일 μœ„, μ•„λž˜, μ™Όμͺ½, 였λ₯Έμͺ½μ— μžˆλŠ” 경우 μ£Όμœ„ μ…€ κ°œμˆ˜κ°€ 8κ°œκ°€ μ•„λ‹ˆκ²Œ λ˜λŠ” 뢀뢄을 μ²˜λ¦¬ν•˜λŠ” 게 생각보닀 μ–΄λ €μ› μŠ΅λ‹ˆλ‹€. outsideCellCountμ΄λΌλŠ” λ³€μˆ˜λ₯Ό λ§Œλ“€μ–΄ 셀이 μ—†λŠ” 개수λ₯Ό 체크해 쑰건문으둜 μ²˜λ¦¬ν•΄μ„œ ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.

Cell Flag μƒμˆ˜λ‘œ μ •μ˜

const FLAG = {
  MINE: -1,
  AROUND_ALL_EMPTY: 9,
  EMPTY: 10,
  OPENED: 11,
  QUESTION_MARK: 12,
  MINE_FLAG: 13,
};
  • μ…€μ˜ 데이터 νƒ€μž…μ„ 숫자둜 μ •μ˜ν–ˆμŠ΅λ‹ˆλ‹€. λͺ…μ‹œμ μΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κΈ° μœ„ν•΄ flagλ₯Ό μƒμˆ˜λ‘œ μ²˜λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ…€ μ»΄ν¬λ„ŒνŠΈ μ΅œμ ν™”

  • PureComponentλ₯Ό μ‚¬μš©ν•˜μ—¬ μ΅œμ ν™”λ₯Ό ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. μ…€ μ»΄ν¬λ„ŒνŠΈμΈ TD μ»΄ν¬λ„ŒνŠΈμ— μ μš©ν•΄ λ³€κ²½λœ μ»΄ν¬λ„ŒνŠΈλ§Œ λ¦¬λ Œλ”λ§ λ˜λ„λ‘ ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.

배운 점과 λŠλ‚€ 점

  • class에 λŒ€ν•΄μ„œ 쑰금 더 μΉœμˆ™ν•˜κ²Œ λŠκ»΄μ§€λŠ” 계기가 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. class 문법이 μ΅μˆ™ν•˜μ§€ μ•Šμ•„ λˆˆμ— 잘 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜λŠ”λ° μ΄μ œλŠ” ν”„λ‘œμ νŠΈ 전보닀 μ΅μˆ™ν•˜κ²Œ μ‚¬μš©ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
  • ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ—μ„œ useEffect만 맀번 μ“°λ‹€κ°€ class μ»΄ν¬λ„ŒνŠΈμ˜ 라이프 사이클을 λ‹€λ£¨λŠ” λ©”μ„œλ“œλ“€μ„ μ“°λ‹ˆ μƒ‰λ‹¬λžμŠ΅λ‹ˆλ‹€. class μ»΄ν¬λ„ŒνŠΈλΌμ„œ μ’€ 더 λΆˆνŽΈν•  쀄 μ•Œμ•˜λŠ”λ° 생각보닀 λ©”μ„œλ“œ λͺ…듀이 λͺ…ν™•ν•˜μ—¬ useEffect보닀 μ΄ν•΄ν•˜κΈ° μ‰¬μ› μŠ΅λ‹ˆλ‹€.
  • Redux toolkit을 쓰지 μ•Šκ³ , κΈ°λ³Έν˜•μ„ κ·ΈλŒ€λ‘œ μ“°λ‹€ λ³΄λ‹ˆ λ§Žμ€ λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈκ°€ μƒκΈ°κ²Œ λλŠ”λ°, κ°œλ…μ„ μ’€ 더 μ΄ν•΄ν•˜κ³  μ‚¬μš©ν•˜λ‹€ λ³΄λ‹ˆ 크게 κ±°μŠ¬λ¦¬μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μ΄μ œλŠ” 였히렀 더 λͺ…ν™•ν•œ λŠλ‚Œμ΄ λ“€μ—ˆκ³  κ·Έμ „μ—” μ œλŒ€λ‘œ μ•Œκ³  μ‚¬μš©ν•œ 게 μ•„λ‹ˆλΌλŠ” 생각이 λ“€μ—ˆμŠ΅λ‹ˆλ‹€.

μ•„μ‰¬μš΄ 점

  • ν”„λ‘œμ νŠΈ 기간을 짧게 μ„€μ •ν•˜μ—¬ UI와 κΈ°λŠ₯λ“€μ˜ λ””ν…ŒμΌμ„ 더 살리지 λͺ»ν•œ 점이 μ•„μ‰¬μ› μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ 처음 κΈ°νšν–ˆλ˜ ν”„λ‘œμ νŠΈ λͺ©ν‘œλŠ” λ‹¬μ„±ν•˜μ—¬ 좔후에 μ‘°κΈˆμ”© 더 μ—…λ°μ΄νŠΈλ₯Ό ν•΄λ³΄κ³ μž ν•©λ‹ˆλ‹€.
  • container-presenterνŒ¨ν„΄μ„ μ μš©ν•˜κΈ° μœ„ν•΄ μ‹œλ„ν–ˆμ§€λ§Œ, container둜 λΆ„λ¦¬ν•œ μ»΄ν¬λ„ŒνŠΈλ₯Ό 아직 μ™„λ²½νžˆ μΆ”μƒν™”ν•˜μ§€ λͺ»ν•œ 점이 μ•„μ‰¬μ› μŠ΅λ‹ˆλ‹€. μ»΄ν¬λ„ŒνŠΈ 내에 μŠ€νƒ€μΌκ³Ό λ§ˆν¬μ—…μ΄ ν•¨κ»˜ λ“€μ–΄κ°€ μžˆμ–΄ μ’€ 더 뢄리가 ν•„μš”ν•  것 κ°™μŠ΅λ‹ˆλ‹€.
  • class μ»΄ν¬λ„ŒνŠΈμ—μ„œ ν•¨μˆ˜, λ³€μˆ˜λ₯Ό λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•˜μ—¬ μ΅œμ ν™”ν•˜μ§€ λͺ»ν•œ 점이 μ•„μ‰¬μ› μŠ΅λ‹ˆλ‹€. PureComponentλ₯Ό μ‚¬μš©ν•˜κΈ΄ ν–ˆμœΌλ‚˜ 아직도 λ§Žμ€ λ Œλ”λ§μ΄ μΌμ–΄λ‚˜ 셀이 λ§Žμ€ Extream λͺ¨λ“œμ—μ„œλŠ” 화면을 쀄일 λ•Œ λ²„λ²…μž„μ΄ μ‹¬ν•©λ‹ˆλ‹€. 이 뢀뢄에 λŒ€ν•΄μ„œλŠ” μ’€ 더 κ³ λ―Όν•˜μ—¬ μ—…λ°μ΄νŠΈ ν•΄μ•Ό ν•  것 κ°™μŠ΅λ‹ˆλ‹€.
  • tailwindλ₯Ό μ΄λ²ˆμ— 처음 μ‚¬μš©ν•΄λ³΄μ•˜λŠ”λ° 읡힐 μ‹œκ°„μ΄ 적어 tailwind의 μž₯점을 μ œλŒ€λ‘œ μ‚¬μš©ν•΄λ³΄μ§€ λͺ»ν•œ 점이 μ•„μ‰¬μ› μŠ΅λ‹ˆλ‹€. 아직은 κΉ”λ”ν•˜κ²Œ μŠ€νƒ€μΌ 적용이 μž˜λ˜μ§€ μ•Šμ•„μ„œ μ–΄λ €μš΄ 뢀뢄이 λ§Žμ•˜λŠ”λ°, 적응 μ΄ν›„μ—λŠ” custom class λ“± λͺ¨λ“ˆν™”ν•  수 μžˆλ‹€λŠ” μž₯점을 잘 μ‚¬μš©ν•  수 μžˆμ„ 것 κ°™μ•„ ν•œνŽΈμœΌλ‘œλŠ” κΈ°λŒ€λ˜λŠ” 마음이 λ“€κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ’€ 더 μ •λ¦¬ν•˜λŠ” μ‹œκ°„μ„ 가진 ν›„ μ‚¬μš©ν•΄λ³΄κ³ μž ν•©λ‹ˆλ‹€.

About

πŸ’£React Class μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΄μš©ν•΄ λ§Œλ“  지뒰 μ°ΎκΈ° κ²Œμž„μž…λ‹ˆλ‹€. Easy, Medium, Hard, Extream 4κ°€μ§€μ˜ λͺ¨λ“œλ₯Ό κ²½ν—˜ν•΄λ³Ό 수 있고, μ›Ή λΈŒλΌμš°μ €, λͺ¨λ°”μΌμ—μ„œ κ²Œμž„μ„ 즐길 수 μžˆμŠ΅λ‹ˆλ‹€.

https://minesweeper-by-alex.netlify.app/


Languages

Language:JavaScript 92.6%Language:HTML 6.2%Language:CSS 1.2%