Algorithm [2] - 보드 게임

Seungmin Shin·2021년 8월 17일
3

Algorithm

목록 보기
3/4

문제

N * N의 크기를 가진 체스판 위에서 게임을 하려고 합니다. 게임의 룰은 다음과 같습니다.

  1. 좌표 왼쪽 상단(0, 0)에 말을 놓는다.
  2. 말은 상, 하, 좌, 우로 이동할 수 있고, 플레이어가 조작할 수 있다.
  3. 조작의 기회는 딱 한 번 주어진다.
  4. 조작할 때 U, D, L, R은 각각 상, 하, 좌, 우를 의미하며 한 줄에 띄어쓰기 없이 써야 한다.
    ( 예시: UDDLLRRDRR, RRRRR )
  5. 한 번 움직일 때마다 한 칸씩 움직이게 되며, 그 칸 안에 적힌 숫자를 획득할 수 있다.
  6. 방문한 곳을 다시 방문해도 숫자를 획득할 수 있다.
  7. 보드 밖을 나간 말은 OUT 이다.
  8. 칸 안의 숫자는 0 또는 1이다.
    ( 단, 좌표 왼쪽 상단(0, 0)은 항상 0이다. )
  9. 획득한 숫자를 합산하여 숫자가 제일 큰 사람이 이기게 된다.

보드판이 담긴 board와 조작하려고 하는 문자열 operation이 주어질 때, 말이 해당 칸을 지나가면서
획득한 숫자의 합을 구하는 함수를 작성하세요.

입력

인자 1 : board

  • Number 타입의 2차원 배열
  • 2 <= board.length <= 100
  • 예: [ [0, 0, 1], [1, 0, 1], [1, 1, 1] ]

인자 2 : operation

  • string 타입의 대문자 영어가 쓰여진 문자열
  • 1 <= operation.length <= board.length * 2
  • U, L, D, R 이외의 문자열은 없습니다.

출력

  • Number 타입을 반환해야 합니다

주의사항

  • 만약, 말이 보드밖으로 나갔다면 즉시 OUT 을 반환합니다.

입출력예시

const board1 = [
  [0, 0, 0, 1],
  [1, 1, 1, 0],
  [1, 1, 0, 0],
  [0, 0, 0, 0]
]
const output1 = boardGame(board1, 'RRDLLD');
console.log(output1); // 4


const board2 = [
  [0, 0, 1],
  [1, 1, 1],
  [1, 0, 0]
]
const output2 = boardGame(board2, 'UUUDD');
console.log(output2); // 'OUT'

수도코드

1. 좌,우로 이동할 수 있는 좌표를 생성해준다.
2. 말판을 지날때마다 해당말판의 숫자 (0 또는 1) 을 탐색해주는 변수가 필요하고, 
   그 변수를 담을 변수도 필요하다.
3. 말이 이동할 수 있는 네가지 방향에 대한 조건식을 걸어준다, (ex. U일때 Y축으로 -1 이동)
4. Out에 대한 조건식도 만들어준다.
5. 이 조건식들은 opration 문자열의 순회가 끝날때까지 반복한다.
6. 그렇게 반복하면서 쌓인 숫자들을 전부 더한 값을 변수에 담아 출력해준다.

문제풀이

function boardGame(board, operation) {

  let Y = 0; 
  let X = 0;
  let result = 0;
  let current = board[0][0];

  for (let move of operation) {
    if (move === 'U') {Y += - 1; X += 0;}

    if (move === 'D') {Y += 1; X += 0;}

    if (move === 'L') {Y += 0; X += - 1;}

    if (move === 'R') {Y += 0; X += 1;}

    if (Y < 0 || Y > board.length || X < 0 || X > board.length) {
      return 'OUT'
    }
    current = board[Y][X];
    
    result = result + current;
  }

  return result;
};

코드해석

이 말판안에선 위, 아래, 좌, 우 로 이동할 수 있다. 한칸씩 말이다.
우리가 인지하는 상하좌우는 컴퓨터의 입장에서는 X좌표(가로) 와 Y좌표(세로) 로 인식한다.
그럼 우리가 이동하는만큼 X좌표를 몇 이동, Y좌표를 몇 이동 이런식으로 명령을 내려야 한다.
그렇기때문에 X 와 Y 라는 변수를 만들어 그 값은 초기값인 0으로 준다, (0,0) 에서 시작하기때문이다.

result 변수는 말이 모두 이동하면서 담아놓은 최종값을 출력해줄 변수다.

current 변수는 이동한 말이 위치한곳에 어떤 숫자가 있는지 판별해준다. 0인지 1인지. 

이렇게 기본세팅을 마치고 본격적으로 말을 이동시킬 코드를 작성하게 되는데,
우리는 주어진 operation 에 담긴 문자열의 길이만큼 이동을 해야한다. for of 반복문을 활용하면 된다.
문자열이란 개념 자체가 배열의 개념이기에 for of 반복문을 이용하면 한 글자씩 탐색할 수 있는것이다.

move 라는 임의의 엘리먼트가 한글자씩 반복을 하면서 

1. move 가 'U' 라면 Y축으로 -1만큼 이동한다.
2. move 가 'D' 라면 Y축으로 +1만큼 이동한다.
3. move 가 'L' 라면 X축으로 -1만큼 이동한다.
4. move 가 'R' 라면 X축으로 +1만큼 이동한다.

이런식으로 조건을 준다, 00만큼 이동한다는 뜻은 곧 위에 선언했던 변수에 -1, +1 만큼 변화를 주는것이다.

그렇게 해당 조건으로 말이 움직여 X 와 Y에 변동이 생긴다면, 이제 그 값을 current에 대입시킨다.
board[Y][X] 의 X, Y 에 변화된 값을 대입하고, 그 값으로 생긴 current를 result에 더한다.
이제 계속 반복을 하면서 나오는 current 값을 더할것이다, 그리고 X, Y 는 초기값에서 계속하여
더하거나 빼지는거기때문에 말이 이동하는동안 초기화되지 않고 계속해서 쌓여갈것이다.

Q. 왜 board[X][Y]가 아닌 board[Y][X]로 작성해야 하는지?
A. 우리가 무의식적으로 마치 약속한것처럼 X,Y를 사용하지만, 여기서 사용하는 X,Y는 그 의미가 조금
   다르다, Y는 2차원 배열의 세로, 즉 인덱스를 가리키고, X는 그 안의 1차원 배열의 인덱스를 의미한다.
   그렇기 때문에 배열의 차원 순서상 Y를 먼저 쓰는것이 방법적으로 옳다.
   
이렇게 모든 문자열을 순회하면서 말이 말판으로 나가지 않았다면 지금껏 더해왔던 current의 값을 가지고
있는 result 를 최종출력해주면 되고, 만약 이동하다가 말이 말판 밖으로 나가면 그 즉시 OUT 을 주면
되는데, 그 범위는 코드를 보면 쉽게 해석이 가능하다, X나 Y 둘중에 하나라도 0보다 작거나 보드의
길이보다 커지면 바로 OUT을 리턴하는 조건식을 더해주면 된다. 끝
profile
Frontend Developer

0개의 댓글