Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

동구의_C# & Unity_개발일지

2024.01.15 내일배움캠프 16일차 TIL C#_ProGramming(알고리즘, C# 심화) 본문

C#

2024.01.15 내일배움캠프 16일차 TIL C#_ProGramming(알고리즘, C# 심화)

mongle_0l 2024. 1. 15. 14:53

내일은 팀 과제 던전 게임만들기 제출 일이다.

팀원들에 도움으로 필수 구현은 완성하였지만 뭔가 아쉽다 ㅠㅠ 더 만들수 있지 않을까!?


알고리즘 코드카타 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();
        }
    }
}