- [자바스크립트] 캐릭터의 좌표 - 프로그래머스 120861 객체의 속성값 전달하여 변경하기2024년 06월 19일
- 주사위 clice
- 작성자
- 2024.06.19.:43
반응형문제 설명
https://school.programmers.co.kr/learn/courses/30/lessons/120861
머쓱이는 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만 주어집니다.
입출력 예
keyinput board result ["left", "right", "up", "right", "right"] [11, 11] [2, 1] ["down", "down", "down", "down", "down"] [7, 9] [0, -4] 입출력 예 설명
입출력 예 설명 #1
- [0, 0]에서 왼쪽으로 한 칸 오른쪽으로 한 칸 위로 한 칸 오른쪽으로 두 칸 이동한 좌표는 [2, 1]입니다.
입출력 예 설명 #2
- [0, 0]에서 아래로 다섯 칸 이동한 좌표는 [0, -5]이지만 맵의 세로 크기가 9이므로 아래로는 네 칸을 넘어서 이동할 수 없습니다. 따라서 [0, -4]를 return합니다.
첫 문제 풀이 알고리즘
1. 초기 위치를 [0, 0]으로 설정한다
let position={x:0, y:0};
2. 맵의 경계를 horizontalArm과 verticalArm으로 계산한다
let horizontalArm={minus:-(board[0]-1)/2,plus:(board[0]-1)/2}; //수평 팔의 길이 let verticalArm={minus:-(board[1]-1)/2,plus:(board[1]-1)/2}; //수직 팔의 길이
방향키 입력을 하나씩 처리하며, 경계를 넘지 않는 범위에서 좌표를 업데이트한다
각 방향키 입력에 대해 현재 위치와 방향을 확인하고, 경계 내에서 이동을 수행하는 checkAndMove 함수를 호출해준다
첫번째 코드
//처음에는 같은 방향만 모아서 한번에 더하려고 했지만, 그렇게 되면 맵을 벗어나는 방향키를 무시하지 못한다.그래서 하나 하나 다 생각해줘야 한다 const solution=(keyinput, board)=>{ let position={x:0, y:0}; let horizontalArm={minus:-(board[0]-1)/2,plus:(board[0]-1)/2}; //수평 팔의 길이 let verticalArm={minus:-(board[1]-1)/2,plus:(board[1]-1)/2}; //수직 팔의 길이 console.log("좌표평면: ",horizontalArm, verticalArm); for (let i of keyinput){ if (i=="left"||i=="right") checkAndMove(horizontalArm, position.x, i); //수평 팔의 길이 else checkAndMove(verticalArm , position.y, i); //수직 팔의 길이 console.log([position.x, position.y]); } return [position.x, position.y]; }; //좌표평면과 방향을 확인하고 이동해주는 함수 const checkAndMove=(arm, pos, direction)=>{ //좌표평면, 현재 위치, 이동 방향을 파라미터로 받음 console.log(arm, pos, direction); if(arm.minus< pos && pos<arm.plus){ //만약 현재 위치가 좌표평면의 -+ 안에 있다면 (direction==("left"||"down"))?pos--:pos++; //그리고 방향이 left또는 down이라면 좌표에 --를 하고 아니라면 ++를 함 console.log("pos: ", pos); } };
그런데 복사된 값이 전달되고 객체의 값은 바뀌지 않는 문제가 발생하였다
두번째 수정한 코드
//처음에는 같은 방향만 모아서 한번에 더하려고 했지만, 그렇게 되면 맵을 벗어나는 방향키를 무시하지 못한다.그래서 하나 하나 다 생각해줘야 한다 let horizontalArm; let verticalArm; let position={x:0, y:0}; const solution=(keyinput, board)=>{ horizontalArm={minus:-(board[0]-1)/2,plus:(board[0]-1)/2}; //수평 팔의 길이 verticalArm={minus:-(board[1]-1)/2,plus:(board[1]-1)/2}; //수직 팔의 길이 console.log("좌표평면: ",horizontalArm, verticalArm); for (let i of keyinput){ checkAndMove(position, i); //수평 팔의 길이 console.log(position); } return [position.x, position.y]; }; //좌표평면과 방향을 확인하고 이동해주는 함수 const checkAndMove=(pos, direction)=>{ //현재 위치, 이동 방향을 파라미터로 받음 if (direction == "left" || direction == "right") { if (horizontalArm.minus < pos.x && pos.x < horizontalArm.plus) { // 현재 위치가 좌표평면의 -+ 안에 있다면 (direction == "left") ? pos.x-- : pos.x++; // 방향이 left라면 좌표를 감소시키고, 아니라면 증가시킴 } } else { if (verticalArm.minus < pos.y && pos.y < verticalArm.plus) { // 현재 위치가 좌표평면의 -+ 안에 있다면 (direction == "down") ? pos.y-- : pos.y++; // 방향이 down이라면 좌표를 감소시키고, 아니라면 증가시킴 } } };
그래서 이렇게 수정하였다
다 괜찮았는데 딱 한개의 테스트케이스에서 문제가 발생했다
무슨 이유인가 봤더니 아래 코드 부분에서 좌표평면 끝까지 가서 문제가 발생한것이었다
if (horizontalArm.minus < pos.x && pos.x < horizontalArm.plus) { // 현재 위치가 좌표평면의 -+ 안에 있다면 (direction == "left") ? pos.x-- : pos.x++; // 방향이 left라면 좌표를 감소시키고, 아니라면 증가시킴 }
그럼 '이동할 예정인 위치'가 좌표평면을 벗어나는지 검증하는 방법으로 바꾸어야 한다
수정된 최종 코드
let horizontalArm; let verticalArm; const solution=(keyinput, board)=>{ let position={x:0, y:0}; horizontalArm={minus:-(board[0]-1)/2,plus:(board[0]-1)/2}; //수평 팔의 길이 verticalArm={minus:-(board[1]-1)/2,plus:(board[1]-1)/2}; //수직 팔의 길이 for (let i of keyinput) checkAndMove(position, i); //수평 팔의 길이 return [position.x, position.y]; }; //좌표평면과 방향을 확인하고 이동해주는 함수 const checkAndMove=(pos, direction)=>{ //현재 위치, 이동 방향을 파라미터로 받음 if((direction=="left"&&horizontalArm.minus==pos.x)|| (direction=="right"&&horizontalArm.plus==pos.x)|| (direction=="down"&&verticalArm.minus==pos.y)|| (direction=="up"&&verticalArm.plus==pos.y)) console.log("Cannot Move"); else if(direction=="left"||direction=="right") direction == "left"? pos.x-- : pos.x++; else direction == "down"? pos.y-- : pos.y++; };
다른 사람 풀이(최다 유저 풀이)
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; }
생각해보면 너무 코드를 줄이는데 집착하여 빙빙 돌다가 결국 시간도 오래 걸리고 코드도 길어진것 같다
어떻게 짜도 무조건 갈림길이 4개가 나오는데, 삼항연산자를 이용해서 어떻게든 2줄로 줄이려고 했던게 가장 큰 실수같다
입력값에 따라서 다른 동작을 실행하고 싶다면 switch를 잊지 말자
ⓒ clice lee clicelee
클라이스의 개발일지주사위의 개발일지
반응형'프론트 > Javascript Typescript' 카테고리의 다른 글
[JS] 로그인 성공? - 프로그래머스 120883 Map의 has get 메서드, some, 구조분해할당 (0) 2024.07.12 [JS] 절대 사용하면 안되는 eval 함수에 대해 (프로그래머스 120902 문자열 계산하기) (2) 2024.07.08 [JS] 영어가 싫어요-프로그래머스 120894 (1) 2024.06.15 [JS] 7의 개수-프로그래머스 120912 join(' ') split(' ') filter() 함수 (0) 2024.06.06 [JS로 코테 정복하기] 자주 나오는 함수 정리 + 관련 프로그래머스 문제들 (0) 2024.06.06 다음글이전글이전 글이 없습니다.댓글