[js] 캐릭터의 좌표 (lv.0)

sookyoung.k·2024년 5월 28일
post-thumbnail

머쓱이는 RPG게임을 하고 있습니다. 게임에는 up, down, left, right 방향키가 있으며 각 키를 누르면 위, 아래, 왼쪽, 오른쪽으로 한 칸씩 이동합니다. 예를 들어 [0,0]에서 up을 누른다면 캐릭터의 좌표는 [0, 1], down을 누른다면 [0, -1], left를 누른다면 [-1, 0], right를 누른다면 [1, 0]입니다. 머쓱이가 입력한 방향키의 배열 keyinput와 맵의 크기 board이 매개변수로 주어집니다. 캐릭터는 항상 [0,0]에서 시작할 때 키 입력이 모두 끝난 뒤에 캐릭터의 좌표 [x, y]를 return하도록 solution 함수를 완성해주세요.

  • [0, 0]은 board의 정 중앙에 위치합니다. 예를 들어 board의 가로 크기가 9라면 캐릭터는 왼쪽으로 최대 [-4, 0]까지 오른쪽으로 최대 [4, 0]까지 이동할 수 있습니다.

제한사항

  • board은 [가로 크기, 세로 크기] 형태로 주어집니다.
  • board의 가로 크기와 세로 크기는 홀수입니다.
  • board의 크기를 벗어난 방향키 입력은 무시합니다.
  • 0 ≤ keyinput의 길이 ≤ 50
  • 1 ≤ board[0] ≤ 99
  • 1 ≤ board[1] ≤ 99
  • keyinput은 항상 up, down, left, right만 주어집니다.

나의 풀이

function solution(keyinput, board) {
    // 최대 좌표 절댓값 구하기
    let maxX = Math.floor(board[0]/2);
    let maxY = Math.floor(board[1]/2);
    
    // x, y 좌표 값 초기화
    let x = 0;
    let y = 0;
    
    for (i of keyinput) {
        switch(i) {
            case 'left':
                x--;
                x = x < -maxX ? -maxX : x;
                break;
            case 'right': 
                x++;
                x = x > maxX ? maxX : x;
                break
            case 'up':
                y++;
                y = y > maxY ? maxY : y;
                break;
            case 'down':
                y--;
                y = y < -maxY ? -maxY : y;
                break
        }
    }
    
    return [x, y]
}
  • board를 벗어나선 안되기 때문에 먼저 x축, y축으로 갈 수 있는 최대 좌표를 구한다.
  • x축, y축의 좌표를 각각 0으로 초기화한다.
  • keyinput 배열을 for...of 반복문과 switch 문을 돌며 각각 입력에 따라 다른 조건을 실행한다.
    - 'left' 입력일 경우 x를 감소시키는데, x가 -maxX보다 작아지지 않도록 한다.
    • 'right' 입력의 경우 x를 증가시키는데, x가 maxX보다 커지지 않도록 한다.
    • 'up' 입력은 y를 증가시키는데, y가 maxY보다 커지지 않도록 한다.
    • 'down' 입력은 y를 감소시키는데, y가 -maxY보다 작아지지 않도록 한다.
  • 최종적으로 업데이트 된 x, y를 배열의 형태로 반환한다.

다른 풀이 1

function solution(keyinput, board) {
    let res = [0,0];
    for (let p of keyinput) {
        switch(p){
            case 'left': if (-res[0] < board[0]/2-1) res[0]--; break;
            case 'right': if (res[0] < board[0]/2-1) res[0]++; break;
            case 'up': if (res[1] < board[1]/2-1) res[1]++; break;
            case 'down': if (-res[1] < board[1]/2-1) res[1]--; break;
        }
    }
    return res;
}

나와 비슷한 풀이이지만, 조건부 이동을 통해 사용자의 위치가 보드를 넘지 않을 때에만 위치를 업데이트 하도록 했다.

  • 현재 위치를 res라는 변수에 [0, 0]으로 초기화한다.
  • for...of와 switch를 사용하는 것은 동일
    - 각각의 경우에 대해서 현재 위치(res[0] 또는 res[1])이 보드 경계 내에 있는지 확인한다.
    • 조건을 만족할 때만 증감을 시킨다.
  • 최종 결과 반환

다른 풀이 2

function solution(keyinput, board) {
    let key = {"right" : [1,0], "up" : [0,1], "down" : [0,-1], "left" : [-1,0]};


    let rslt = keyinput.map(v => key[v]).reduce((a,b) => { 
        if (Math.abs(a[0] + b[0]) > board[0]/2 || Math.abs(a[1] + b[1]) > board[1]/2) 
            return [a[0],a[1]] ; 

        return [a[0] + b[0], a[1] + b[1]];}
    , [0,0])


    return rslt;
}

객체를 이용한 풀이!!

  • 객체 매핑을 통해 key 객체는 각 방향으로의 키 입력에 대한 위치 변화를 배열로 저장한다.
  • map()함수를 통해서 사용자의 키 입력을 좌표 변화로 변환한다. (map(v => key[v])) => 좌표 변화의 배열이 된다.
  • reduce() 함수를 통해 모든 키 입력에 대한 좌표 변화를 적용하여 최종 위치를 계산한다.
    - reduce() 함수는 누적된 결과(a)와 현재 처리 요소(b)를 인자로 받는다.
    - if 조건문을 통해 새로운 좌표가 보드의 범위를벗어나는지 확인한다.
    • 벗어날 경우 현재 위치([a[0], b[1])를 그대로 반환하여 이동하지 않는다.
    • 벗어나지 않는 경우에 좌표 변화를 적용한다. (a[0] + b[0], a[1] + b[1]을 계산하여 새로운 위치로 업데이트)
  • 최종적으로 계산된 위치를 반환한다.
profile
영차영차 😎

0개의 댓글