Guest User

Untitled

a guest
Jun 23rd, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.30 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3.  
  4. namespace XOX
  5. {
  6. internal class Program
  7. {
  8. private static void Main()
  9. {
  10. new Game().Init();
  11.  
  12. Console.WriteLine("\n\nPress any key to quit.");
  13. Console.ReadKey();
  14. }
  15. }
  16.  
  17. internal class Game
  18. {
  19. public void Init()
  20. {
  21. var controller = new Controller();
  22. controller.InitEmptyGameField();
  23. controller.GameLoop();
  24. }
  25. }
  26.  
  27. internal class Model
  28. {
  29. public static GameFieldStatus[] GameField = new GameFieldStatus[9];
  30. public static GameStatusEnum GameStatus = GameStatusEnum.Playing;
  31. public enum GameFieldStatus
  32. {
  33. Empty = 0,
  34. X,
  35. O
  36. }
  37.  
  38. public enum GameStatusEnum
  39. {
  40. Playing,
  41. XWon,
  42. OWon,
  43. Tie
  44. }
  45. }
  46.  
  47. internal class View
  48. {
  49. public static void PrintGameField()
  50. {
  51. for (var i = 1; i <= Model.GameField.Length; i++)
  52. {
  53. Console.Write($"| {ParseGameFieldStatus(Model.GameField[i - 1], i)} |");
  54. if (i != 0 && i % 3 == 0)
  55. Console.Write("\n");
  56. }
  57. }
  58.  
  59. public static void PrintErrorNotANumber()
  60. {
  61. Console.Clear();
  62. Console.WriteLine("\nError: This was not a number. Please try again. \n");
  63. }
  64.  
  65. public static void PrintErrorFieldTaken()
  66. {
  67. Console.Clear();
  68. Console.WriteLine("\nError: This field is already taken. Please try again. \n");
  69. }
  70.  
  71. public static void PrintErrorWrongNumber()
  72. {
  73. Console.Clear();
  74. Console.WriteLine("Please enter a valid number. \n");
  75. }
  76.  
  77.  
  78. public static void PrintWaitForInput()
  79. {
  80. Console.WriteLine("Please enter the fieldnumber you want to mark with X: ");
  81. }
  82.  
  83. public static void ClearConsole()
  84. {
  85. Console.Clear();
  86. }
  87.  
  88. public static void PrintGameStatus()
  89. {
  90. switch (Model.GameStatus)
  91. {
  92. case Model.GameStatusEnum.Playing:
  93. break;
  94. case Model.GameStatusEnum.XWon:
  95. Console.WriteLine("Player won the game! :)\n\n");
  96. break;
  97. case Model.GameStatusEnum.OWon:
  98. Console.WriteLine("PC won the game! :(\n\n");
  99. break;
  100. case Model.GameStatusEnum.Tie:
  101. Console.WriteLine("Nobody won, tie. :|\n\n");
  102. break;
  103. default:
  104. throw new ArgumentOutOfRangeException();
  105. }
  106. }
  107.  
  108. private static string ParseGameFieldStatus(Model.GameFieldStatus status, int position = 0)
  109. {
  110. switch (status)
  111. {
  112. case Model.GameFieldStatus.Empty:
  113. return $" {position} ";
  114. case Model.GameFieldStatus.X:
  115. return " X ";
  116. case Model.GameFieldStatus.O:
  117. return " O ";
  118. default:
  119. throw new ArgumentOutOfRangeException(nameof(status), status, null);
  120. }
  121. }
  122. }
  123.  
  124. internal class Controller
  125. {
  126. private static bool _wrongPlayerMove;
  127.  
  128. public void GameLoop()
  129. {
  130. for (;;)
  131. {
  132. View.PrintGameField();
  133. View.PrintWaitForInput();
  134.  
  135. ParsePlayerInput(Console.ReadKey());
  136.  
  137. CheckForWinCondition();
  138. if (ParseWinCondition())
  139. break;
  140.  
  141. if(!_wrongPlayerMove) // only move when player has entered a sane and vaild input
  142. MakeEnemyMove();
  143.  
  144. CheckForWinCondition();
  145. if (ParseWinCondition())
  146. break;
  147.  
  148. }
  149.  
  150. View.PrintGameField(); // print the game one more time to celebrate wins visually ;)
  151. }
  152.  
  153. public void InitEmptyGameField()
  154. {
  155.  
  156. for (var i = 0; i < Model.GameField.Length; i++)
  157. {
  158. Model.GameField[i] = Model.GameFieldStatus.Empty;
  159. }
  160. }
  161.  
  162. private static void ParsePlayerInput(ConsoleKeyInfo input)
  163. {
  164. if (int.TryParse(input.KeyChar.ToString(), out var intResult))
  165. {
  166. _wrongPlayerMove = false; // reset dirty flag
  167.  
  168. if (intResult < 1)
  169. {
  170. _wrongPlayerMove = true;
  171. View.PrintErrorWrongNumber();
  172. return;
  173. }
  174.  
  175. if (Model.GameField[intResult - 1] == Model.GameFieldStatus.Empty)
  176. Model.GameField[intResult - 1] = Model.GameFieldStatus.X;
  177. else
  178. {
  179. View.PrintErrorFieldTaken();
  180. _wrongPlayerMove = true;
  181. return;
  182. }
  183.  
  184.  
  185. View.ClearConsole();
  186. }
  187. else
  188. {
  189. _wrongPlayerMove = true;
  190. View.PrintErrorNotANumber();
  191. }
  192. }
  193.  
  194. private static bool ParseWinCondition()
  195. {
  196. if (Model.GameStatus == Model.GameStatusEnum.Playing) return false;
  197.  
  198. View.PrintGameStatus();
  199. return true;
  200. }
  201.  
  202.  
  203. private static void MakeEnemyMove()
  204. {
  205. // get available fields array positions, read: an array of array positions, where GameFieldStatus is empty
  206. var emptyFieldsArrayPosition = Model.GameField.Select((s, i) => new {i, s})
  207. .Where(t => t.s == Model.GameFieldStatus.Empty)
  208. .Select(t => t.i)
  209. .ToArray();
  210.  
  211. // TODO: Make enemy smarter
  212. // chose one array position of the earlier created array
  213. var randomEmptyArrayPosition = new Random().Next(0, emptyFieldsArrayPosition.Length-1);
  214. var chosenField = emptyFieldsArrayPosition[randomEmptyArrayPosition];
  215.  
  216. Model.GameField[chosenField] = Model.GameFieldStatus.O;
  217. }
  218.  
  219. private static void CheckForWinCondition()
  220. {
  221.  
  222. if (CheckHorizontal(Model.GameFieldStatus.X) || CheckVertical(Model.GameFieldStatus.X) ||
  223. CheckDiagonal(Model.GameFieldStatus.X))
  224. {
  225. Model.GameStatus = Model.GameStatusEnum.XWon;
  226. return;
  227. }
  228.  
  229.  
  230. if (CheckHorizontal(Model.GameFieldStatus.O) || CheckVertical(Model.GameFieldStatus.O) ||
  231. CheckDiagonal(Model.GameFieldStatus.O))
  232. {
  233. Model.GameStatus = Model.GameStatusEnum.OWon;
  234. return;
  235. }
  236.  
  237.  
  238. if (Model.GameField.Any(x => x == (int) Model.GameStatusEnum.Playing)) return; // not all fields filled yet, early out
  239.  
  240. Model.GameStatus = Model.GameStatusEnum.Tie; // all fields filled, no winner -> tie
  241.  
  242. }
  243.  
  244. private static bool CheckHorizontal(Model.GameFieldStatus checkForThisPlayer)
  245. {
  246. for (var i = 0; i < Model.GameField.Length; i += 3)
  247. {
  248. if (Model.GameField[i] == checkForThisPlayer && Model.GameField[i + 1] == checkForThisPlayer &&
  249. Model.GameField[i + 2] == checkForThisPlayer)
  250. return true;
  251. }
  252.  
  253. return false;
  254. }
  255.  
  256. private static bool CheckVertical(Model.GameFieldStatus checkForThisPlayer)
  257. {
  258. for (var i = 0; i < 3; i++)
  259. {
  260. if (Model.GameField[i] == checkForThisPlayer && Model.GameField[i + 3] == checkForThisPlayer &&
  261. Model.GameField[i + 6] == checkForThisPlayer)
  262. return true;
  263. }
  264.  
  265. return false;
  266. }
  267.  
  268. private static bool CheckDiagonal(Model.GameFieldStatus checkForThisPlayer)
  269. {
  270. if (Model.GameField[0] == checkForThisPlayer && Model.GameField[4] == checkForThisPlayer &&
  271. Model.GameField[8] == checkForThisPlayer)
  272. return true;
  273.  
  274. if (Model.GameField[2] == checkForThisPlayer && Model.GameField[4] == checkForThisPlayer &&
  275. Model.GameField[6] == checkForThisPlayer)
  276. return true;
  277.  
  278. return false;
  279. }
  280. }
  281. }
Add Comment
Please, Sign In to add comment