[TIL] 24.10.01 TUE

GDORI·2024년 10월 1일
0

TIL

목록 보기
58/79
post-thumbnail

오늘 푼 알고리즘 코드카타

42587. 프로세스

풀이

위 문제는 실행 대기 큐에 들어있는 프로세스 중 우선순위가 높은 순으로 처리한 다음 FIFO로 처리될 때 location으로 지정된
프로세스가 몇번째로 수행되는지를 알아내는 문제이다.
우선 대기 큐에 [ [우선순위,인덱스번호],[우선순위,인덱스번호], ... ] 이런식으로 변환하고 우선순위가 가장 높은지 비교 후 제일 높으면 바로 큐에서 빼고 처리 수를 기록하는 변수를 증가시킨다. 만약 여기서 처리된 프로세스가 location과 같으면 지금까지 얼마나 처리되었는지 반환한다.

JS 코드

function solution(priorities, location) {
  // 실행대기 큐를 [우선순위, 인덱스번호] 요소를 가진 2차원 배열로 변환
    const processArr = priorities.reduce((acc,priority,idx) => {
        acc.push([priority,idx]);
        return acc;
    },[]);
  // 처리된 수를 저장할 변수
    let number = 0;
  // 대기 큐가 모두 처리되기 전까지 루프
    while(processArr.length>0){
        // 가장 큰 우선순위를 인자로 받은 priorities에서 계산함
        const maxPriority = Math.max(...processArr.map(item => item[0]));
        // 큐는 FIFO 방식이기 때문에 0번째 인자를 빼기 위하여 shift 사용
        const temp = processArr.shift();
        // 우선순위가 가장 높고 몇번째로 처리되었는지 알고자 했던 프로세스면 실행
        if(temp[0] === maxPriority && temp[1] === location){
            number ++;
            return number;
        // 그 외 우선순위가 높은 프로세스 처리
        }else if(temp[0] === maxPriority){
            number ++;
        // 우선순위가 낮은게 나왔다면 대기 큐로 다시 푸쉬    
        }else{
            processArr.push(temp)
        }
    }
}

갑자기 CANVAS ?

서버 쪽만 공부하다보니 크롬 디노 개인과제가 발제되고 스켈레톤 코드로 받은 클라이언트 쪽 코드가 이해가 잘 가지 않아서
CANVAS에 대하여 얕게나마 공부하면 과제에 도움이 될 것 같아 찾아보았다.
깊게 공부하기엔 너무 시간이 부족하고 스켈레톤이 이해갈 정도만...

CANVAS 환경 구축(?)

환경 구축이라기보다는 그릴 준비라 하는게 맞겠다. 사전적 의미가 유화(油畵)를 그릴 때 쓰는 천이니까 html에는
이 캔버스를 어디에 놓을지 정하는게 되고, JS에는 캔버스의 사이즈와 무엇을 그릴지를 정하면 된다.

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Canvas Tutorial</title>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script src="main.js"></script>
  </body>
</html>

JS

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

canvas.width = window.innerWidth - 100;
canvas.height = window.innerHeight - 100;

위와 같은 코드만으로 빈 화면이지만 그릴 준비가 완료되었다.
canvas를 유동적으로 조절하려면 위와 같이 써도 되겠지만 게임의 형평성에 맞게 고정값으로 지정하는 것이 좋겠다.

네모 그리기

JS

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

canvas.width = window.innerWidth - 100;
canvas.height = window.innerHeight - 100;

const x = 10;
const y = 200;
const width = 50;
const height = 50;

ctx.fillStyle = "green";
ctx.fillRect(x, y, width, height);

ctx.fillStyle 을 통하여 채울 색상을 결정할 수 있고, ctx.fillRect(x, y, width, height) 로 (x,y)좌료에 너비 width, 높이 height 인 귀여운 사각형을 그릴 수 있다.

클래스로 인스턴스 생성

class gameObject {
  constructor(x, y, width, height, color) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
  }
  draw() {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
  }
}

var dino = new gameObject(10, 200, 50, 50, "green");
dino.draw();
var cactus = new gameObject(500, 200, 50, 50, "red");
cactus.draw();

gameObject라는 x,y,width,height,color를 다르게 만들 수 있는 클래스를 생성하여 dino와 cactus 라는 인스턴스를
생성하여 그려주었다.
지금 단계에서는 상속받아 만들 필요성이 없어보여서 하나로 주인공과 장애물을 만들었다..

장애물 복제 및 좌측으로 이동

변경 전 코드

var cactuses = [];
let timer = 0;
function a() {
  requestAnimationFrame(a);
  timer++;
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  if (timer % 144 === 0) {
    var cactus = new gameObject(500, 200, 50, 50, "red");
    cactuses.push(cactus);
  }

  cactuses.forEach((cactus) => {
    cactus.x--;
    cactus.draw();
  });

  dino.draw();
}

requestAnimationFrame 의 주요 역할은 브라우저가 최적의 시점에 애니메이션을 실행할 수 있도록 콜백 함수를 호출하는 것으로 모니터 호환 프레임마다 다르게 호출한다.
144HZ를 지원하는 모니터와 60HZ를 지원하는 모니터는 1초에 실행되는 수가 다르기 때문에 조금 변경해주어야 한다.

변경 후 코드

var cactuses = [];

let previousTime = 0;
let timer = 0;
const fps = 144; // 목표 프레임 속도 
const interval = 1000 / fps; // 각 프레임의 시간 

function a(currentTime) {
  if (!previousTime) {
    previousTime = currentTime;
  }
  // 경과 시간을 계산
  const deltaTime = currentTime - previousTime;
  // 경과 시간이 목표 프레임 시간 이상일 때만 실행
  if (deltaTime > interval) {
    // 타이머 증가
    timer++;
    // 캔버스 지우기
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 144프레임마다 선인장 생성
    if (timer % fps === 0) {
      const cactus = new gameObject(500, 200, 50, 50, "red");
      cactuses.push(cactus);
    }
    // 선인장 업데이트 및 그리기
    cactuses.forEach((cactus, idx, arr) => {
      if (cactus.x < 0 - cactus.width) {
        arr.splice(idx, 1);
      }
      cactus.x--;
      cactus.draw();
    });
    // 공룡 그리기
    dino.draw();
    // 이전 시간 업데이트
    previousTime = currentTime;
  }
  // 다음 프레임 요청
  requestAnimationFrame(a);
}
a();

requestAnimationFrame 은 콜백인자로 currentTime을 넘겨주기 때문에 그걸 이용하여 원하는 프레임의 시간으로 계산하여 누구든 같은 속도로 진행할 수 있게 할 수 있다.

profile
하루 최소 1시간이라도 공부하자..

0개의 댓글