개발 일지

24일 일지

rabbit97 2024. 8. 25. 05:44

사실 지금은 25일 새벽 5시이다 하지만 25일에도 기록을 할게 생길 수도 있으니 혹시나 24일부터 25일 새벽까지의 기록을 남긴다

 

과제를 주말까지 만들고 월요일 부터는 노드 강의를 들을 예정이였는데 코드의 구조적으로 문제가 생겨 이 기록하는 과정에서 혹시나 나중에 득을 볼 일이 있을까봐 기록 해본다.

 

일단 현재 진행 상황

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

class Skill {
constructor(name, probability, effect) {
this.name = name;
this.probability = probability;
this.effect = effect;
}
}

const combo = new Skill('연속 공격', 0.3, (player, monster, logs) => {
for (let i = 0; i < 3; i++) {
player.attack(monster, logs);
}
logs.push(chalk.green(`연속 공격을 성공!`));
});

class Player {
constructor(player) {
this.name = '';
this.hp = 100;
this.attacks = 10;
this.defense = 5;
this.speed = 12;
this.inventory = [];
}

equip(item) {
console.log('아이템 선택 후 엔터 두번');
console.log('현재 장비 목록 :');
if (this.equippedItem) {
console.log(`[장착] ${this.equippedItem.name}`);
}
this.inventory.forEach((item, index) => {
console.log(
`${index + 1}. ${item.name} (공격력 +${item.attackBonus}, 방어력 +${item.defenseBonus})`,
);
});
console.log('0. 장착 취소');

const equipChoice = readlineSync.question('장비를 선택하세요 : ');
let selectedItem;

if (equipChoice === '0') {
if (this.equippedItem) {
this.unequip();
console.log('장착 해제!');
} else {
console.log('장착된 장비가 없습니다.');
}
} else if (equipChoice > 0 && equipChoice <= this.inventory.length) {
const selectedItem = this.inventory[equipChoice - 1];
this.equip(selectedItem);
console.log(`${selectedItem.name} 장착!`);
} else {
console.log('잘못된 입력입니다.');
}

if (equipChoice > 0 && equipChoice <= this.inventory.length) {
const selectedItem = this.inventory[equipChoice - 1];
if (selectedItem instanceof Equipment) {
this.equippedItem = selectedItem;
this.attacks += selectedItem.attackBonus || 0;
this.defense += selectedItem.defenseBonus || 0;
console.log(`${selectedItem.name} 장착!`);
console.log(`현재 공격력: ${this.attacks}, 방어력: ${this.defense}`);
} else {
console.log('장착 실패: 장착할 수 없는 아이템입니다.');
}
} else {
console.log('잘못된 입력입니다.');
}
}

unequip() {
if (this.equippedItem) {
this.attacks -= this.equippedItem.attackBonus;
this.defense -= this.equippedItem.defenseBonus;
this.equippedItem = null;
console.log('장착 해제!');
} else {
console.log('장착된 장비가 없습니다.');
}
}

attack(monster, logs) {
const critical = 0.1;
const Cri = Math.random() < critical;
const inidamage = this.attacks - monster.defense;
const random = Math.random() * 20 - 1;
const damage = Math.max(1, Math.round(inidamage + random));
const finalDamage = Cri ? damage * 2 : damage;
monster.hp -= finalDamage > 0 ? finalDamage : 1;

logs.push(chalk.green(`${this.name}${finalDamage}${Cri ? ' (크리티컬!)' : ''} 공격!`));

if (Math.random() < combo.probability) {
combo.effect(this, monster, logs);
return;
}
}
}

function increaseStats(player) {
const increase = 30;
player.attacks += Math.floor(Math.random() * increase) + 10;
player.defense += Math.floor(Math.random() * increase);

console.log(
chalk.green(`공격력: ${player.attacks}, 방어력: ${player.defense}, 스피드: ${player.speed}`),
);
}

class Equipment {
constructor(name, attackBonus, defenseBonus) {
this.name = name;
this.attackBonus = attackBonus;
this.defenseBonus = defenseBonus;
}
}

class Monster {
constructor(stage) {
this.hp = stage * 100;
this.attacks = stage * 20;
this.defense = stage * 6;
this.speed = stage * 1;
this.name = `몬스터${stage}`;
}

attack(player) {
const inidamage = this.attacks - player.defense;
const random = Math.random() * 20 - 10;
const damage = Math.max(1, Math.round(inidamage + random));
player.hp -= damage;
console.log(`${this.name}${damage} 공격!`);
return damage;
}
}

