자료구조/수업과제

04/04 게임 알고리즘 시험

박준희 2021. 4. 1. 00:45

 

 

'꿈의 나라'라는 머드 게임 구현연습

 

로그인 기능 구현
로그인 시 아이디 입력으로 기존유저와 신규유저 판별함
기존유저는 아이디와 일치하는 비밀번호를 입력하는것으로 게임 시작
신규유저는 이름과 비밀번호 성별등을 입력받아 회원가입

유저 로그인 정보는 user_data.json에 저장

 

인벤토리 기능 구현
아이템을 버리고 줍는 기능을 구현

아이템은 user_info.json에 저장

 

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    class Program
    {
        static void Main(string[] args)
        {
            new App();
        }
    }
}

 

App.cs

namespace Exam01
{
    public class App
    {
        public App()
        {            
            new Login();
            new GameLauncher();
        }
    }
}


GameManager.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Exam01
{
    public class GameManager
    {
        private static GameManager instance;
        public UserData userData;

        public Dictionary<int, TextResourceData> dicTexts;
        public Dictionary<int, UserData> dicUsers;
        public Dictionary<int, UserInfo> dicUserInfos;

        public const string TEXT_DATA_PATH = "./text_data.json";
        public const string USER_DATA_PATH = "./user_data.json";
        public const string USER_INFO_PATH = "./user_info.json";

        public GameManager()
        {
            LoadTextData(TEXT_DATA_PATH);
            LoadUserData(USER_DATA_PATH);
            LoadUserInfo(USER_INFO_PATH);
        }

        public static GameManager GetInstance()
        {
            if(GameManager.instance == null)
            {
                instance = new GameManager();
            }
            return instance;
        }

        private void LoadTextData(string path)
        {
            string json = File.ReadAllText(path);
            TextResourceData[] texts = JsonConvert.DeserializeObject<TextResourceData[]>(json);
            dicTexts = texts.ToDictionary(x => x.id);
        }

        private void LoadUserData(string path)
        {
            if(File.Exists(path))
            {
                string json = File.ReadAllText(path);
                UserData[] users = JsonConvert.DeserializeObject<UserData[]>(json);
                dicUsers = users.ToDictionary(x => x.no);                
            }
            else
            {
                dicUsers = new Dictionary<int, UserData>();
            }
        }

        private void LoadUserInfo(string path)
        {
            if (File.Exists(path))
            {
                string json = File.ReadAllText(path);
                UserInfo[] users = JsonConvert.DeserializeObject<UserInfo[]>(json);
                dicUserInfos = users.ToDictionary(x => x.no);
            }
            else
            {
                dicUserInfos = new Dictionary<int, UserInfo>();
            }
        }
    }
}

 

TextResourceData.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    public class TextResourceData
    {
        public int id;
        public string text;
    }
}

 

