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
  • mines.ts
  • constants.ts
  • html-renderer.ts
  • Operators Used

Was this helpful?

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

Mine Sweeper Game

PreviousMemory GameNextPlatform Jumper Game

Last updated 5 years ago

Was this helpful?

By

This recipe demonstrates RxJS implementation of Mine Sweeper Game.

Example Code

( )

Mine Sweeper

index.ts

// RxJS v6+
import { fromEvent, of } from 'rxjs';
import {
  map,
  tap,
  filter,
  pluck,
  switchMap,
  takeWhile,
  finalize
} from 'rxjs/operators';
import { renderMinefield, renderScore, renderGameOver } from './html-renderer';
import { size, mine } from './constants';
import { addMines, addMarks } from './mines';

const mines$ = of(
  Array(size)
    .fill(0)
    .map(e => Array(size).fill(0))
).pipe(
  map(addMines),
  map(addMarks),
  tap(renderMinefield)
);

const click$ = mines =>
  fromEvent(document, 'click').pipe(
    map(({ clientX, clientY }: MouseEvent) =>
      document.elementFromPoint(clientX, clientY)
    ),
    filter(elem => elem.id !== ''),
    tap(elem =>
      (val => (
        renderScore(val === mine || elem.innerHTML !== '_' ? 0 : val),
        (elem.innerHTML = val)
      ))(mines[elem.id[0]][elem.id[1]])
    ),
    pluck('id'),
    takeWhile(([x, y]) => mines[x][y] !== mine),
    finalize(renderGameOver)
  );

mines$.pipe(switchMap(click$)).subscribe();

mines.ts

import { size, mine } from './constants';

const randomNumber = () => Math.floor(Math.random() * Math.floor(size));

export const addMines = arr => {
  for (let i = 0; i < size / 2; i++) {
    arr[randomNumber()][randomNumber()] = mine;
  }

  return arr;
};

const mark = (arr, x, y) =>
  arr[x] !== undefined && arr[x][y] !== undefined
    ? (arr[x][y] += arr[x][y] === mine ? 0 : 1)
    : () => {};

export const addMarks = arr => {
  for (let ri = 0; ri < size; ri++) {
    for (let ci = 0; ci < size; ci++) {
      if (arr[ri][ci] === mine) {
        mark(arr, ri - 1, ci + 1);
        mark(arr, ri - 1, ci);
        mark(arr, ri - 1, ci - 1);
        mark(arr, ri, ci + 1);
        mark(arr, ri, ci - 1);
        mark(arr, ri + 1, ci + 1);
        mark(arr, ri + 1, ci);
        mark(arr, ri + 1, ci - 1);
      }
    }
  }
  return arr;
};

constants.ts

export const mine = 9;
export const size = 10;

html-renderer.ts

export const renderMinefield = arr =>
  arr.forEach((r, ri) =>
    (elem =>
      r.forEach(
        (c, ci) =>
          (col => (
            (col.innerText = '_'),
            (col.id = `${ri}${ci}`),
            elem.appendChild(document.createTextNode('\u00A0\u00A0')),
            elem.appendChild(col)
          ))(document.createElement('span')),
        document.body.appendChild(elem)
      ))(document.createElement('div'))
  );

export const renderScore = val =>
  (scoreElem => (scoreElem.innerText = parseInt(scoreElem.innerText) + val))(
    document.getElementById('score')
  );

export const renderGameOver = () =>
  (document.body.innerHTML += '<br/>GAME OVER');

const addElem = decorator =>
  (elem => (decorator(elem), document.body.appendChild(elem)))(
    document.createElement('span')
  );

addElem(elem => (elem.innerText = 'Score: '));
addElem(elem => ((elem.id = 'score'), (elem.innerText = '0')));

Operators Used

filter
finalize
fromEvent
map
of
pluck
switchMap
takeWhile
tap
adamlubek
StackBlitz