RxJS 배우기
  • 소개
  • RxJS 배우기
    • 연산자
      • Combination
        • combineAll
        • combineLatest
        • concat
        • concatAll
        • endWith
        • forkJoin
        • merge
        • mergeAll
        • pairwise
        • race
        • startWith
        • withLatestFrom
        • zip
      • Conditional
        • defaultIfEmpty
        • every
        • iif
        • sequenceEqual
      • Creation
        • ajax
        • create
        • defer
        • empty
        • from
        • fromEvent
        • generate
        • interval
        • of
        • range
        • throw
        • timer
      • Error Handling
        • catch / catchError
        • retry
        • retryWhen
      • Multicasting
        • publish
        • multicast
        • share
        • shareReplay
      • Filtering
        • audit
        • auditTime
        • debounce
        • debounceTime
        • distinct
        • distinctUntilChanged
        • distinctUntilKeyChanged
        • filter
        • find
        • first
        • ignoreElements
        • last
        • sample
        • single
        • skip
        • skipUntil
        • skipWhile
        • take
        • takeLast
        • takeUntil
        • takeWhile
        • throttle
        • throttleTime
      • Transformation
        • buffer
        • bufferCount
        • bufferTime
        • bufferToggle
        • bufferWhen
        • concatMap
        • concatMapTo
        • exhaustMap
        • expand
        • groupBy
        • map
        • mapTo
        • mergeMap / flatMap
        • mergeScan
        • partition
        • pluck
        • reduce
        • scan
        • switchMap
        • switchMapTo
        • toArray
        • window
        • windowCount
        • windowTime
        • windowToggle
        • windowWhen
      • Utility
        • tap / do
        • delay
        • delayWhen
        • dematerialize
        • finalize / finally
        • let
        • repeat
        • timeInterval
        • timeout
        • timeoutWith
        • toPromise
      • 전체 목록
    • Subjects
      • AsyncSubject
      • BehaviorSubject
      • ReplaySubject
      • Subject
    • 사용예시
      • Alphabet Invasion Game
      • Battleship Game
      • Breakout Game
      • Car Racing Game
      • Catch The Dot Game
      • Click Ninja Game
      • Flappy Bird Game
      • Game Loop
      • Horizontal Scroll Indicator
      • Http Polling
      • Lockscreen
      • Matrix Digital Rain
      • Memory Game
      • Mine Sweeper Game
      • Platform Jumper Game
      • Progress Bar
      • Save Indicator
      • Smart Counter
      • Space Invaders Game
      • Stop Watch
      • Swipe To Refresh
      • Tank Battle Game
      • Tetris Game
      • Type Ahead
      • Uncover Image Game
    • 개념
      • RxJS 입문서
      • RxJS v5 -> v6 업그레이드
      • 시간 기반의 연산자 비교
      • 연산자 imports의 이해
Powered by GitBook
On this page
  • Example Code
  • index.ts
  • index.html
  • Operators Used

Was this helpful?

  1. RxJS 배우기
  2. 사용예시

Memory Game

PreviousMatrix Digital RainNextMine Sweeper Game

Last updated 5 years ago

Was this helpful?

By

This recipe demonstrates an RxJS game to train your memory.

Example Code

( )

Memory Game

index.ts

// RxJS v6+
import { EMPTY, from, fromEvent, generate, interval, merge, noop } from 'rxjs';
import {
  map,
  pluck,
  scan,
  sequenceEqual,
  switchMap,
  take,
  tap
} from 'rxjs/operators';

const random = (): number => Math.floor(Math.random() * Math.floor(8));
const setInfo = (text: string) =>
  (document.getElementById('info').innerHTML = text);
const displayLevelChange = () =>
  document
    .querySelectorAll('.child')
    .forEach((c: HTMLElement) => (c.style.background = 'gray'));

const checkIfGameOver$ = (randomSequence: number[]) => (
  userSequence: number[]
) =>
  from(userSequence).pipe(
    sequenceEqual(from(randomSequence)),
    tap(match =>
      !match && userSequence.length === randomSequence.length
        ? setInfo('GAME OVER!')
        : noop
    )
  );

const takePlayerInput$ = (randomSequence: number[]) => _ =>
  fromEvent(document, 'click').pipe(
    take(randomSequence.length),
    scan(
      (acc: number[], curr: MouseEvent) => [
        ...acc,
        parseInt(curr.target['id'])
      ],
      []
    ),
    switchMap(checkIfGameOver$(randomSequence)),
    switchMap(result =>
      result
        ? (displayLevelChange(), memoryGame$(randomSequence.length + 1))
        : EMPTY
    )
  );

const showSequenceToMemorize$ = (memorySize: number) => (
  randomSequence: number[]
) =>
  interval(1000).pipe(
    tap(i =>
      setInfo(i === memorySize - 1 ? `YOUR TURN` : `${memorySize - i} elements`)
    ),
    take(randomSequence.length),
    map(index => randomSequence[index]),
    tap(value => document.getElementById(`${value}`).click()),
    switchMap(takePlayerInput$(randomSequence))
  );

const memoryGame$ = memorySize =>
  generate(1, x => x <= memorySize, x => x + 1).pipe(
    scan((acc: number[], _: number): number[] => [...acc, random() + 1], []),
    switchMap(showSequenceToMemorize$(memorySize))
  );

const elementClick$ = (event: string, color: string) =>
  fromEvent(document.querySelectorAll('.child'), event).pipe(
    pluck('srcElement'),
    tap((e: HTMLElement) => (e.style.background = color))
  );

const clicks$ = merge(
  elementClick$('click', 'lightgray'),
  elementClick$('transitionend', 'white')
);

const game$ = merge(clicks$, memoryGame$(2));

game$.subscribe();

index.html

<style>
  .parent {
    border-spacing: 5px;
    width: 50%;
    padding: 0.5em;
  }

  .parent.perspective {
    perspective: 50em;
  }

  .child {
    margin: 0.5em;
    max-width: 2em;
    min-width: 2em;
    height: 2.8em;
    padding: 0.5em;
    display: table-cell;
    border: 1px solid rgba(0, 0, 0, 0.5);
  }

  .parent.perspective .child {
    transform: rotateX(40deg);
    transition: all 0.3s ease-in;
  }
</style>

<div id="info">Train Your Memory!</div>
<div id="grid" class="grid parent perspective">
  <div>
    <div class="child" id="1"></div>
    <div class="child" id="2"></div>
    <div class="child" id="3"></div>
  </div>
  <div>
    <div class="child" id="4"></div>
    <div class="child" id="5"></div>
    <div class="child" id="6"></div>
  </div>
  <div>
    <div class="child" id="7"></div>
    <div class="child" id="8"></div>
    <div class="child" id="9"></div>
  </div>
</div>

Operators Used

  • noop

empty
from
fromEvent
generate
interval
map
merge
pluck
scan
sequenceEqual
switchMap
take
tap
adamlubek
StackBlitz