GameLauncher.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Exam01
{
    public class GameLauncher
    {
        UserInfo userInfo;
        List<Item> ItemsInTheGround = new List<Item>();
        public GameLauncher()
        {
            ItemsInTheGround.Add(new Item("막대기"));
            Console.WriteLine(GameManager.GetInstance().dicTexts[10].text);
            ExplainMap();
            Thread thread1 = new Thread(UserInfoSave);
            thread1.Start();
            Thread thread2 = new Thread(PrintTick);
            thread2.Start();

            //파일 내 유저 인포 데이터가 없으면 튜토리얼 시작
            if(!File.Exists(GameManager.USER_INFO_PATH) || !GameManager.GetInstance().dicUserInfos.ContainsKey(GameManager.GetInstance().userData.no))
            {
                userInfo = new UserInfo(GameManager.GetInstance().userData.no, GameManager.GetInstance().userData.name + "님의 방");
                Console.WriteLine("초기 아이템 지급");
                userInfo.inventory.items.Add(new Item("교복모자"));
                userInfo.inventory.items.Add(new Item("교복바지"));
                userInfo.inventory.items.Add(new Item("대걸레"));
                userInfo.inventory.items.Add(new Item("학교 졸업뱃지"));
                userInfo.inventory.items.Add(new Item("책가방"));
                userInfo.inventory.items.Add(new Item("실내화"));
                userInfo.inventory.items.Add(new Item("칠판지우개"));
                userInfo.inventory.items.Add(new Item("교복허리끈"));
                userInfo.inventory.items.Add(new Item("교복웃옷"));                
                GameManager.GetInstance().dicUserInfos.Add(GameManager.GetInstance().userData.no , userInfo);
                string json = JsonConvert.SerializeObject(GameManager.GetInstance().dicUserInfos.Values.ToArray());
                File.WriteAllText(GameManager.USER_INFO_PATH,json);
            }
            else
            {
                userInfo = GameManager.GetInstance().dicUserInfos[GameManager.GetInstance().userData.no];
            }


            while(true)
            {
                var command = Console.ReadLine().Split(' ');
                if(command.Length == 1)
                {
                    switch(command[0])
                    {
                        case "동":
                        case "서":
                        case "남":
                        case "북":
                        case "위":
                        case "아래":
                            Console.WriteLine("{0}쪽으로 갑니다", command[0]);
                            break;
                        case "나가":
                            break;
                        case "꿈깨":
                            ExitGame();
                            break;
                        case "저장":
                            SaveInfo();
                            Console.WriteLine("당신의 현재 상태를 저장합니다.");
                            break;
                        case "소지품":
                            PrintInventory();
                            break;
                        case "도움":
                        case "도움말":
                            Console.WriteLine(GameManager.GetInstance().dicTexts[11].text);
                            break;
                        default:
                            Console.WriteLine("{0}::그런 명령은 없습니다.", command[0]);
                            break;
                    }
                }
                else if(command.Length > 1)
                {
                    switch (command[command.Length-1])
                    {
                        case "집다":
                            PickUpItem(command[0]);
                            break;
                        case "버리다":
                            DesertItem(command[0]);
                            break;
                        default:
                            Console.WriteLine("{0}::그런 명령은 없습니다.", command[command.Length - 1]);
                            break;
                    }
                }
                PrintHpMpMvInfo();
            }            
        }

        private void PrintInventory()
        {
            Console.WriteLine("\n물건의 무게 [{0}/{1}] 물건의 부피[{2}/{3}]", userInfo.inventory.weight, userInfo.inventory.capacity, userInfo.inventory.volume, userInfo.inventory.capacity);
            Console.WriteLine("\t\t 당신이 가지고 있는 물건들");
            foreach(Item item in userInfo.inventory.items)
            {
                Console.WriteLine(" {0}개 :: {1}", item.count, item.name);
            }
        }

        private void UserInfoSave()
        {
            while(true)
            {
                Thread.Sleep(20000);
                GameManager.GetInstance().dicUserInfos[GameManager.GetInstance().userData.no] = userInfo;
                string json = JsonConvert.SerializeObject(GameManager.GetInstance().dicUserInfos.Values.ToArray());
                File.WriteAllText(GameManager.USER_INFO_PATH, json);
                PrintHpMpMvInfo();
            }
        }

        private void SaveInfo()
        {
            GameManager.GetInstance().dicUserInfos[GameManager.GetInstance().userData.no] = userInfo;
            string json = JsonConvert.SerializeObject(GameManager.GetInstance().dicUserInfos.Values.ToArray());
            File.WriteAllText(GameManager.USER_INFO_PATH, json);            
        }

        private void ExitGame()
        {
            SaveInfo();
            Console.WriteLine("꿈의 나라 여행이 즐거우셨는지 모르겠네요.꾸벅~\n너무 많은 여행은 피곤하겠죠 ? 조금씩만 하도록 하세용~~\n그럼 이만.\n                                       안암동에서 씨알.");
            Console.WriteLine("BYE");
            Environment.Exit(0);
        }

        private void PickUpItem(string itemName)
        {
            Item pickUpItem = ItemsInTheGround.Find(x => x.name == itemName);
            if (pickUpItem != null)
            {                
                userInfo.inventory.items.Add(pickUpItem);
                ItemsInTheGround.Remove(pickUpItem);
                Console.WriteLine("당신이 {0}을 집었습니다.", itemName);
            }
            else
            {
                Console.WriteLine("그런 물건은 없는데요?");
            }
        }

        private void DesertItem(string itemName)
        {
            Item desertItem = userInfo.inventory.items.Find(x => x.name == itemName);
            if (desertItem != null)
            {
                ItemsInTheGround.Add(desertItem);
                userInfo.inventory.items.Remove(desertItem);
                Console.WriteLine("당신이 {0}을 버렸습니다.", itemName);
            }
            else
            {
                Console.WriteLine("그런 물건은 없는데요?");
            }
        }

        private void PrintHpMpMvInfo()
        {
            Console.WriteLine("[HP {0}, MP {1}, MV {2}]", userInfo.hp, userInfo.mp, userInfo.mv);
        }

        private void ExplainMap()
        {
            Console.WriteLine("───━ {0}님의 방 ━───", GameManager.GetInstance().userData.name);
            Console.WriteLine("\n침대가 저만치 놓여있고, 그 주변에 여기 저기 물건들이 흩어져 있다. \n정신없이 널려져 있는 물건들을 보니 정리를 꽤나 안하는 모양이다.\n밖으로 나가는 길이 보이기는 하는데 어디로 가는 길인지는 모르겠다.");
        }

        private void PrintTick()
        {
            while(true)
            {
                Thread.Sleep(60000);
                Console.WriteLine("\n####  [틱방송]=========<<< 틱이 다가옵니다 >>>=========  ####\n");
                PrintHpMpMvInfo();
                Thread.Sleep(5000);
                Console.WriteLine("밥 줘~~~ 밥 줘~~~~ 밥 줘~~~~~ 밥 줘~~~~~~ 밥 줘~~~~~~~");
                Console.WriteLine("물 줘~~~ 물 줘~~~~ 물 줘~~~~~ 물 줘~~~~~~ 물 줘~~~~~~~");
                Console.WriteLine("\n####  [틱방송]=========<<< 틱이 지나갔어요 >>>=========  ####\n");
                PrintHpMpMvInfo();
            }

        }
    }
}

 

