동구의_C# & Unity_개발일지
2024.01.15 내일배움캠프 16일차 TIL C#_ProGramming(알고리즘, C# 심화) 본문
내일은 팀 과제 던전 게임만들기 제출 일이다.
팀원들에 도움으로 필수 구현은 완성하였지만 뭔가 아쉽다 ㅠㅠ 더 만들수 있지 않을까!?
알고리즘 코드카타 3일차
두 수의 합
문제 설명
문제 설명정수 num1과 num2가 주어질 때, num1과 num2의 합을 return하도록 soltuion 함수를 완성해주세요.
using System;
public class Solution {
public int solution(int num1, int num2) {
int answer = num1 + num2;
return answer;
}
}
몫 구하기
문제 설명
정수 num1, num2가 매개변수로 주어질 때, num1을 num2로 나눈 몫을 return 하도록 solution 함수를 완성해주세요.
using System;
public class Solution {
public int solution(int num1, int num2) {
int answer = num1 / num2;
return answer;
}
}
팀 과제 던전 게임 만들기
private static void ChangeTextColor(string text, ConsoleColor consoleColor)
{
Console.ForegroundColor = consoleColor;
Console.WriteLine(text);
Console.ResetColor();
}
# 사용된 예시
ChangeTextColor("상태보기", ConsoleColor.Green);
ChangeTextColor("Battle!!", ConsoleColor.DarkYellow);
ChangeTextColor("Victory!", ConsoleColor.Green);
'ChangeTextColor' 메서드는 콘솔 출력의 텍스트 색을 지정된 색으로 임시로 변경하고, 지정된 텍스트를 인쇄한 다음, 텍스트 색을 다시 디폴트 상태로 재설정하는 유틸리티 메서드이다.
새로알게 된것!
public object Clone()
{
return this.MemberwiseClone();
}
'Clone' 메서드는 어떤 클래스나 개체가 자체적으로 정의한 메서드로, 일반적으로 해당 객체를 복제하여 새로운 객체를 반환하는 역할을 한다.
'MemberwiseClone' 메서드는 현재 개체의 멤버 변수들을 복사하여 같은 값으로 초기화된 새로운 개체를 생성한다. 그러나 이 복사는 얕은 복사로서, 참조 형식의 멤버 변수들은 동일한 객체를 참조하게 된다. 따라서 원본 객체와 복제된 객체가 같은 참조를 공유하게 된다.
ICloneable과 Clone (feat.Chat GPT )
'ICloneable' 인터페이스: 'ICloneable' 인터페이스는 .NET Framework에서 제공되는 인터페이스로, 개체의 얕은 복사(shallow copy)를 지원하는 메서드 'Clone'을 정의합니다. 이 인터페이스를 구현하려면 'Clone' 메서드를 제공해야 합니다. 'Clone' 메서드는 얕은 복사를 지원하기 때문에, 참조 형식의 멤버 변수들은 같은 객체를 참조하게 됩니다.
'Clone' 메서드: 'Clone' 메서드는 어떤 클래스나 개체가 자체적으로 정의한 메서드로, 일반적으로 해당 객체를 복제하여 새로운 객체를 반환하는 역할을 합니다. 'ICloneable' 인터페이스를 구현하지 않고도 'Clone' 메서드를 직접 구현할 수 있습니다. 하지만, 이 경우에는 특별한 규약이나 표준에 따르지 않으므로 사용자는 메서드의 동작 방식을 명확히 이해해야 합니다.
따라서 'ICloneable'은 인터페이스로서 얕은 복사를 지원하기 위한 것이며, 'Clone'은 그냥 메서드의 이름으로, 해당 개체를 복제하는 데 사용되는 메서드를 가리킵니다. 때때로, 클래스가 'ICloneable'을 구현하면서 'Clone' 메서드를 구현하는 경우가 많습니다.
오늘의 오류!!
공격 버튼을 눌렀을 때 숫자 버튼만 있는 몬스터들만 나와야 되는데 몬스터 정보가 중복되어 한꺼번에 나오고 있다.
static void playerInfo()
{
Console.WriteLine($"[내정보]");
Console.WriteLine($"{_player}");
Console.WriteLine("");
}
static void monsterInfo()
{
foreach (Monster monster in _monsters)
{
if (monster.IsDead())
{
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"{monster}");
Console.ResetColor();
}
else
{
Console.WriteLine($"{monster}");
}
}
Console.Write("\n");
}
player 정보와 monster 정보에 함수를 따로 만들어
static void Attack()
{
Console.Clear();
ChangeTextColor("Battle!!\n", ConsoleColor.DarkYellow);
for (int i = 0; i < _monsters.Count; i++)
{
Console.WriteLine($"{i + 1}. {_monsters[i]}");
}
Console.WriteLine("");
playerInfo(); // 플레이어 정보
Console.WriteLine("0. 취소\n");
Console.WriteLine("대상을 선택해주세요.");
Console.Write(">>");
int choice = CheckVailedInput(0, _monsters.Count);
if (choice == 0)
{
Battle();
}
else
{
Attack(_monsters[choice - 1]);
}
}
private static void Battle()
{
Console.Clear();
ChangeTextColor("Battle!!", ConsoleColor.DarkYellow);
Console.WriteLine("");
Console.WriteLine("[몬스터 정보]");
monsterInfo(); // 몬스터 정보
playerInfo(); // 플레이어 정보
Console.WriteLine("1. 공격");
Console.WriteLine("0. 나가기\n");
Console.WriteLine("원하시는 행동을 입력해주세요.");
Console.Write(">>");
switch (CheckVailedInput(0, 1))
{
case 0:
StartMenu();
break;
case 1:
Attack();
break;
}
}
필요한 곳에 직접 갔다 쓰면
숫자만 적힌 몬스터들이 뜬다!
♧필수구현 전체 코드♣
더보기
using System.Numerics;
using System.Reflection.Emit;
using System.Xml.Linq;
namespace spartaTextDungeon
{
internal class Program
{
static Player? _player;
static List<Monster>? _monsters;
static void Main(string[] args)
{
GameDataSetting();
PrintStartLogo();
StartMenu();
}
private static void GameDataSetting()
{
_player = new Player("Chad", "전사", 100, 100, 10, 5, 1500, 1);
List<Monster> createMonster = new List<Monster> {
new Monster("미니언", 15, 5, 6, 0, 2),
new Monster("대포미니언", 25, 8, 10, 1, 5),
new Monster("공허충", 10, 3, 8, 2, 3) };
_monsters = RandomMonster(createMonster);
}
private static List<Monster> RandomMonster(List<Monster> monsters)
{
List<Monster> saveMonster = new List<Monster>();
Random random = new Random();
int rndcnt = random.Next(1, 5);
for (int i = 0; i < rndcnt; i++)
{
int rndIndex = random.Next(0, monsters.Count);
Monster selectedMonster = (Monster)monsters[rndIndex].Clone();
saveMonster.Add(selectedMonster);
}
return saveMonster;
}
private static void StartMenu()
{
Console.Clear();
Console.WriteLine($"◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆");
Console.WriteLine($"스파르타 마을에 오신 여러분 환영합니다.");
Console.WriteLine($"이곳에서 던전으로 들어가기 전 활동을 할 수 있습니다.");
Console.WriteLine($"◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆");
Console.WriteLine();
Console.WriteLine("1.상태 보기");
Console.WriteLine("2.전투 시작");
Console.WriteLine("");
Console.WriteLine("원하시는 행동을 입력해주세요.");
Console.Write(">>");
switch (CheckVailedInput(1, 2))
{
case 1:
State();
break;
case 2:
Battle();
break;
}
}
private static void Battle()
{
Console.Clear();
ChangeTextColor("Battle!!", ConsoleColor.DarkYellow);
Console.WriteLine("");
Console.WriteLine("[몬스터 정보]");
monsterInfo();
playerInfo();
Console.WriteLine("1. 공격");
Console.WriteLine("0. 나가기\n");
Console.WriteLine("원하시는 행동을 입력해주세요.");
Console.Write(">>");
switch (CheckVailedInput(0, 1))
{
case 0:
StartMenu();
break;
case 1:
Attack();
break;
}
}
static void monsterInfo()
{
foreach (Monster monster in _monsters)
{
if (monster.IsDead())
{
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"{monster}");
Console.ResetColor();
}
else
{
Console.WriteLine($"{monster}");
}
}
Console.Write("\n");
}
static void playerInfo()
{
Console.WriteLine($"[내정보]");
Console.WriteLine($"{_player}");
Console.WriteLine("");
}
static void Attack()
{
Console.Clear();
ChangeTextColor("Battle!!\n", ConsoleColor.DarkYellow);
for (int i = 0; i < _monsters.Count; i++)
{
Console.WriteLine($"{i + 1}. {_monsters[i]}");
}
Console.WriteLine("");
playerInfo();
Console.WriteLine("0. 취소\n");
Console.WriteLine("대상을 선택해주세요.");
Console.Write(">>");
int choice = CheckVailedInput(0, _monsters.Count);
if (choice == 0)
{
Battle();
}
else
{
Attack(_monsters[choice - 1]);
}
}
static void Attack(Monster monster)
{
if (monster.IsDead())
{
Console.Clear();
Console.WriteLine("잘못된 입력입니다. 이미 죽은 몬스터를 공격할 수 없습니다.");
Console.WriteLine("\n0 다음");
switch (CheckVailedInput(0, 0))
{
case 0:
Battle();
break;
}
}
else
{
Console.WriteLine("");
Console.WriteLine($"몬스터 {monster.Name}을(를) 공격합니다.");
int damage = CalculateDamage(_player.Attack);
monster.HP -= damage;
Console.WriteLine($"몬스터에게 {damage}의 데미지를 입혔습니다.");
if (monster.IsDead())
{
Console.WriteLine($"몬스터 {monster.Name}을(를) 처치했습니다.");
}
Console.WriteLine("\n0 다음");
switch (CheckVailedInput(0, 0))
{
case 0:
EnemyPhase();
break;
}
}
}
private static void EnemyPhase()
{
Console.Clear();
bool allMonstersDead = true;
foreach (Monster monster in _monsters)
{
if (!monster.IsDead())
{
Console.Clear();
allMonstersDead = false;
ChangeTextColor("Battle!!\n", ConsoleColor.DarkYellow);
Console.WriteLine($"Lv.{monster.Level} {monster.Name}의 공격!");
Console.WriteLine($"{_player.Name} 을(를) 맞췄습니다. [데미지 : {monster.Attack}]\n");
Console.WriteLine($"Lv.{_player.Level} {_player.Name}");
Console.Write($"HP {_player.HP}");
_player.HP -= monster.Attack;
Console.WriteLine($"-> {_player.HP}\n");
Console.WriteLine("0.다음\n");
Console.WriteLine("대상을 선택해주세요.\n");
Console.Write(">>");
CheckVailedInput(0, 0);
}
}
if (allMonstersDead)
{
Console.Clear();
ChangeTextColor("Battle!! - Result", ConsoleColor.DarkYellow);
Console.WriteLine("");
ChangeTextColor("Victory!", ConsoleColor.Green);
Console.WriteLine("");
Console.WriteLine($"던전에서 몬스터 {_monsters.Count}마리를 잡았습니다.");
Console.WriteLine("");
Console.WriteLine($"{_player}\n");
Console.WriteLine("0. 다음\n>>");
CheckVailedInput(0, 0);
Console.Clear();
Console.WriteLine("게임 종료");
Console.ReadKey();
Environment.Exit(0);
}
if (_player.IsDead())
{
Console.Clear();
ChangeTextColor("Battle!! - Result", ConsoleColor.DarkYellow);
Console.WriteLine("");
ChangeTextColor("You Lose", ConsoleColor.Red);
Console.WriteLine("");
Console.WriteLine($"{_player}\n");
Console.WriteLine("0. 다음\n>>");
Console.WriteLine("");
CheckVailedInput(0, 0);
Console.ReadKey();
Environment.Exit(0);
}
Battle();
}
static void DisplayInfo(Player player, Monster[] monsters)
{
Console.Clear();
ChangeTextColor("Battle!!", ConsoleColor.DarkYellow);
Console.WriteLine($"\n[내정보]");
Console.WriteLine($"{player}");
Console.WriteLine("");
foreach (var monster in monsters)
{
Console.WriteLine($"{monster}");
}
Console.WriteLine("");
}
static void Attack(Player player, Monster[] monsters)
{
DisplayInfo(player, monsters);
for (int i = 0; i < monsters.Length; i++)
{
Console.WriteLine($"{i + 1}. {monsters[i]}");
}
Console.WriteLine("0. 취소");
int choice = GetUserInput(monsters.Length);
if (choice == 0)
{
Console.WriteLine("취소되었습니다.");
}
else
{
Attack(player, monsters[choice - 1]);
DisplayInfo(player, monsters);
if (!monsters[choice - 1].IsDead())
{
DisplayInfo(player, monsters);
}
}
Console.WriteLine("\n게임 종료");
Console.ReadKey();
}
static void Attack(Player player, Monster monster)
{
if (monster.IsDead())
{
Console.WriteLine("잘못된 입력입니다. 이미 죽은 몬스터를 공격할 수 없습니다.");
}
else
{
Console.WriteLine($"몬스터 {monster.Name}을(를) 공격합니다.");
int damage = CalculateDamage(player.Attack);
monster.TakeDamage(damage);
Console.WriteLine($"몬스터에게 {damage}의 데미지를 입혔습니다.");
if (monster.IsDead())
{
Console.WriteLine($"몬스터 {monster.Name}을(를) 처치했습니다.");
}
}
}
static int CalculateDamage(int baseAttack)
{
Random random = new Random();
double error = Math.Ceiling(baseAttack * 0.1);
int randomValue = random.Next(-(int)error, (int)error + 1);
return baseAttack + randomValue;
}
static int GetUserInput(int maxChoice)
{
int choice;
while (!int.TryParse(Console.ReadLine(), out choice) || choice < 0 || choice > maxChoice)
{
Console.WriteLine("올바르지 않은 입력입니다. 다시 입력해주세요.");
}
return choice;
}
private static void State()
{
Console.Clear();
ChangeTextColor("상태보기", ConsoleColor.Green);
Console.WriteLine("캐릭터의 정보가 표시됩니다.");
Console.WriteLine();
Console.WriteLine
($" LV. {_player.Level}\n " +
$"{_player.Name} ( {_player.Class} )\n " +
$"공격력 : {_player.Attack}\n " +
$"방어력 : {_player.Def}\n " +
$"체 력 : {_player.HP}\n " +
$"Gold : {_player.Gold}");
Console.WriteLine("");
Console.WriteLine("0. 나가기");
Console.WriteLine("");
Console.Write("원하시는 행동을 입력 해주세요.\n>>");
switch (CheckVailedInput(0, 0))
{
case 0:
StartMenu();
break;
}
}
private static void ChangeTextColor(string text, ConsoleColor consoleColor)
{
Console.ForegroundColor = consoleColor;
Console.WriteLine(text);
Console.ResetColor();
}
private static int CheckVailedInput(int min, int max)
{
int saveIndex;
while (true)
{
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("잘못된 입력입니다");
continue;
}
if (!int.TryParse(input, out saveIndex))
{
Console.WriteLine("잘못된 입력입니다");
continue;
}
if (saveIndex < min || saveIndex > max)
{
Console.WriteLine("잘못된 입력입니다");
continue;
}
break;
}
return saveIndex;
}
internal class Player
{
public string Name { get; }
public string Class { get; }
public int MaxHP { get; }
public int HP { get; set; }
public int Attack { get; }
public int Def { get; }
public int Gold { get; }
public int Level { get; }
public Player(string name, string playerClass, int maxHP, int hp, int attack, int def, int gold, int level)
{
Name = name;
Class = playerClass;
MaxHP = maxHP;
HP = hp;
Attack = attack;
Def = def;
Gold = gold;
Level = level;
}
public void TakeDamage(int damage)
{
HP -= damage;
if (HP < 0)
{
HP = 0;
}
}
public bool IsDead()
{
return HP <= 0;
}
public override string ToString()
{
return $"Lv.1 {Name} ({Class})\nHP {HP}/{MaxHP}";
}
}
internal class Monster
{
public string Name { get; }
public int MaxHP { get; }
public int HP { get; set; }
public int Attack { get; }
public int Level { get; set; }
public Monster(string name, int maxHP, int hp, int attack, int checkIndex, int level)
{
Name = name;
MaxHP = maxHP;
HP = maxHP;
Attack = attack;
Level = level;
}
public object Clone()
{
return this.MemberwiseClone();
}
public bool IsDead()
{
return HP <= 0;
}
public void TakeDamage(int damage)
{
HP -= damage;
if (HP < 0)
{
HP = 0;
}
}
public override string ToString()
{
string status = IsDead() ? "Dead" : $"HP {HP}";
return $"Lv{Level} {Name} {status}";
}
}
static void PrintStartLogo()
{
Console.WriteLine($"▄████████ ▄███████▄ ▄████████ ▄████████ ███ ▄████████\n" +
$"███ ███ ███ ███ ███ ███ ███ ███ ▀█████████▄ ███ ███\n" +
$"███ █▀ ███ ███ ███ ███ ███ ███ ▀███▀▀██ ███ ███\n" +
$"███ ███ ███ ███ ███ ▄███▄▄▄▄██▀ ███ ▀ ███ ███\n" +
$"▀███████████ ▀█████████▀ ▀███████████ ▀▀███▀▀▀▀▀ ███ ▀███████████\n" +
$" ███ ███ ███ ███ ▀███████████ ███ ███ ███\n" +
$" ▄█ ███ ███ ███ ███ ███ ███ ███ ███ ███\n" +
$"▄████████▀ ▄████▀ ███ █▀ ███ ███ ▄████▀ ███ █▀\n" +
$"\n" +
$"████████▄ ███ █▄ ███▄▄▄▄ ▄██████▄ ▄████████ ▄██████▄ ███▄▄▄▄\n" +
$"███ ▀███ ███ ███ ███▀▀▀██▄ ███ ███ ███ ███ ███ ███ ███▀▀▀██▄\n" +
$"███ ███ ███ ███ ███ ███ ███ █▀ ███ █▀ ███ ███ ███ ███\n" +
$"███ ███ ███ ███ ███ ███ ▄███ ▄███▄▄▄ ███ ███ ███ ███\n" +
$"███ ███ ███ ███ ███ ███ ▀▀███ ████▄ ▀▀███▀▀▀ ███ ███ ███ ███\n" +
$"███ ███ ███ ███ ███ ███ ███ ███ ███ █▄ ███ ███ ███ ███\n" +
$"███ ▄███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███\n" +
$"████████▀ ████████▀ ▀█ █▀ ████████▀ ██████████ ▀██████▀ ▀█ █▀\n" +
$"================================================================================\n" +
$" PRESS ANYKEY TO START \n" +
$"================================================================================\n");
Console.ReadKey();
}
}
}
'C#' 카테고리의 다른 글
2024.01.17 내일배움캠프 18일차 TIL C#_ProGramming(알고리즘, C# 심화) (0) | 2024.01.17 |
---|---|
2024.01.16 내일배움캠프 17일차 TIL C#_ProGramming(알고리즘, C# 심화) (0) | 2024.01.16 |
2024.01.12 내일배움캠프 15일차 TIL C#_ProGramming(알고리즘, C# 심화) (0) | 2024.01.12 |
2024.01.11 내일배움캠프 14일차 TIL C#_ProGramming(알고리즘, C# 심화) (0) | 2024.01.11 |
2024.01.10 내일배움캠프 13일차 TIL C#_ProGramming(알고리즘, C# 심화) (0) | 2024.01.10 |