롤 구현하기
C#/과제 2019. 4. 10. 19:47사용한 것
Singleton Pattern, Dictionary, List, Interface, Json(load, save), DataTable, Vector, UML, 상속
인터페이스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public interface IAttackable { bool Attack(Character target); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public interface IMoveable { void Move(Vector2 targetPosition); } } | cs |
캐릭터
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 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class Character { public CharacterInfo charInfo; //생성자 public Character(CharacterInfo info) { this.charInfo = info; } //피해메소드 public virtual bool GetDamage(int damage) { return true; } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class Champion : Character { //생성자 public Champion(CharacterInfo info) : base(info) { } } } | cs |
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace AniviaVsNashor { public class Anivia : Champion, IAttackable, IMoveable { private float moveSpeed = 3.25f; private DataStorage dataStorage = DataStorage.GetInstance(); private Dictionary<int, CharacterData> dicData; //생성자 public Anivia(CharacterInfo info) : base(info) { this.dicData = this.dataStorage.dicCharData; } //피해메소드 public override bool GetDamage(int damage) { Console.WriteLine("{0}의 데미지를 입었습니다!", damage); this.charInfo.remainHp -= damage; if (this.charInfo.remainHp <= 0) { Console.WriteLine("체력이 0이 되어 에그니비아로 환생합니다."); Console.WriteLine("환생까지 10턴이 소모됩니다."); Thread.Sleep(500); return false; } Console.WriteLine("현재 체력 : ({0}/{1})", this.charInfo.remainHp, this.dicData[this.charInfo.id].maxHp); return true; } //거리를 리턴해주는 메소드 public float GetDistance(Vector2 targetPosition) { return Vector2.GetDistance(this.charInfo.position, targetPosition); } #region IAttackable, IMoveable 구현부분 public bool Attack(Character target) { Thread.Sleep(500); Console.WriteLine("\n{0}을 공격합니다.", this.dicData[target.charInfo.id].name); Console.WriteLine("{0}에게 {1}의 피해를 주었습니다!", this.dicData[target.charInfo.id].name, this.dicData[this.charInfo.id].damage); var alive = target.GetDamage(this.dicData[this.charInfo.id].damage); return alive; } public void Move(Vector2 targetPosition) //애니비아 이동속도 3.25 가정한다. { var distanceVector = targetPosition - this.charInfo.position; //거리벡터 var normalizeVector = Vector2.Normalize(distanceVector); //거리벡터의 단위벡터(방향벡터) var speedVector = normalizeVector * moveSpeed; //스칼라곱을 통하여 방향벡터로 향하는 속도벡터 산출 var distance = Vector2.GetDistance(this.charInfo.position, targetPosition); //타겟과의 거리 산출 while(true) { distance = Vector2.GetDistance(this.charInfo.position, targetPosition); Thread.Sleep(500); if (distance > this.dicData[this.charInfo.id].attackRange) { Console.WriteLine("사거리가 닿지 않아 이동합니다."); this.charInfo.position += speedVector; Console.WriteLine("현재 {0}의 위치 : ({1}/{2})", this.dicData[this.charInfo.id].name, this.charInfo.position.x, this.charInfo.position.y); } else if (distance <= this.dicData[this.charInfo.id].attackRange) { Console.WriteLine("사거리 내에 바론이 있습니다. 이동을 멈춥니다."); break; } } } #endregion } } | cs |
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class Eggnivia : Champion { private DataStorage dataStorage = DataStorage.GetInstance(); private Dictionary<int, CharacterData> dicData; private int remainTurn = 9; //생성자 public Eggnivia(CharacterInfo info) : base(info) { this.dicData = this.dataStorage.dicCharData; } //피해메소드 public override bool GetDamage(int damage) { Console.WriteLine("{0}의 데미지를 입었습니다!", damage); this.charInfo.remainHp -= damage; if (this.remainTurn > 0) { Console.WriteLine("현재 체력 : ({0}/{1})", this.charInfo.remainHp, this.dicData[this.charInfo.id].maxHp); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("애니비아의 환생까지 {0}턴 남았습니다.", this.remainTurn); Console.ForegroundColor = ConsoleColor.Gray; this.remainTurn--; return false; } Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("****에그니비아가 애니비아로 환생합니다!****"); Console.ForegroundColor = ConsoleColor.Gray; remainTurn = 9; return true; } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class Monster : Character { //생성자 public Monster(CharacterInfo info) : base(info) { } } } | cs |
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class NashorBaron : Monster, IAttackable { private DataStorage dataStorage = DataStorage.GetInstance(); private Dictionary<int, CharacterData> dicData; //생성자 public NashorBaron(CharacterInfo info) : base(info) { this.dicData = this.dataStorage.dicCharData; } //피해메소드 public override bool GetDamage(int damage) { this.charInfo.remainHp -= damage; if (this.charInfo.remainHp <= 0) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n바론이 죽었습니다!"); return false; } Console.WriteLine("{0}의 현재 체력 : ({1}/{2})", this.dicData[this.charInfo.id].name, this.charInfo.remainHp, this.dicData[this.charInfo.id].maxHp); return true; } #region IAttackable 구현부분 public bool Attack(Character target) { Console.WriteLine("\n{0}이 {1}를 공격합니다.", this.dicData[this.charInfo.id].name, this.dicData[target.charInfo.id].name); var alive = target.GetDamage(this.dicData[this.charInfo.id].damage); return alive; } #endregion } } | cs |
데이터
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 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class CharacterData { public int id; public string name; public int maxHp; public int remainHp; public int damage; public float attackRange; //생성자 public CharacterData() { } } } | cs |
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 29 30 31 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class DataStorage { private static DataStorage instance; public Dictionary<int, CharacterData> dicCharData; //생성자 private DataStorage() { } //인스턴스 리턴 메서드 public static DataStorage GetInstance() { if (DataStorage.instance == null) { DataStorage.instance = new DataStorage(); } return DataStorage.instance; } } } | cs |
인포
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class CharacterInfo { public int id; public int remainHp { get; set; } public Vector2 position; //생성자 public CharacterInfo(int id) { this.id = id; } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class UserInfo { public GameInfo gameInfo; public int userId { get; set; } public string userName { get; set; } //생성자 public UserInfo(GameInfo info) { this.gameInfo = info; } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class GameInfo { public List<CharacterInfo> listCharInfo; //생성자 public GameInfo() { } } } | cs |
벡터
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class Vector2 { public float x; public float y; //생성자 public Vector2(float x, float y) { this.x = x; this.y = y; } //operator public static Vector2 operator +(Vector2 a, Vector2 b) { return new Vector2((a.x + b.x), (a.y + b.y)); } public static Vector2 operator -(Vector2 a, Vector2 b) { return new Vector2((a.x - b.x), (a.y - b.y)); } public static Vector2 operator *(Vector2 a, float b) { return new Vector2((a.x * b), (a.y * b)); } //calculate vector //정규화 메소드 public static Vector2 Normalize(Vector2 a) { return new Vector2((a.x / Vector2.GetLength(a)), (a.y / Vector2.GetLength(a))); } //길이리턴 메소드 public static float GetLength(Vector2 a) { return (float)Math.Sqrt(Math.Pow(a.x, 2) + Math.Pow(a.y, 2)); } //거리리턴 메소드 public static float GetDistance(Vector2 a, Vector2 b) { return (float)Math.Sqrt(Math.Pow(a.x - b.x, 2) + Math.Pow(a.y - b.y, 2)); } } } | cs |
실행부
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { class Program { static void Main(string[] args) { App app = new App(); app.Start(); } } } | cs |
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 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AniviaVsNashor { public class App { private GameLauncher gameLauncher; //생성자 public App() { Console.WriteLine("App이 실행되었습니다."); this.gameLauncher = new GameLauncher(); } //앱실행 public void Start() { this.gameLauncher.Start(); } } } | cs |
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Threading; using Newtonsoft.Json; namespace AniviaVsNashor { public class GameLauncher { private DataStorage dataStorage; private Anivia anivia; private NashorBaron baron; private Eggnivia eggnivia; private UserInfo userInfo; //생성자 public GameLauncher() { this.dataStorage = DataStorage.GetInstance(); } //런쳐실행 public void Start() { bool success; success = this.LoadData("./data/character_data.json"); if(success) { Console.WriteLine("데이터 로딩에 성공했습니다!"); } success = this.LoadData("./info/user_info.json"); if (success) { Console.WriteLine("환영합니다."); } this.SetData(); this.UpdateData(); this.GameStart(); } //데이터로드 public bool LoadData(string path) { switch(path) { case "./data/character_data.json": { var isExist = File.Exists(path); if(isExist == false) { throw new Exception("게임을 플레이하기 위한 데이터가 없습니다"); } this.dataStorage.dicCharData = new Dictionary<int, CharacterData>(); var temp = File.ReadAllText(path); var dataJson = JsonConvert.DeserializeObject<CharacterData[]>(temp); for (int index = 0; index < dataJson.Length; index++) { this.dataStorage.dicCharData.Add(index, dataJson[index]); } return true; } case "./info/user_info.json": { var isExist = File.Exists(path); if(isExist == false) { Console.WriteLine("새로운 유저의 데이터를 생성합니다."); this.userInfo = new UserInfo(new GameInfo()); this.userInfo.userId = 0; this.userInfo.userName = "유저"; this.userInfo.gameInfo.listCharInfo = new List<CharacterInfo>(); this.userInfo.gameInfo.listCharInfo.Add(new CharacterInfo(0)); this.userInfo.gameInfo.listCharInfo[0].remainHp = this.dataStorage.dicCharData[0].maxHp; this.userInfo.gameInfo.listCharInfo[0].position = new Vector2(0, 0); this.userInfo.gameInfo.listCharInfo.Add(new CharacterInfo(1)); this.userInfo.gameInfo.listCharInfo[1].remainHp = this.dataStorage.dicCharData[1].maxHp; this.userInfo.gameInfo.listCharInfo[1].position = new Vector2(0, 0); this.userInfo.gameInfo.listCharInfo.Add(new CharacterInfo(2)); this.userInfo.gameInfo.listCharInfo[2].remainHp = this.dataStorage.dicCharData[2].maxHp; this.userInfo.gameInfo.listCharInfo[2].position = new Vector2(15, 15); } else if(isExist) { Console.WriteLine("기존 유저의 데이터를 불러옵니다."); var temp = File.ReadAllText(path); var dataJson = JsonConvert.DeserializeObject<UserInfo>(temp); this.userInfo = dataJson; } return true; } default: { Console.WriteLine("경로가 잘못되었습니다."); return false; } } } //객체생성 public void SetData() { this.anivia = new Anivia(this.userInfo.gameInfo.listCharInfo[0]); this.eggnivia = new Eggnivia(this.userInfo.gameInfo.listCharInfo[1]); this.baron = new NashorBaron(this.userInfo.gameInfo.listCharInfo[2]); } //게임시작 public void GameStart() { bool aniviaAlive = true; bool baronAlive = true; Console.WriteLine("**************게임을 시작합니다*************"); while(true) { this.UpdateData(); Console.WriteLine("\n1.계속하기 2.저장하고 종료하기"); var continueKey = Console.ReadKey().Key; if(continueKey == ConsoleKey.D2) { this.SaveData(); break; } if (this.dataStorage.dicCharData[this.anivia.charInfo.id].attackRange <= this.anivia.GetDistance(this.baron.charInfo.position)) { Thread.Sleep(500); this.anivia.Move(this.baron.charInfo.position); } Thread.Sleep(500); baronAlive = this.anivia.Attack(this.baron); if(baronAlive == false) { Console.WriteLine("\n*****축하합니다. 게임을 클리어하셨습니다!*****"); break; } Thread.Sleep(1000); aniviaAlive = this.baron.Attack(this.anivia); if(aniviaAlive == false) { for(int remainTurn = 10; remainTurn > 0; remainTurn--) { Thread.Sleep(1000); this.baron.Attack(this.eggnivia); } this.anivia.charInfo.remainHp = this.dataStorage.dicCharData[this.anivia.charInfo.id].maxHp; this.eggnivia.charInfo.remainHp = this.dataStorage.dicCharData[this.eggnivia.charInfo.id].maxHp; } } Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine("게임을 종료합니다."); } //데이터업데이트 (CharacterInfo List Update) public void UpdateData() { this.userInfo.gameInfo.listCharInfo[0].remainHp = this.anivia.charInfo.remainHp; this.userInfo.gameInfo.listCharInfo[0].position = this.anivia.charInfo.position; this.userInfo.gameInfo.listCharInfo[1].remainHp = this.eggnivia.charInfo.remainHp; this.userInfo.gameInfo.listCharInfo[1].position = this.eggnivia.charInfo.position; this.userInfo.gameInfo.listCharInfo[2].remainHp = this.baron.charInfo.remainHp; this.userInfo.gameInfo.listCharInfo[2].position = this.baron.charInfo.position; } //데이터를 파일로 저장 public void SaveData() { if(Directory.Exists("./info") == false) { Directory.CreateDirectory("./info"); } var dataJson = JsonConvert.SerializeObject(this.userInfo); File.WriteAllText("./info/user_info.json", dataJson); } } } | cs |
'C# > 과제' 카테고리의 다른 글
Character의 Move, Attack, MoveAttack 구현 (0) | 2019.04.08 |
---|---|
Inventory + Singleton (0) | 2019.04.07 |
Hash란? (0) | 2019.04.04 |
13. 인벤토리 구현하기 (0) | 2019.03.27 |
12. WoW 캐릭터 생성 과제 (2단계+α 까지 완료) (0) | 2019.03.27 |