자료구조/수업과제
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;
}
}
}