function displayStatus(stage, player, monster) {
console.log(chalk.magentaBright(`\n=== Current Status ===\n`));
console.log(
chalk.cyanBright(`\n | Stage: ${stage} \n`) +
chalk.blueBright(
`\n | 플레이어 정보 | 체력 ${player.hp} | 공격력 ${player.attacks} | 방어력 ${player.defense} | 스피드 ${player.speed} | \n | 장착 장비: ${player.equippedItem ? player.equippedItem.name : '없음'} |\n`,
) +
chalk.redBright(
`\n | 몬스터 정보 | 체력 ${monster.hp} | 공격력 ${monster.attacks} | 방어력 ${monster.defense} | 스피드 ${monster.speed} | \n`,
),
);
console.log(chalk.magentaBright(`\n=====================\n`));
}

function Turn(player, monster) {
const speedy = player.speed - monster.speed;
if (speedy < 0) {
speedy = 0;
}
const probability = 0.5 + speedy * 0.01;
return Math.random() < probability ? 'player' : 'monster';
}

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

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

logs.forEach((log) => console.log(log));

turns = Turn(player, monster);

if (turns === 'player') {
console.log(chalk.green(`\n플레이어의 턴입니다.`));
console.log(chalk.green(`\n1. 공격한다 2. 장비 장착 - 몬스터가 때림.`));
const choice = readlineSync.question(chalk.bgGray('선택 > '));

logs.push(chalk.green(`**** ${choice}를 선택 ****`));

switch (choice) {
case '1':
player.attack(monster, logs);
if (monster.hp <= 0) {
console.log(`${monster.name} 처치!! 다음 스테이지!`);
player.hp += 50;
console.log(` 체력이 50 증가 !! 현재 체력 : ${player.hp} `);
logs.push(chalk.green(`${player.name}${player.attacks} 공격!`));
increaseStats(player, stage);
const dropRate = 1;
if (Math.random() < dropRate) {
const newEquipment = new Equipment('검', 10, 5);
player.inventory.push(newEquipment);
logs.push(chalk.green('검을 주웠다!'));
}
}
break;
case '2':
player.equip();
break;
default: {
console.log('잘못된 선택');
break;
}
}
} else {
const damage = monster.attack(player);
logs.push(chalk.red(`${monster.name} ${damage} 공격!`));
}

if (monster.hp > 0) {
logs.push(chalk.red(` 몬스터 공격 후 플레이어 체력 : ${player.hp}`));
} else {
console.log('몬스터의 체력이 0 이하입니다.');
}
if (player.hp <= 0) {
console.log(`으악`);
break;
}
}
};

export async function startGame() {
const player = new Player();
let stage = 1;

while (stage <= 10) {
const monster = new Monster(stage);
await battle(stage, player, monster);

stage++;
}
}

 

이 중에서 가장 문제인 곳이 이곳

 

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

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

logs.forEach((log) => console.log(log));

turns = Turn(player, monster);

if (turns === 'player') {
console.log(chalk.green(`\n플레이어의 턴입니다.`));
console.log(chalk.green(`\n1. 공격한다 2. 장비 장착 - 몬스터가 때림.`));
const choice = readlineSync.question(chalk.bgGray('선택 > '));

logs.push(chalk.green(`**** ${choice}를 선택 ****`));

switch (choice) {
case '1':
player.attack(monster, logs);
if (monster.hp <= 0) {
console.log(`${monster.name} 처치!! 다음 스테이지!`);
player.hp += 50;
console.log(` 체력이 50 증가 !! 현재 체력 : ${player.hp} `);
logs.push(chalk.green(`${player.name}${player.attacks} 공격!`));
increaseStats(player, stage);
const dropRate = 1;
if (Math.random() < dropRate) {
const newEquipment = new Equipment('검', 10, 5);
player.inventory.push(newEquipment);
logs.push(chalk.green('검을 주웠다!'));
}
}
break;
case '2':
player.equip();
break;
default: {
console.log('잘못된 선택');
break;
}
}
} else {
const damage = monster.attack(player);
logs.push(chalk.red(`${monster.name} ${damage} 공격!`));
}

if (monster.hp > 0) {
logs.push(chalk.red(` 몬스터 공격 후 플레이어 체력 : ${player.hp}`));
} else {
console.log('몬스터의 체력이 0 이하입니다.');
}
if (player.hp <= 0) {
console.log(`으악`);
break;
}
}
};

 

