본문 바로가기

HackerRank

[해커랭크] Day 8: Buttons Container (javascript)

3X3의 숫자판에서 가운데 버튼 클릭 시 시계방향으로 숫자판 회전시키기
- html, css, script 작성하기

조건

  • 초기  레이아웃

  • 버튼 5를 한번 클릭했을 경우

  • 버튼 5를 한번 더 클릭했을 경우

제한사항

  • 지정된 ID, css 부여할 것
  • 클릭 때 마다 시계방향으로 돌 것.

나의 풀이

  •  더 쉽게 처리하는 방법이 있을 것 같은데, 일단 직역적으로 처리
  • 그림 4. 처럼 3x3의 행렬(2중배열)을 단일 배열로 치환하여 계산
    • 이중배열을 단일배열로 처리 후 계산하는 방법
col = index%len
row = Math.abs( Math.floor((index-1)/len))
index = col + row*(col_len);

그림 4. 행렬 데이터를 단일배열 데이터로 변환할 때 구조

  • 3x3 그리드에서 가운데 좌표 (1,1)을 중심으로 시계방향으로 돌릴 경우, 각각의 위치가 이동되는 지점을 그려서 확인 

그림 5. 각 행렬에서 중심좌표를 기준으로 시계방향으로 돌 경우의 위치 변화

  • 관련 코드 (주석으로 설명)
  const onClick = (e) => {
    // 이벤트 버블링 막기
    e.stopPropagation();
    /*
     * 타겟 ID
     */
    const id = e.target.id;
    
    // 가운데 버튼이 아닌 경우 리턴
    // 해당 버튼에만 클릭이벤트를 부여하는 것이 좋음
    // 동적으로 버튼을 생성하면서 전체버튼에 클릭 이벤트를 부여하게 되어 부득이하게 제어함
    if (id !== 'btn5') {
       return ;
    }
    
    /*
     * 버튼 노드 리스트 
     */
    const buttons = document.querySelectorAll('#btns button');
    
    /*
     * 현재 버튼순서별로 표출하는 숫자배열 추출
     */
    const values = [...buttons].map(ele => ele.innerHTML);
    
    /*
     * 그리드 열 길이
     */ 
    const len = 3;
    
    /*
     * 시계방향으로 회전한 배열 처리
     */
    const rotate_values = values.map((v, i, arr) => {
    	/*
         * 배열에서의 해당 데이터의 행
         */
        const row = Math.abs(Math.floor((i-1)/len));
        /*
         * 배열에서의 해당 데이터의 열
         */
        const col = i%len;

		
        if (col === 0) {  // 열이 0번째 인 경우
          if (row === 2) {  // 행이 2번째(마지막) 인 경우 +1열의 값
          
            return arr[(col+1)+row*len];
          } else {  // 아닌 경우 아래 행의 값
          
            return arr[col+(row+1)*len];
          }
        } else if (col === 2) {  // 열이 2번째 인 경우
          if (row === 0) {  // 행이 0번째(첫) 인 경우 -1열의 값
          
            return arr[(col-1)+row*len];
          } else {  // 아닌 경우 위 행의 값
          
            return arr[col+(row-1)*len];
          }
        } else {  // 열이 1번째 인 경우
          if (row === 0) {  // 행이 0번째(첫) 인 경우 -1열의 값
          
            return arr[(col-1)+row*len];
          } else if (row === 2) {  // 행이 2번째(마지막) 인 경우 +1열의 값
          
            return arr[(col+1)+row*len];
          } else {  // 행이 1번째(가운데) 인 경우 해당 값
          
            return v;
          }
        }     
      });
      
      // 시계방향으로 회전한 배열데이터를 순서대로 배치하기
      rotate_values.forEach((v, i) => buttons[i].innerHTML = v);
  };
  • 전체 소스는 아래와 같음 (codepen)

 

결과