UserData.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    public class UserData
    {
        public int no;
        public string id;
        public string name;
        public string pass;
        public string gender;
        public int tribe;
    }
}

 

UserInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    public class UserInfo
    {
        public int no;
        public string position;
        public int hp;
        public int mp;
        public int mv;
        public Inventory inventory;
        public UserInfo (int no , string position, int hp = 84, int mp = 44, int mv = 82)
        {
            this.no = no;
            this.position = position;
            this.hp = hp;
            this.mp = mp;
            this.mv = mv;
            inventory = new Inventory(94);
        }
    }
}

 

 

Inventory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    public class Inventory
    {
        public List<Item> items;
        public int capacity;
        public int volume;
        public int weight;
        public Inventory(int capacity)
        {            
            this.capacity = capacity;
            items = new List<Item>();
        }
        
        
    }
}

 

Item.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam01
{
    public class Item
    {
        public int itemNum;
        public string name;
        public int count;
        public int volume;
        public int weight;
        
        public Item(string name, int count = 1, int volume = 1, int weight = 1)
        {
            this.name = name;
            this.count = count;
            this.volume = volume;
            this.weight = weight;
        }
    }
}

 

Login.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Exam01
{
    public class Login
    {
        
        public Login()
        {
            UserData user = null;
            string userId = "";

            //초기화면 출력
            Console.WriteLine(GameManager.GetInstance().dicTexts[1].text);
            Console.WriteLine("\n[Enter]를 누르세요.\n");
            while (true)
            {
                if ((ConsoleKey)Console.ReadKey().KeyChar == ConsoleKey.Enter)
                {                    
                    break;
                }
            }
            Console.WriteLine(GameManager.GetInstance().dicTexts[2].text);

            //아이디 입력
            bool flag = true;
            while (true)
            {                
                if(flag)
                {
                    while (true)
                    {
                        Console.WriteLine("\n당신의 아이디는 ?");
                        userId = Console.ReadLine();
                        if (userId != null && userId.Length < 9)
                        {                            
                            break;
                        }
                        Console.WriteLine("아이디의 길이가 8자가 넘네요??\n정말 당신 아이디 맞아요 ? 그러지 말구 정확히 입력해 주세요. ^^; ");
                    }
                    Console.WriteLine("당신의 아이디가 '{0}' 맞습니까? [Y/n] ", userId);
                }

                flag = false;
                string yesOrNo = Console.ReadLine().Trim().ToLower();
                
                if ("y"== yesOrNo || "예" == yesOrNo || "yes" == yesOrNo )
                {
                    break;
                }
                else if("n" == yesOrNo || "아니오" == yesOrNo || "no" == yesOrNo)
                {
                    flag = true;
                    continue;
                }
                
                if(!flag)
                {
                    Console.WriteLine("(예 / 아니오)(YES / NO)(Y / N) 중 하나로 대답해주세요..");
                }                
            }

            IEnumerable<UserData> searchUser = GameManager.GetInstance().dicUsers.Values.Where(x => x.id == userId);
            if (searchUser.Count() != 0)
            {
                //기존유저
                GameManager.GetInstance().userData = user = searchUser.First();
                Console.WriteLine("어머 안녕하세요~~  {0}님 또 오셨군요.", user.name);
                Console.WriteLine("\n암호를 입력해주십시요. ");
                while (true)
                {
                    if (user.pass == Console.ReadLine())
                    {
                        break;
                    }
                    Console.WriteLine("\n암호가 틀린데요?? 다시한번 입력해 주세요. ");
                }
            }
            else
            {
                user = new UserData();
                user.id = userId;
                Console.WriteLine("어머 처음 오셨네요~~  환영해요~~");
                Console.WriteLine("\n당신은 꿈의나라에서 누구라 불립니까?[중단: 끝]");
                while (true)
                {
                    var name = Console.ReadLine();
                    if (name.Length < 9)
                    {
                        if (GameManager.GetInstance().dicUsers.Values.Where(x => x.name == name).Count() != 0)
                        {
                            Console.WriteLine("\n이미 사용중인 이름이군요. 다른 이름을 넣어주세요.");
                            continue;
                        }
                        else
                        {
                            Console.WriteLine("\n새로운 이름이군요.이 이름을 원하십니까 ? (Y / n)");

                            var yesOrNo = Console.ReadLine();
                            if ("y" == yesOrNo || "예" == yesOrNo || "yes" == yesOrNo)
                            {
                                user.name = name;
                                break;
                            }
                            else if ("n" == yesOrNo || "아니오" == yesOrNo || "no" == yesOrNo)
                            {
                                Console.WriteLine("\n그러면 다시 이름을 입력하세요. ");
                            }
                            else
                            {
                                Console.WriteLine("\n(예 / 아니오)(YES / NO)(Y / N) 중 하나로 대답해주세요..");
                            }
                        }
                    }
                    else if (name == "끝")
                    {
                        Console.WriteLine("BYE");
                        Environment.Exit(0);
                    }
                    else
                    {
                        Console.WriteLine("사용자의 이름은 8자를 넘을 수 없습니다.");
                    }
                }

                user.no = GameManager.GetInstance().dicUsers.Count == 0 ? 1 : GameManager.GetInstance().dicUsers.Values.OrderBy(x => x.no).Last().no + 1;

                while (true)
                {
                    Console.WriteLine("\n암호를 입력해주십시요. ");
                    var tmpPass1 = Console.ReadLine();
                    Console.WriteLine("\n확인을 위해 다시한번 암호를 입력해주십시요. ");
                    var tmpPass2 = Console.ReadLine();
                    if (tmpPass1 == tmpPass2)
                    {
                        user.pass = tmpPass1;
                        break;
                    }
                    Console.WriteLine("\n먼저 입력하신 암호와 다르군요.\n암호를 다시 정하시죠. ");
                }

                Console.WriteLine("\n당신의 성별은 무엇입니까? (남[M]/여[F]) ");
                while (true)
                {
                    var tmp = Console.ReadLine();
                    if (tmp == "남" || tmp == "여" || tmp == "M" || tmp == "F")
                    {
                        switch (tmp)
                        {
                            case "남":
                            case "M":
                                tmp = "M";
                                break;
                            case "여":
                            case "F":
                                tmp = "F";
                                break;
                        }
                        user.gender = tmp;
                        break;
                    }
                    else
                    {
                        Console.WriteLine("\n성별이 어떻게 된다고요 ?? (남[M] / 여[F])");
                    }
                }

                Console.WriteLine("꿈의 나라에는 다음과 같은 아홉 신족이 있습니다.\n== 천신(1) / 지신(2) / 마신(3) / 용신(4) / 호신(5) / 수신(6) / 화신(7) / 광신(8) / 사신(9) ==\n당신은 어느 신족에 속하십니까 ? (해당 번호를 입력하세요) ");
                while (true)
                {
                    var tmp = int.Parse(Console.ReadLine());
                    if (tmp > 0 && tmp < 10)
                    {
                        user.tribe = tmp;
                        break;
                    }
                    else
                    {
                        Console.WriteLine("\n그런 신족은 없는데요 ? 다시한번 입력해주세요(1 - 9) ");
                    }
                }

                GameManager.GetInstance().dicUsers.Add(user.no, user);
                string json = JsonConvert.SerializeObject(GameManager.GetInstance().dicUsers.Values.ToArray());
                File.WriteAllText(GameManager.USER_DATA_PATH, json);
            }
            GameManager.GetInstance().userData = user;
        }        
    }
}