위 문제는 실행 대기 큐에 들어있는 프로세스 중 우선순위가 높은 순으로 처리한 다음 FIFO로 처리될 때 location으로 지정된
프로세스가 몇번째로 수행되는지를 알아내는 문제이다.
우선 대기 큐에 [ [우선순위,인덱스번호],[우선순위,인덱스번호], ... ] 이런식으로 변환하고 우선순위가 가장 높은지 비교 후 제일 높으면 바로 큐에서 빼고 처리 수를 기록하는 변수를 증가시킨다. 만약 여기서 처리된 프로세스가 location과 같으면 지금까지 얼마나 처리되었는지 반환한다.
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에 대하여 얕게나마 공부하면 과제에 도움이 될 것 같아 찾아보았다.
깊게 공부하기엔 너무 시간이 부족하고 스켈레톤이 이해갈 정도만...
환경 구축이라기보다는 그릴 준비라 하는게 맞겠다. 사전적 의미가 유화(油畵)를 그릴 때 쓰는 천이니까 html에는
이 캔버스를 어디에 놓을지 정하는게 되고, JS에는 캔버스의 사이즈와 무엇을 그릴지를 정하면 된다.
<!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>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth - 100;
canvas.height = window.innerHeight - 100;
위와 같은 코드만으로 빈 화면이지만 그릴 준비가 완료되었다.
canvas를 유동적으로 조절하려면 위와 같이 써도 되겠지만 게임의 형평성에 맞게 고정값으로 지정하는 것이 좋겠다.
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을 넘겨주기 때문에 그걸 이용하여 원하는 프레임의 시간으로 계산하여 누구든 같은 속도로 진행할 수 있게 할 수 있다.