TIL

TIL 8/21 - 데일리 루틴 40번, 개인과제

nbcssw 2024. 8. 21. 21:06

40번 - 3진법 뒤집기

https://school.programmers.co.kr/learn/courses/30/lessons/68935

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

function solution(n) {
    var answer = 0;
    var samjin = [];

    while (n >= 3) {
        samjin.unshift(n % 3);
        n = parseInt(n / 3);
    }
    samjin.unshift(n);
    n = Math.floor(n / 3);
    samjin.reverse();
    
    for (let i = samjin.length-1; i >= 0; i--)
        answer += Math.pow(3, i) * samjin[samjin.length-i-1];
    
    return answer;
}

 

 

개인과제

텍스트 기반 로그라이크 RPG

game.js

import chalk from 'chalk';
import figlet from 'figlet';
import readlineSync from 'readline-sync';

function getRandomInt(min, max) { // 두 정수를 입력받아 그 사이의 랜덤 정수를 출력하는 함수
  return Math.floor(Math.random() * (max - min + 1) + min);
}

function success(percent) { // 확률을 입력받아서 성공 실패 결정하는 함수
  let arr = [percent, 100 - percent];
  if (getRandomInt(0, 100) <= percent)
    return true;
  else
    return false;
};

class Player {
  constructor() {
    this.hp = 100;
    this.atk = 10;
    this.crit = 20;
    this.critdmg = 1.5;
    this.canRun = 25;
  }

  attack(target) {
    // 플레이어의 공격
    target.hp -= this.atk;
  }

  critatk(target) {
    const lastdmg = Math.floor(this.atk * this.critdmg);
    target.hp -= lastdmg;
  }
}

class Monster {
  constructor(name) {
    this.name = name;
    this.hp = 25;
    this.atk = 7;
  }

  attack(target) {
    // 몬스터의 공격
    target.hp -= this.atk;
  }
}

function displayStatus(floor, player, monster) {
  console.log(chalk.magentaBright(`\n=== Current Status ===`));
  console.log(
    chalk.cyanBright(`| Floor: ${floor}|`) +
    chalk.blueBright(
      `\n| 플레이어 정보 | `,
      `Hp: ${player.hp} | `,
      `Atk: ${player.atk} | `,
      `Crit: ${player.crit}% | `,
      `CritDmg: x${player.critdmg} | `
    ) +
    chalk.redBright(
      `\n| 몬스터 정보 |`,
      `Name: ${monster.name} | `,
      `HP: ${monster.hp} | `,
      `Atk: ${monster.atk} | `
    ),
  );
  console.log(chalk.magentaBright(`=====================\n`));
}