일단 금요일에도 계속 의문이였던 내용 스피드와 관련해서 몬스터는 내 턴이 오지 않을때마다 계속, 내 턴이 끝날때마다 플레이어를 한대씩 때려야한다.

 

하지만 무슨 이유인지 내 턴이 아닐때는 한 대부터 여러번 잘 때리는데 내 턴일때는 else아래 if가 실행이 되어 로그만 출력이 되는 문제...

 

이게 사실 금요일에 해결이 되었던 문제인데 장비 관련해서 함수를 몇개 더 추가하고 갑자기 또 이런다..

 

그래서 조건 중첩문을 검색해서 이 블로그 저 블로그 다 뒤져서 찾아본거같은데 아직도 이유를 잘 모르겠다.

 

스위치 안에 케이스 2번 장비와 관련된 함수에서 반환 값이 있으면 브레이크로 통과를 안하고 else로 안간다는 말이 있던데

 

1번을 해도 else로 안가고 심지어 equip함수에는 return이 없다.

 

1번에는 몬스터 어택 함수에서 return을 하는 부분이 있어서 혹시 맞나?? 하긴 한데 2번은 그럼 왜 안되는지...

 

이게 찾아본 내용들이 다 if 안의 switch만 다룬 내용들이지 if switch else와 관련된 내용을 다룬 정보를 찾기 어렵다. 원래 안되는건가???????

 

이 내용은 월요일까지 해결을 못하면 본 캠프 출석 하고 바로 질문을 하러 가야겠다........................

 

===================================================================================

추가 내용

원래 else로 안간다............... 처음부터 설계를 잘못했다...................................................................................

 

그냥 주고 받는 식으로 할껄 괜히 이상한거 넣어가지고.................................................................

아무튼 수정!!

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

class Skill {
constructor(name, probability, effect) {
this.name = name;
this.probability = probability;
this.effect = effect;
}
}

const combo = new Skill('연속 공격', 0.3, (player, monster, logs) => {
for (let i = 0; i < 3; i++) {
player.attack(monster, logs);
}
logs.push(chalk.green(`연속 공격을 성공!`));
});

class Player {
constructor(player) {
this.name = '';
this.hp = 100;
this.attacks = 10;
this.defense = 5;
this.speed = 12;
this.inventory = [];
}

equip(item) {
console.log('아이템 선택 후 엔터 두번');
console.log('현재 장비 목록 :');
if (this.equippedItem) {
console.log(`[장착] ${this.equippedItem.name}`);
}
this.inventory.forEach((item, index) => {
console.log(
`${index + 1}. ${item.name} (공격력 +${item.attackBonus}, 방어력 +${item.defenseBonus})`,
);
});
console.log('0. 장착 취소');

const equipChoice = readlineSync.question('장비를 선택하세요 : ');
let selectedItem;

if (equipChoice === '0') {
if (this.equippedItem) {
this.unequip();
console.log('장착 해제!');
} else {
console.log('장착된 장비가 없습니다.');
}
} else if (equipChoice > 0 && equipChoice <= this.inventory.length) {
const selectedItem = this.inventory[equipChoice - 1];
this.equip(selectedItem);
console.log(`${selectedItem.name} 장착!`);
} else {
console.log('잘못된 입력입니다.');
}

if (equipChoice > 0 && equipChoice <= this.inventory.length) {
const selectedItem = this.inventory[equipChoice - 1];
if (selectedItem instanceof Equipment) {
this.equippedItem = selectedItem;
this.attacks += selectedItem.attackBonus || 0;
this.defense += selectedItem.defenseBonus || 0;
console.log(`${selectedItem.name} 장착!`);
console.log(`현재 공격력: ${this.attacks}, 방어력: ${this.defense}`);
} else {
console.log('장착 실패: 장착할 수 없는 아이템입니다.');
}
} else {
console.log('잘못된 입력입니다.');
}
}

unequip() {
if (this.equippedItem) {
this.attacks -= this.equippedItem.attackBonus;
this.defense -= this.equippedItem.defenseBonus;
this.equippedItem = null;
console.log('장착 해제!');
} else {
console.log('장착된 장비가 없습니다.');
}
}

attack(monster, logs) {
const critical = 0.1;
const Cri = Math.random() < critical;
const inidamage = this.attacks - monster.defense;
const random = Math.random() * 20 - 1;
const damage = Math.max(1, Math.round(inidamage + random));
const finalDamage = Cri ? damage * 2 : damage;
monster.hp -= finalDamage > 0 ? finalDamage : 1;

logs.push(chalk.green(`${this.name}${finalDamage}${Cri ? ' (크리티컬!)' : ''} 공격!`));

if (Math.random() < combo.probability) {
combo.effect(this, monster, logs);
return;
}
}
}