const battle = async (stage, player, monster) => {
  let logs = [];
  let run;

  while (player.hp > 0 && monster.hp > 0) {
    console.clear();
    displayStatus(stage, player, monster);

    logs.forEach((log) => process.stdout.write(log));

    console.log(
      chalk.green(
        `\n1. 공격한다 2. 치명타를 노린다 3. 도망친다(${player.canRun}%) 0. 항복한다 `,
      ),
    );
    const choice = readlineSync.question('선택: ');
    // 플레이어의 선택에 따라 다음 행동 처리
    // logs.push(chalk.green(`${choice}를 선택하셨습니다.`));
    switch (choice) {
      case '1':
        logs.push(chalk.green(`몬스터를 공격! `));
        if (success(player.crit)) { // 치명타 발생
          logs.push(chalk.redBright(`치명타!! ${Math.floor(player.atk * player.critdmg)}의 데미지!!!\n`));
          player.critatk(monster);
        } else {
          logs.push(chalk.yellow(`${player.atk}의 데미지!\n`));
          player.attack(monster);
        }
        break;
      case '2':
        logs.push(chalk.green(`치명타를 노린 공격! `));
        if (success(player.crit * 2)) { // 치명타 발생
          logs.push(chalk.redBright(`치명타!! ${Math.floor(player.atk * player.critdmg)}의 데미지!!!\n`));
          player.critatk(monster);
        } else {
          logs.push(chalk.gray(`무리하게 공격하는 바람에 공격이 빗나가 버렸다..\n`));
        }
        break;
      case '3':
        if (success(player.canRun)){
          console.log(chalk.blueBright(`성공적으로 도망쳤습니다.\n`));
          run = true;
        }
        else
          logs.push(chalk.cyan(`도망에 실패했습니다..\n`));
        break;
      case '0':
        console.log(chalk.red(`몬스터에게 항복했습니다...`));
        player.hp = 0;
        break;
      default:
        await battle(stage, player, monster);
        break;
    }

    if(player.hp <= 0 || monster.hp <= 0 || run)
      break;

    // 몬스터의 행동
    monster.attack(player);
    logs.push(chalk.green(`몬스터가 공격해왔다! `), chalk.red(`${monster.atk}만큼의 데미지를 입었다..\n`));
  }

  if (player.hp <= 0) {
    console.clear();
    displayStatus(stage, player, monster);
    logs.forEach((log) => process.stdout.write(log));
    console.log(chalk.red('플레이어 사망'));
    process.exit(0);
  } else if (monster.hp <= 0) {
    console.clear();
    displayStatus(stage, player, monster);
    logs.forEach((log) => process.stdout.write(log));
    console.log(chalk.green(`${monster.name}을 해치웠다!`));
    console.log(chalk.magenta('체력이 50 회복되었다.'));
    player.hp += 50;
    const reward = getRandomInt(0,2);
    let amount;
    if(reward === 0){
      amount = getRandomInt(1,3);
      player.atk += amount;
      console.log(chalk.magenta(`보상: 공격력 ${amount} 증가 => Atk: ${player.atk}(+${amount})`));
    } else if (reward === 1){
      amount = getRandomInt(5, 10);
      player.crit += amount;
      console.log(chalk.magenta(`보상: 치명타 확률 ${amount} 증가 => Crit: ${player.crit}%(+${amount})`));
    } else if (reward === 2){
      amount = getRandomInt(2,5);
      player.critdmg += (amount/10);
      console.log(chalk.magenta(`보상: 치명타 데미지 ${amount/10} 증가 => CritDmg: x${player.critdmg}(+${amount/10})`));
    }
  }

  readlineSync.question(chalk.gray('아무 키나 입력해서 다음 전투로 넘어가세요\n'));
};

export async function startGame() {
  console.clear();
  const player = new Player();
  player.hp = 100;
  let stage = 1;

  while (stage <= 10) {
    let mult = 1 + ((stage - 1) * 0.2);
    const monster = new Monster('Monster');
    monster.hp = Math.floor(monster.hp*mult);
    monster.atk = Math.floor(monster.atk*mult);
    await battle(stage, player, monster);

    if (player.hp <= 0) {
      console.log('플레이어 사망');
      process.exit(0);
    }
    // 스테이지 클리어 및 게임 종료 조건

    stage++;
  }
  console.clear()
  console.log(
    chalk.yellow(
        figlet.textSync('GAEM CLEAR', {
            font: 'Standard',
            horizontalLayout: 'default',
            verticalLayout: 'default'
        })
    )
);
}

 

Math.random을 통한 랜덤 정수를 return하는 함수, 확률을 입력받아서 성공 여부를 return하는 함수 등을 추가했고,

player의 스탯에 치명타 확률, 치명타 데미지를 추가해서 치명타를 가할 수 있게 만들었다. 이외에도 치명타를 터트릴 확률을 높이는 대신 빗맞출 수 있는 '2.치명타를 노린다'라는 행동이나 게임을 포기하는 '0.항복한다'라는 행동도 추가했다.

 

아직 동기/비동기나 클래스에 대한 이해가 부족해서 원했던 모든 기능을 추가하진 못해서, 다음 주 제출 기간까지 더 공부해서 추가해볼 생각이다.

'TIL' 카테고리의 다른 글

8/23 TIL  (0) 2024.08.23
8/22 TIL  (0) 2024.08.22
TIL 8/20 - 데일리 루틴 28번 ~ 39번  (0) 2024.08.20
TIL 8/20 (1) - 알고리즘 문제풀이 2  (0) 2024.08.20
TIL 8/19 - 알고리즘 문제풀이  (0) 2024.08.19