function increaseStats(player) {
const increase = 30;
player.attacks += Math.floor(Math.random() * increase) + 10;
player.defense += Math.floor(Math.random() * increase);

console.log(
chalk.green(`공격력: ${player.attacks}, 방어력: ${player.defense}, 스피드: ${player.speed}`),
);
}

class Equipment {
constructor(name, attackBonus, defenseBonus) {
this.name = name;
this.attackBonus = attackBonus;
this.defenseBonus = defenseBonus;
}
}

class Monster {
constructor(stage) {
this.hp = stage * 100;
this.attacks = stage * 20;
this.defense = stage * 6;
this.speed = stage * 1;
this.name = `몬스터${stage}`;
}

attack(player) {
const inidamage = this.attacks - player.defense;
const random = Math.random() * 20 - 10;
const damage = Math.max(1, Math.round(inidamage + random));
player.hp -= damage;
console.log(`${this.name}${damage} 공격!`);
return damage;
}
}

function displayStatus(stage, player, monster) {
console.log(chalk.magentaBright(`\n=== Current Status ===\n`));
console.log(
chalk.cyanBright(`\n | Stage: ${stage} \n`) +
chalk.blueBright(
`\n | 플레이어 정보 | 체력 ${player.hp} | 공격력 ${player.attacks} | 방어력 ${player.defense} | 스피드 ${player.speed} | \n | 장착 장비: ${player.equippedItem ? player.equippedItem.name : '없음'} |\n`,
) +
chalk.redBright(
`\n | 몬스터 정보 | 체력 ${monster.hp} | 공격력 ${monster.attacks} | 방어력 ${monster.defense} | 스피드 ${monster.speed} | \n`,
),
);
console.log(chalk.magentaBright(`\n=====================\n`));
}

function Turn(player, monster) {
const speedy = player.speed - monster.speed;
if (speedy < 0) {
speedy = 0;
}
const probability = 0.5 + speedy * 0.01;
return Math.random() < probability ? 'player' : 'monster';
}

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

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

logs.forEach((log) => console.log(log));

turns = Turn(player, monster);

if (turns === 'player') {
console.log(chalk.green(`\n플레이어의 턴입니다.`));
console.log(chalk.green(`\n1. 공격한다 2. 장비 장착 - 몬스터가 때림.`));
const choice = readlineSync.question(chalk.bgGray('선택 > '));

logs.push(chalk.green(`**** ${choice}를 선택 ****`));

switch (choice) {
case '1':
player.attack(monster, logs);
if (monster.hp <= 0) {
console.log(`${monster.name} 처치!! 다음 스테이지!`);
player.hp += 50;
console.log(` 체력이 50 증가 !! 현재 체력 : ${player.hp} `);
logs.push(chalk.green(`${player.name}${player.attacks} 공격!`));
increaseStats(player, stage);
const dropRate = 1;
if (Math.random() < dropRate) {
const newEquipment = new Equipment('검', 10, 5);
player.inventory.push(newEquipment);
logs.push(chalk.green('검을 주웠다!'));
}
}
break;
case '2':
player.equip();
break;
default: {
console.log('잘못된 선택');
break;
}
}
}

if (monster.hp > 0) {
const damage = monster.attack(player);
logs.push(chalk.red(`${monster.name} ${damage} 공격!`));
logs.push(chalk.red(` 몬스터 공격 후 플레이어 체력 : ${player.hp}`));
} else {
console.log('몬스터의 체력이 0 이하입니다.');
}
if (player.hp <= 0) {
console.log(`으악`);
break;
}
}
};

export async function startGame() {
const player = new Player();
let stage = 1;

while (stage <= 10) {
const monster = new Monster(stage);
await battle(stage, player, monster);

stage++;
}
}

 

그래도 이 과정을 통해서 if와 switch에 대해서 완벽하게 이해 한 것 같다. 이제 딱 원하는대로!!

금요일에 되었다고 생각한 이유는 아마 break 위치가 이상했거나 현재 플레이어 체력 로그만 보고 몬스터가 나를 때렸다고 생각했던 것 같다.

이래서 기본기가 중요하다 하나보다. 그래도 다행히 오늘 안에는 과제를 끝낼 수 있을 것 같다.