└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # С# through game examples 2 | 3 | ## Content 4 | 5 | 0. [Hello World](#hello-world) 6 | 1. [Variables types](#variables-types) 7 | 2. [List](#list) 8 | 3. [Delegate](#delegate) 9 | 4. [Class Encapsulation](#class-encapsulation) 10 | 5. [Class Inheritance](#class-inheritance) 11 | 6. [Class Dispose](#class-dispose) 12 | 7. [Interfaces](#interfaces) 13 | 8. [Strategy pattern](#strategy-pattern) 14 | 9. [Observer pattern](#observer-pattern) 15 | 10. [Decorator pattern](#decorator-pattern) 16 | 11. [Factory method pattern](#factory-method-pattern) 17 | 12. [Abstract factory pattern](#abstract-factory-pattern) 18 | 13. [Singleton pattern](#singleton-pattern) 19 | 14. [Command pattern](#command-pattern) 20 | 15. [Adapter pattern](#adapter-pattern) 21 | 16. [Facade pattern](#facade-pattern) 22 | 17. [Template method pattern](#template-method-pattern) 23 | 18. [Iterator pattern](#iterator-pattern) 24 | 19. [Composite pattern](#composite-pattern) 25 | 20. [State pattern](#state-pattern) 26 | 21. [Proxy pattern](#proxy-pattern) 27 | 28 | ## Hello World 29 | 30 | ```c# 31 | using System; 32 | 33 | namespace hello_world 34 | { 35 | class Program 36 | { 37 | static void Main() 38 | { 39 | Console.WriteLine("Hello World!\nIt's guessing game!\n"); 40 | 41 | var secret = new Random().Next(100) + 1; 42 | var attempt = 0; 43 | var count = 0; 44 | 45 | do 46 | { 47 | count += 1; 48 | 49 | Console.Write("Your {0}try: ", count > 1 ? "next " : String.Empty); 50 | 51 | var thisIsNumber = int.TryParse(Console.ReadLine(), out attempt); 52 | 53 | if (!thisIsNumber) 54 | { 55 | Console.WriteLine("It doesn't look like a number...\n"); 56 | } 57 | else if (attempt > secret) 58 | { 59 | Console.WriteLine("Overshoot!\n"); 60 | } 61 | else if (attempt < secret) 62 | { 63 | Console.WriteLine("Undershoot!\n"); 64 | } 65 | else 66 | { 67 | Console.WriteLine("Exactly! You WIN!\n\nNumber of attempts: {0}", count); 68 | } 69 | } 70 | while (secret != attempt); 71 | 72 | Console.ReadLine(); 73 | } 74 | } 75 | } 76 | ``` 77 | ## Variables types 78 | 79 | ```c# 80 | using System; 81 | using System.Collections.Generic; 82 | using System.Linq; 83 | 84 | namespace csharp_through_code_examples 85 | { 86 | class Program 87 | { 88 | private static Random random = new Random(); 89 | 90 | private static Dictionary> AllTypes = new Dictionary> 91 | { 92 | ["sbyte"] = new List { "-128", "127" }, 93 | ["byte"] = new List { "0", "255" }, 94 | ["short"] = new List { "-32768", "32767" }, 95 | ["int"] = new List { "-2147483648", "2147483647" }, 96 | ["uint"] = new List { "0", "4294967295" }, 97 | ["ushort"] = new List { "0", "65535" }, 98 | ["ulong"] = new List { "0", "18446744073709551615" }, 99 | ["long"] = new List { "-9223372036854775808", "9223372036854775807" }, 100 | ["bool"] = new List { "true", "false" }, 101 | ["string"] = new List { "abcdefg", "foo bar" }, 102 | ["char"] = new List { "a", "\\0", "\\u006A" }, 103 | }; 104 | 105 | private static string Variants(string correct) 106 | { 107 | var types = new List { correct }; 108 | 109 | for (int i = 1; i < 3; i++) 110 | { 111 | string nextVariant; 112 | 113 | do 114 | { 115 | nextVariant = AllTypes.ElementAt(random.Next(AllTypes.Count)).Key; 116 | } 117 | while (types.Contains(nextVariant)); 118 | 119 | types.Add(nextVariant); 120 | } 121 | 122 | var randTypes = types.OrderBy(x => random.Next()).ToList(); 123 | 124 | return String.Format("{0}, {1} or {2}?", randTypes[0], randTypes[1], randTypes[2]); 125 | } 126 | 127 | static void Main() 128 | { 129 | var win = 0; 130 | var round = 0; 131 | 132 | Console.WriteLine("Try to guess the type of the variable by value!\n"); 133 | 134 | while (round < 5) 135 | { 136 | var test = AllTypes.ElementAt(random.Next(AllTypes.Count)).Key; 137 | var testLine = AllTypes[test][random.Next(AllTypes[test].Count)]; 138 | 139 | Console.Write("Var: {0}\nThis is: {1}\n> ", testLine, Variants(test)); 140 | 141 | var response = Console.ReadLine(); 142 | 143 | if (response == test) 144 | { 145 | Console.WriteLine("YES!\n"); 146 | win += 1; 147 | } 148 | else if (AllTypes.ContainsKey(response) && AllTypes[response].Contains(testLine)) 149 | { 150 | Console.WriteLine("Ow... But why not?\n"); 151 | win += 1; 152 | } 153 | else 154 | { 155 | Console.WriteLine("No ({0})\n", test); 156 | } 157 | 158 | round += 1; 159 | } 160 | 161 | Console.WriteLine("Result: {0}/5", win); 162 | Console.ReadLine(); 163 | } 164 | } 165 | } 166 | ``` 167 | 168 | ## List 169 | 170 | ```c# 171 | using System; 172 | using System.Collections.Generic; 173 | 174 | namespace csharp_through_code_examples 175 | { 176 | class Program 177 | { 178 | private static Random random = new Random(); 179 | 180 | private static List SecretWords = new List 181 | { 182 | "antelope", "bear", "cow", "donkey", "falcon", "gibbon", "horse", 183 | "iguana", "jaguar", "koala", "lion", "monkey", "octopus", "shark" 184 | }; 185 | 186 | private static List Opened = new List(); 187 | 188 | private static string ShowWord(string word) 189 | { 190 | for (int i = 0; i < word.Length; i++) 191 | { 192 | if (!Opened.Contains(word[i])) 193 | word = word.Replace(word[i], '*'); 194 | } 195 | 196 | return word; 197 | } 198 | 199 | private static bool WordOpened(string word) => 200 | !ShowWord(word).Contains("*"); 201 | 202 | static void Main() 203 | { 204 | Console.WriteLine("Try to guess the word!\n"); 205 | 206 | var word = SecretWords[random.Next(SecretWords.Count)]; 207 | var attempts = 0; 208 | 209 | do 210 | { 211 | Console.Write("Word: {0}\n{1}etter: ", ShowWord(word), (attempts > 0 ? "Next l" : "L")); 212 | 213 | var key = Char.ToLower(Console.ReadKey().KeyChar); 214 | 215 | if (word.Contains(key)) 216 | { 217 | Console.WriteLine("\nYES!\n"); 218 | Opened.Add(key); 219 | } 220 | else 221 | { 222 | Console.WriteLine("\nNo...\n"); 223 | } 224 | 225 | attempts += 1; 226 | } 227 | while (!WordOpened(word)); 228 | 229 | Console.WriteLine("You WIN!\nAttempts: {0}", attempts); 230 | Console.ReadLine(); 231 | } 232 | } 233 | } 234 | ``` 235 | 236 | ## Delegate 237 | 238 | ```c# 239 | using System; 240 | using System.Linq; 241 | 242 | namespace csharp_through_code_examples 243 | { 244 | class Program 245 | { 246 | private static Random random = new Random(); 247 | 248 | delegate string EnemyScreams(int screamCount); 249 | 250 | static string EnemyHit(int hits, string enemyName, EnemyScreams scream) => 251 | String.Format("{0} yells: {1}", enemyName, scream(hits)); 252 | 253 | static string OrcScream(int screamCount) => 254 | string.Concat(Enumerable.Repeat("Ouch! ", screamCount)); 255 | 256 | static string GoblinScream(int screamCount) => 257 | string.Concat(Enumerable.Repeat("Oops! ", screamCount)); 258 | 259 | static void Main() 260 | { 261 | Console.WriteLine("Try to hit the enemy!\n"); 262 | 263 | while (true) 264 | { 265 | EnemyScreams scream = null; 266 | 267 | Console.Write("How many hits > "); 268 | 269 | var success = int.TryParse(Console.ReadLine(), out int hits); 270 | var enemyName = String.Empty; 271 | 272 | if (!success || (hits <= 0)) 273 | { 274 | break; 275 | } 276 | else if (random.Next(100) % 2 == 0) 277 | { 278 | enemyName = "Orc"; 279 | scream = OrcScream; 280 | } 281 | else 282 | { 283 | enemyName = "Goblin"; 284 | scream = GoblinScream; 285 | } 286 | 287 | Console.WriteLine(EnemyHit(hits, enemyName, scream)); 288 | } 289 | } 290 | } 291 | } 292 | ``` 293 | 294 | ## Class Encapsulation 295 | 296 | ```c# 297 | using System; 298 | 299 | namespace csharp_through_code_examples 300 | { 301 | class Program 302 | { 303 | private static Random rand = new Random(); 304 | 305 | private class Goblin 306 | { 307 | public int Hitpoints { get; set; } 308 | 309 | public string Name() => "ugly goblin"; 310 | 311 | public void Wound() 312 | { 313 | Hitpoints -= rand.Next(5) + 1; 314 | } 315 | } 316 | 317 | static void Main() 318 | { 319 | Goblin goblin = new Goblin 320 | { 321 | Hitpoints = rand.Next(20) + 10, 322 | }; 323 | 324 | Console.WriteLine("You have to fight the {0} ({1} hitpoints)!\n" + 325 | "To hit him you have to type 'hit'!\n", goblin.Name(), goblin.Hitpoints); 326 | 327 | while (goblin.Hitpoints > 0) 328 | { 329 | Console.Write("> "); 330 | 331 | if (Console.ReadLine().ToLower() == "hit") 332 | { 333 | goblin.Wound(); 334 | 335 | Console.WriteLine("You hit him! His hitponts dropped to {0}\n", 336 | goblin.Hitpoints); 337 | } 338 | else 339 | { 340 | Console.WriteLine("I did not understand you...\n"); 341 | } 342 | } 343 | 344 | Console.WriteLine("YOU WON THIS BATTLE!\nNot surprisingly, but still..."); 345 | Console.ReadLine(); 346 | } 347 | } 348 | } 349 | ``` 350 | 351 | ## Class Inheritance 352 | 353 | ```c# 354 | using System; 355 | 356 | namespace csharp_through_code_examples 357 | { 358 | class Program 359 | { 360 | private static Random rand = new Random(); 361 | 362 | private class Сharacter 363 | { 364 | public int Hitpoints { get; set; } 365 | 366 | public string Name { get; set; } 367 | 368 | public void Wound() => 369 | Hitpoints -= rand.Next(5) + 1; 370 | } 371 | 372 | private class Hero : Сharacter 373 | { 374 | public string BeautifulSpeeches() => 375 | "Oh, it hurts, but I won't give up!"; 376 | } 377 | 378 | private class Goblin : Сharacter 379 | { 380 | public string Swearing() => 381 | "Oh, *$?@#&!! I hate this %#@*!!"; 382 | } 383 | 384 | static void Main() 385 | { 386 | Hero hero = new Hero 387 | { 388 | Name = "You", 389 | Hitpoints = rand.Next(20) + 10, 390 | }; 391 | 392 | Goblin goblin = new Goblin 393 | { 394 | Name = "Ugly goblin", 395 | Hitpoints = rand.Next(20) + 10, 396 | }; 397 | 398 | Console.WriteLine("You have {0} hitpoints and " + 399 | "gotta fight the {1} ({2} hitpoints)!\n" + 400 | "To hit him you have to type 'attack'!\n", 401 | hero.Hitpoints, goblin.Name, goblin.Hitpoints); 402 | 403 | while ((goblin.Hitpoints > 0) && (hero.Hitpoints > 0)) 404 | { 405 | Console.Write("> "); 406 | 407 | string action = Console.ReadLine(); 408 | 409 | if (action.ToLower() == "attack") 410 | { 411 | goblin.Wound(); 412 | 413 | Console.WriteLine("You hit him! " + 414 | "His hitponts dropped to {0}", goblin.Hitpoints); 415 | 416 | if (goblin.Hitpoints <= 0) 417 | continue; 418 | 419 | Console.WriteLine("{0}: {1}\n", goblin.Name, goblin.Swearing()); 420 | 421 | hero.Wound(); 422 | 423 | Console.WriteLine("{0} hit you! Your hitponts " + 424 | "dropped to {1}", goblin.Name, hero.Hitpoints); 425 | 426 | if (hero.Hitpoints > 0) 427 | Console.WriteLine("{0}: {1}\n", hero.Name, hero.BeautifulSpeeches()); 428 | } 429 | else 430 | { 431 | Console.WriteLine("I did not understand you...\n"); 432 | } 433 | } 434 | 435 | if (goblin.Hitpoints <= 0) 436 | { 437 | Console.WriteLine("\nYOU WON THIS BATTLE!"); 438 | } 439 | else 440 | { 441 | Console.WriteLine("\nYou lost this fight..."); 442 | } 443 | 444 | Console.ReadLine(); 445 | } 446 | } 447 | } 448 | ``` 449 | 450 | ## Class Dispose 451 | 452 | ```c# 453 | using System; 454 | 455 | namespace csharp_through_code_examples 456 | { 457 | class Program 458 | { 459 | private class Gandalf : IDisposable 460 | { 461 | public Gandalf() => 462 | Console.WriteLine("[constructor]\t\tGandalf was born in 2500 of the Third Age!"); 463 | 464 | public void Dispose() => 465 | Console.WriteLine("[dispose call]\t\tHey, Gandalf, you have to go!"); 466 | 467 | public void OrdinaryMagic() => 468 | Console.WriteLine("\t\t\tGandalf does something good!"); 469 | 470 | ~Gandalf() => 471 | Console.WriteLine("[finalizer]\t\tGandalf sailed away at 3200 of the Third Age!"); 472 | } 473 | 474 | static void GandalfHistory() 475 | { 476 | var gandalf = new Gandalf(); 477 | 478 | while (true) 479 | { 480 | if (Console.ReadKey(true).Key == ConsoleKey.Enter) 481 | { 482 | gandalf.Dispose(); 483 | break; 484 | } 485 | else 486 | { 487 | gandalf.OrdinaryMagic(); 488 | } 489 | } 490 | } 491 | 492 | static void GarbageCleaning() 493 | { 494 | Console.WriteLine("[garbage collector]\tThis is end of the Gandalf story!"); 495 | GC.Collect(); 496 | } 497 | 498 | static void Main() 499 | { 500 | GandalfHistory(); 501 | 502 | GarbageCleaning(); 503 | 504 | Console.ReadKey(); 505 | } 506 | } 507 | } 508 | ``` 509 | 510 | ## Interfaces 511 | 512 | ```c# 513 | using System; 514 | 515 | namespace csharp_through_code_examples 516 | { 517 | class Program 518 | { 519 | private static Random rand = new Random(); 520 | interface Movement 521 | { 522 | string Sound(); 523 | int Move(); 524 | } 525 | 526 | private class Foot : Movement 527 | { 528 | public string Sound() => "Step! Step! Step!"; 529 | public int Move() => 1; 530 | } 531 | 532 | private class Velo : Movement 533 | { 534 | public string Sound() => "Pedals turn! Turn! Turn!"; 535 | public int Move() => 4; 536 | } 537 | 538 | private class Car : Movement 539 | { 540 | public string Sound() => "On the highway whoosh!"; 541 | public int Move() => 25; 542 | } 543 | 544 | private class Helicopter : Movement 545 | { 546 | public string Sound() => "Helicopter propeller whoooosh!"; 547 | public int Move() => 300; 548 | } 549 | 550 | private class Airplane : Movement 551 | { 552 | public string Sound() => "Airport is left behind..."; 553 | public int Move() => 1000; 554 | } 555 | 556 | private static Movement Transport(string type) 557 | { 558 | switch (type.ToLower()) 559 | { 560 | case "velo": 561 | return new Velo(); 562 | 563 | case "car": 564 | return new Car(); 565 | 566 | case "helicopter": 567 | return new Helicopter(); 568 | 569 | case "airplane": 570 | return new Airplane(); 571 | 572 | case "foot": 573 | return new Foot(); 574 | 575 | default: 576 | return null; 577 | } 578 | } 579 | 580 | static void Main() 581 | { 582 | var distance = rand.Next(500, 3000); 583 | 584 | Console.WriteLine("You have to overcome the distance of {0} km!\n" + 585 | "Make a choice: airplane, helicopter, car, velo, foot?", distance); 586 | 587 | var steps = 0; 588 | 589 | while (true) 590 | { 591 | steps += 1; 592 | 593 | Console.Write("\n> "); 594 | 595 | var movement = Transport(Console.ReadLine()); 596 | 597 | if (movement == null) 598 | continue; 599 | 600 | var step = movement.Move(); 601 | 602 | distance -= step; 603 | 604 | Console.WriteLine(movement.Sound()); 605 | Console.WriteLine("You have covered {0} km!", step); 606 | 607 | if (distance < 0) 608 | { 609 | distance = Math.Abs(distance); 610 | Console.WriteLine("Overmuch! You need to go back {0} km!", distance); 611 | } 612 | else if (distance == 0) 613 | { 614 | Console.WriteLine("WIN! it took you {0} steps!", steps); 615 | break; 616 | } 617 | else 618 | { 619 | Console.WriteLine("{0} km left.", distance); 620 | } 621 | } 622 | 623 | Console.ReadLine(); 624 | } 625 | } 626 | } 627 | ``` 628 | 629 | ## Strategy pattern 630 | 631 | ```c# 632 | using System; 633 | 634 | namespace csharp_through_code_examples 635 | { 636 | interface WeaponBehavior 637 | { 638 | int Use(); 639 | string Name(); 640 | } 641 | 642 | class Character 643 | { 644 | public WeaponBehavior Weapon; 645 | public string Name; 646 | public int Hitpoints; 647 | } 648 | 649 | class SwordBehavior : WeaponBehavior 650 | { 651 | public int Use() => 5; 652 | public string Name() => "sword"; 653 | } 654 | 655 | class AxeBehavior : WeaponBehavior 656 | { 657 | public int Use() => 4; 658 | public string Name() => "axe"; 659 | } 660 | 661 | class СlubBehavior : WeaponBehavior 662 | { 663 | public int Use() => 3; 664 | public string Name() => "club"; 665 | } 666 | 667 | class WarhammerBehavior : WeaponBehavior 668 | { 669 | public int Use() => 6; 670 | public string Name() => "warhammer"; 671 | } 672 | 673 | class KnifeBehavior : WeaponBehavior 674 | { 675 | public int Use() => 2; 676 | public string Name() => "knife"; 677 | } 678 | 679 | class Program 680 | { 681 | static Character hero = new Character 682 | { 683 | Name = "Hero", 684 | Hitpoints = 15, 685 | Weapon = new SwordBehavior(), 686 | }; 687 | 688 | static Character orc = new Character 689 | { 690 | Name = "Orc", 691 | Hitpoints = 15, 692 | Weapon = new СlubBehavior(), 693 | }; 694 | 695 | static void Fight(Character whoAttack, Character beingAttacked) 696 | { 697 | if (whoAttack.Hitpoints <= 0) 698 | return; 699 | 700 | beingAttacked.Hitpoints -= whoAttack.Weapon.Use(); 701 | 702 | Console.WriteLine("{0} use {1}, {2} lost {3} hitpoints!", 703 | whoAttack.Name, whoAttack.Weapon.Name(), beingAttacked.Name, whoAttack.Weapon.Use()); 704 | } 705 | 706 | static WeaponBehavior ChangeWeapon() 707 | { 708 | Random newWeapon = new Random(); 709 | 710 | switch (newWeapon.Next(5)) 711 | { 712 | default: 713 | case 0: 714 | return new SwordBehavior(); 715 | 716 | case 1: 717 | return new AxeBehavior(); 718 | 719 | case 2: 720 | return new СlubBehavior(); 721 | 722 | case 3: 723 | return new WarhammerBehavior(); 724 | 725 | case 4: 726 | return new KnifeBehavior(); 727 | } 728 | } 729 | 730 | static void Main() 731 | { 732 | Console.WriteLine("This is an epic battle!\n"); 733 | 734 | while ((hero.Hitpoints > 0) && (orc.Hitpoints > 0)) 735 | { 736 | hero.Weapon = ChangeWeapon(); 737 | orc.Weapon = ChangeWeapon(); 738 | 739 | Fight(hero, orc); 740 | Fight(orc, hero); 741 | } 742 | 743 | Console.WriteLine("\n{0} WIN!!", orc.Hitpoints <= 0 ? hero.Name : orc.Name); 744 | } 745 | } 746 | } 747 | ``` 748 | 749 | ## Observer pattern 750 | 751 | ```c# 752 | using System; 753 | 754 | namespace csharp_through_code_examples 755 | { 756 | interface Subject 757 | { 758 | void Register(Observer observer); 759 | void Remove(Observer observer); 760 | void Hit(int hitpoints); 761 | } 762 | 763 | interface Observer 764 | { 765 | void Update(int hitpoints); 766 | } 767 | 768 | class Hero : Subject 769 | { 770 | List enemyList = new List(); 771 | 772 | public void Register(Observer enemy) => 773 | enemyList.Add(enemy); 774 | 775 | public void Remove(Observer enemy) => 776 | enemyList.Remove(enemy); 777 | 778 | public void Hit(int hitpoints) 779 | { 780 | foreach (Observer enemy in enemyList) 781 | enemy.Update(hitpoints); 782 | } 783 | } 784 | 785 | class Orc : Observer 786 | { 787 | int Hitpoints { get; set; } 788 | 789 | public Orc(int hitpoints) => 790 | Hitpoints = hitpoints; 791 | 792 | public void Update(int hitpoints) 793 | { 794 | Hitpoints -= hitpoints; 795 | 796 | if (Hitpoints > 0) 797 | Console.WriteLine("Ah! Orc wounded! Now hitpoints: {0}", Hitpoints); 798 | } 799 | } 800 | 801 | class Goblin : Observer 802 | { 803 | int Hitpoints { get; set; } 804 | 805 | public Goblin(int hitpoints) => 806 | Hitpoints = hitpoints; 807 | 808 | public void Update(int hitpoints) 809 | { 810 | Hitpoints -= hitpoints; 811 | 812 | if (Hitpoints > 0) 813 | Console.WriteLine("Oh! Goblin wounded! Now hitpoints: {0}", Hitpoints); 814 | } 815 | } 816 | 817 | class Program 818 | { 819 | static void Main() 820 | { 821 | var hero = new Hero(); 822 | var orc = new Orc(hitpoints: 30); 823 | var goblin = new Goblin(hitpoints: 20); 824 | 825 | hero.Register(enemy: orc); 826 | hero.Register(enemy: goblin); 827 | 828 | var action = String.Empty; 829 | 830 | Console.WriteLine("This is another epic battle!\n"); 831 | 832 | do 833 | { 834 | Console.Write("Strength of hero hit > "); 835 | action = Console.ReadLine(); 836 | 837 | if (int.TryParse(action, out int strength)) 838 | hero.Hit(hitpoints: strength); 839 | } 840 | while (!String.IsNullOrEmpty(action)); 841 | } 842 | } 843 | } 844 | ``` 845 | 846 | ## Decorator pattern 847 | 848 | ```c# 849 | using System; 850 | 851 | namespace csharp_through_code_examples 852 | { 853 | class Program 854 | { 855 | private static Random random = new Random(); 856 | 857 | private static List phrases = new List 858 | { 859 | "The journey of a thousand miles begins with one step", 860 | "That which does not kill us makes us stronger", 861 | "I want to believe", 862 | "The secret of getting ahead is getting started", 863 | }; 864 | 865 | static void Main() 866 | { 867 | Console.WriteLine("Try to restore word order!\n"); 868 | 869 | var fullPhrase = phrases[random.Next(phrases.Count)]; 870 | 871 | var puzzle = fullPhrase 872 | .Split(' ') 873 | .Select(x => x.Trim()) 874 | .OrderBy(a => random.Next()) 875 | .ToList(); 876 | 877 | Console.WriteLine("Puzzles:"); 878 | 879 | for (int i = 0; i < puzzle.Count(); i++) 880 | Console.WriteLine("{0}: {1}", i + 1, puzzle[i]); 881 | 882 | var responseLine = String.Empty; 883 | 884 | do 885 | { 886 | Console.Write("\nEnter your order (1 2 3 4...): "); 887 | 888 | responseLine = Console.ReadLine(); 889 | 890 | if (String.IsNullOrEmpty(responseLine)) 891 | break; 892 | 893 | var responseStrings = responseLine.Split(' ').ToList(); 894 | 895 | if (responseStrings.Count() < puzzle.Count) 896 | { 897 | Console.WriteLine("Fail! Not enough answers! Try again!"); 898 | continue; 899 | } 900 | 901 | var response = responseStrings.Select(x => int.Parse(x)).ToList(); 902 | 903 | var newPhrase = new Component(); 904 | Decorator newDecorator = null; 905 | Decorator prevDecorator = null; 906 | 907 | foreach (int word in response) 908 | { 909 | newDecorator = new Decorator(puzzle[word - 1]); 910 | newDecorator.SetComponent(prevDecorator ?? (ComponentAbstraction)newPhrase); 911 | prevDecorator = newDecorator; 912 | } 913 | 914 | var responsePhrase = newDecorator.Operation().Trim(); 915 | 916 | Console.WriteLine("Result: {0}", responsePhrase); 917 | 918 | if (fullPhrase == responsePhrase) 919 | { 920 | Console.WriteLine("WIN!"); 921 | responseLine = String.Empty; 922 | } 923 | else 924 | { 925 | Console.WriteLine("Fail! Try again!"); 926 | } 927 | } 928 | while (!String.IsNullOrEmpty(responseLine)); 929 | } 930 | } 931 | 932 | abstract class ComponentAbstraction 933 | { 934 | public abstract string Operation(); 935 | } 936 | 937 | class Component : ComponentAbstraction 938 | { 939 | public override string Operation() => 940 | String.Empty; 941 | } 942 | 943 | abstract class DecoratorAbstraction : ComponentAbstraction 944 | { 945 | protected ComponentAbstraction component; 946 | 947 | public void SetComponent(ComponentAbstraction component) => 948 | this.component = component; 949 | 950 | public override string Operation() => 951 | component.Operation(); 952 | } 953 | 954 | class Decorator : DecoratorAbstraction 955 | { 956 | private string Word; 957 | 958 | public Decorator(string word) => 959 | Word = word; 960 | 961 | public override string Operation() => 962 | String.Format("{0} {1}", base.Operation(), Word); 963 | } 964 | } 965 | ``` 966 | 967 | ## Factory method pattern 968 | 969 | ```c# 970 | using System; 971 | 972 | namespace csharp_through_code_examples 973 | { 974 | class Program 975 | { 976 | public abstract class Hero 977 | { 978 | protected string Name; 979 | public abstract string Description(); 980 | } 981 | 982 | public abstract class HeroCreator 983 | { 984 | public abstract Hero HeroFactoryMethod(); 985 | } 986 | 987 | public class Human : Hero 988 | { 989 | public Human(string name) => 990 | Name = name; 991 | 992 | public override string Description() => 993 | String.Format("human {0}", Name); 994 | } 995 | 996 | public class HumanCreator : HeroCreator 997 | { 998 | private List names = new List { "Aragorn", "Boromir", "Faramir" }; 999 | private static int nameIndex = -1; 1000 | 1001 | public override Hero HeroFactoryMethod() 1002 | { 1003 | nameIndex += 1; 1004 | 1005 | if (nameIndex >= names.Count) 1006 | return null; 1007 | else 1008 | return new Human(names[nameIndex]); 1009 | } 1010 | } 1011 | 1012 | public class Elf : Hero 1013 | { 1014 | public Elf(string name) => 1015 | Name = name; 1016 | 1017 | public override string Description() => 1018 | String.Format("elf {0}", Name); 1019 | } 1020 | 1021 | public class ElfCreator : HeroCreator 1022 | { 1023 | private List names = new List { "Legolas", "Galadriel", "Haldir" }; 1024 | private static int nameIndex = -1; 1025 | 1026 | public override Hero HeroFactoryMethod() 1027 | { 1028 | nameIndex += 1; 1029 | 1030 | if (nameIndex >= names.Count) 1031 | return null; 1032 | else 1033 | return new Elf(names[nameIndex]); 1034 | } 1035 | } 1036 | 1037 | public class Orc : Hero 1038 | { 1039 | public Orc(string name) => 1040 | Name = name; 1041 | 1042 | public override string Description() => 1043 | String.Format("orc {0}", Name); 1044 | } 1045 | 1046 | public class OrcCreator : HeroCreator 1047 | { 1048 | private List names = new List { "Azog", "Ugluk", "Grishnakh" }; 1049 | private static int nameIndex = -1; 1050 | 1051 | public override Hero HeroFactoryMethod() 1052 | { 1053 | nameIndex += 1; 1054 | 1055 | if (nameIndex >= names.Count) 1056 | return null; 1057 | else 1058 | return new Orc(names[nameIndex]); 1059 | } 1060 | } 1061 | 1062 | public static HeroCreator Creator(string type) 1063 | { 1064 | switch (type.ToLower()) 1065 | { 1066 | case "human": 1067 | return new HumanCreator(); 1068 | 1069 | case "elf": 1070 | return new ElfCreator(); 1071 | 1072 | case "orc": 1073 | return new OrcCreator(); 1074 | 1075 | default: 1076 | return null; 1077 | } 1078 | } 1079 | 1080 | static void Main() 1081 | { 1082 | do 1083 | { 1084 | Console.WriteLine("The birth of heroes and villains!\n" + 1085 | "Choose type: human, elf, orc...\n"); 1086 | 1087 | Console.Write("Hero type > "); 1088 | var heroType = Console.ReadLine(); 1089 | 1090 | if (String.IsNullOrEmpty(heroType)) 1091 | break; 1092 | 1093 | var heroFactory = Creator(heroType); 1094 | 1095 | if (heroFactory == null) 1096 | { 1097 | Console.WriteLine("Invalid hero type! Try again!"); 1098 | continue; 1099 | } 1100 | else 1101 | { 1102 | Hero hero = heroFactory.HeroFactoryMethod(); 1103 | 1104 | if (hero == null) 1105 | Console.WriteLine("No more hero of this type..."); 1106 | else 1107 | Console.WriteLine("New hero created: {0}", hero.Description()); 1108 | } 1109 | } 1110 | while (true); 1111 | } 1112 | } 1113 | } 1114 | ``` 1115 | 1116 | ## Abstract factory pattern 1117 | 1118 | ```c# 1119 | using System; 1120 | 1121 | namespace csharp_through_code_examples 1122 | { 1123 | class Program 1124 | { 1125 | public class Hero 1126 | { 1127 | public string Name; 1128 | protected int Hitpoints; 1129 | protected string Information; 1130 | 1131 | public AbstractrDescription Description; 1132 | 1133 | public Hero(HeroFactory factory) 1134 | { 1135 | Name = factory.GetName(); 1136 | Hitpoints = factory.GetHitpoints(); 1137 | Information = factory.GetWeapon(); 1138 | Description = factory.SetDescription(); 1139 | } 1140 | 1141 | public string Discribe() => 1142 | String.Format("{0} ({1} hitpoints), {2}{3}", 1143 | Name, Hitpoints, Information, Description.Get()); 1144 | } 1145 | 1146 | public abstract class HeroFactory 1147 | { 1148 | public abstract string GetName(); 1149 | public abstract int GetHitpoints(); 1150 | public abstract string GetWeapon(); 1151 | public abstract AbstractrDescription SetDescription(); 1152 | } 1153 | 1154 | public abstract class AbstractrDescription 1155 | { 1156 | public abstract string Get(); 1157 | } 1158 | 1159 | public class GoodPersonage : AbstractrDescription 1160 | { 1161 | public override string Get() => 1162 | ", this is good guy!"; 1163 | } 1164 | 1165 | public class BadPersonage : AbstractrDescription 1166 | { 1167 | public override string Get() => 1168 | ", this is bad guy!"; 1169 | } 1170 | 1171 | public class HumanFactory : HeroFactory 1172 | { 1173 | private string weapon; 1174 | private List names = new List { "Aragorn", "Boromir", "Faramir" }; 1175 | private static int nameIndex = -1; 1176 | 1177 | public HumanFactory(string hisWeapon) => 1178 | weapon = hisWeapon; 1179 | 1180 | public override string GetName() 1181 | { 1182 | nameIndex += 1; 1183 | return nameIndex >= names.Count ? String.Empty : names[nameIndex]; 1184 | } 1185 | 1186 | public override int GetHitpoints() => 1187 | 10; 1188 | 1189 | public override string GetWeapon() => 1190 | String.Format("with his beautiful {0}", weapon); 1191 | 1192 | public override AbstractrDescription SetDescription() => 1193 | new GoodPersonage(); 1194 | } 1195 | 1196 | public class OrcFactory : HeroFactory 1197 | { 1198 | private string weapon; 1199 | private List names = new List { "Azog", "Ugluk", "Grishnakh" }; 1200 | private static int nameIndex = -1; 1201 | 1202 | public OrcFactory(string hisWeapon) => weapon = hisWeapon; 1203 | 1204 | public override string GetName() 1205 | { 1206 | nameIndex += 1; 1207 | return nameIndex >= names.Count ? String.Empty : names[nameIndex]; 1208 | } 1209 | 1210 | public override int GetHitpoints() => 1211 | 12; 1212 | 1213 | public override string GetWeapon() => 1214 | String.Format("with his hideous {0}", weapon); 1215 | 1216 | public override AbstractrDescription SetDescription() => 1217 | new BadPersonage(); 1218 | } 1219 | 1220 | public static HeroFactory GetFactory(string type, string weapon) 1221 | { 1222 | switch (type.ToLower()) 1223 | { 1224 | case "human": 1225 | return new HumanFactory(weapon); 1226 | 1227 | case "orc": 1228 | return new OrcFactory(weapon); 1229 | 1230 | default: 1231 | return null; 1232 | } 1233 | } 1234 | 1235 | static void Main() 1236 | { 1237 | Console.WriteLine("Another birth of heroes and villains!\n" + 1238 | "Choose type: human or orc...\n"); 1239 | 1240 | do 1241 | { 1242 | Console.Write("Hero type > "); 1243 | var heroType = Console.ReadLine(); 1244 | 1245 | Console.Write("His weapon > "); 1246 | var heroWeapon = Console.ReadLine(); 1247 | 1248 | if (String.IsNullOrEmpty(heroType) || String.IsNullOrEmpty(heroWeapon)) 1249 | break; 1250 | 1251 | var heroFactory = GetFactory(heroType, heroWeapon); 1252 | 1253 | if (heroFactory == null) 1254 | { 1255 | Console.WriteLine("Invalid hero type! Try again!"); 1256 | continue; 1257 | } 1258 | 1259 | var hero = new Hero(heroFactory); 1260 | 1261 | if (String.IsNullOrEmpty(hero.Name)) 1262 | { 1263 | Console.WriteLine("No more hero of this type..."); 1264 | continue; 1265 | } 1266 | 1267 | Console.WriteLine(hero.Discribe()); 1268 | } 1269 | while (true); 1270 | } 1271 | } 1272 | } 1273 | ``` 1274 | 1275 | ## Singleton pattern 1276 | 1277 | ```c# 1278 | using System; 1279 | 1280 | namespace csharp_through_code_examples 1281 | { 1282 | class Program 1283 | { 1284 | 1285 | public class Counter 1286 | { 1287 | private static Counter instance = new Counter(); 1288 | 1289 | private Counter() { } 1290 | 1291 | public static Counter NewInstance() => 1292 | instance; 1293 | 1294 | private int counter = 99; 1295 | 1296 | public int Get() => 1297 | --instance.counter; 1298 | } 1299 | 1300 | static void Main() 1301 | { 1302 | int bottles = 99; 1303 | 1304 | do 1305 | { 1306 | Console.WriteLine("{0} bottles of beer on " + 1307 | "the wall", bottles); 1308 | Console.WriteLine("{0} bottles of beer!", bottles); 1309 | Console.WriteLine("Take one down, pass it around"); 1310 | 1311 | Counter bottleCounter = Counter.NewInstance(); 1312 | bottles = bottleCounter.Get(); 1313 | 1314 | Console.WriteLine("{0} bottles of beer on the wall!", bottles); 1315 | Console.ReadLine(); 1316 | } 1317 | while (bottles > 1); 1318 | 1319 | Console.WriteLine("1 bottle of beer on the wall\n1 bottle of beer!"); 1320 | Console.WriteLine("Take one down, pass it around\nNo bottles of beer on the wall"); 1321 | } 1322 | } 1323 | } 1324 | ``` 1325 | 1326 | ## Command pattern 1327 | 1328 | ```c# 1329 | using System; 1330 | 1331 | class Program 1332 | { 1333 | interface IAttack 1334 | { 1335 | void Execute(); 1336 | } 1337 | 1338 | class Hero 1339 | { 1340 | string heroName = String.Empty; 1341 | 1342 | public Hero(string name) => 1343 | heroName = name; 1344 | 1345 | public void Attack() => 1346 | Console.WriteLine("\n{0} attack!!", heroName); 1347 | } 1348 | 1349 | class AttackCommand : IAttack 1350 | { 1351 | Hero hero; 1352 | 1353 | public AttackCommand(Hero heroSet) => 1354 | hero = heroSet; 1355 | 1356 | public void Execute() => 1357 | hero.Attack(); 1358 | } 1359 | 1360 | class Fight 1361 | { 1362 | IAttack attack; 1363 | 1364 | public void SetAttack(IAttack setAttack) => 1365 | attack = setAttack; 1366 | 1367 | public void Attack() => 1368 | attack.Execute(); 1369 | } 1370 | 1371 | static void Main() 1372 | { 1373 | Console.WriteLine("Welcome to Duelling Club of Hogwarts!\n" + 1374 | "Press 'H' for Harry Potter attack, press 'D' for Draco Malfoy attack...\n"); 1375 | 1376 | var fight = new Fight(); 1377 | 1378 | var harryPotter = new Hero("Harry Potter"); 1379 | var dracoMalfoy = new Hero("Draco Malfoy"); 1380 | 1381 | do 1382 | { 1383 | var action = Console.ReadKey(); 1384 | 1385 | if (action.Key == ConsoleKey.H) 1386 | { 1387 | fight.SetAttack(new AttackCommand(harryPotter)); 1388 | } 1389 | else if (action.Key == ConsoleKey.D) 1390 | { 1391 | fight.SetAttack(new AttackCommand(dracoMalfoy)); 1392 | 1393 | } 1394 | else if (action.Key == ConsoleKey.Enter) 1395 | { 1396 | break; 1397 | } 1398 | else 1399 | { 1400 | Console.WriteLine("\nI don't know who this is: '{0}'!", action.Key.ToString()); 1401 | continue; 1402 | } 1403 | 1404 | fight.Attack(); 1405 | } 1406 | while (true); 1407 | } 1408 | } 1409 | ``` 1410 | 1411 | ## Adapter pattern 1412 | 1413 | ```c# 1414 | using System; 1415 | 1416 | class Program 1417 | { 1418 | interface IGermanOfficer 1419 | { 1420 | public string Greeting(); 1421 | public string Name(); 1422 | public string GermanMilitaryRank(); 1423 | } 1424 | 1425 | class GermanOfficer : IGermanOfficer 1426 | { 1427 | private string name; 1428 | private string rank; 1429 | 1430 | public GermanOfficer(string setName, string setRank) 1431 | { 1432 | name = setName; 1433 | rank = setRank; 1434 | } 1435 | 1436 | public string Greeting() => 1437 | String.Format("Jawohl! Mein Name ist"); 1438 | 1439 | public string Name() => 1440 | name; 1441 | 1442 | public string GermanMilitaryRank() => 1443 | rank; 1444 | } 1445 | 1446 | class SovietOfficer 1447 | { 1448 | private string name; 1449 | private string rank; 1450 | private string fakeName; 1451 | 1452 | public SovietOfficer(string setName, string setRank, string setFakeName) 1453 | { 1454 | name = setName; 1455 | rank = setRank; 1456 | fakeName = setFakeName; 1457 | } 1458 | 1459 | public string Greeting() => 1460 | String.Format("Здравия желаю! Меня зовут"); 1461 | 1462 | public string Name() => 1463 | name; 1464 | 1465 | public string FakeName() => 1466 | fakeName; 1467 | 1468 | public string SovietMilitaryRank() => 1469 | rank; 1470 | } 1471 | 1472 | class SpyDisguise : IGermanOfficer 1473 | { 1474 | SovietOfficer officer; 1475 | 1476 | public SpyDisguise(SovietOfficer setOfficer) => 1477 | officer = setOfficer; 1478 | 1479 | public string Greeting() => 1480 | String.Format("Jawohl! Mein Name ist"); 1481 | 1482 | public string Name() 1483 | { 1484 | string newName = officer.FakeName(); 1485 | 1486 | string[] russianAlphabet = 1487 | ("А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я " + 1488 | "а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ы э ю я").Split(" "); 1489 | 1490 | string[] englishAlphabet = 1491 | ("A B V G D E Yo Zh Z I Y K L M N O P R S T U F Kh Ts Ch Sh Shch Y E Yu Ya " + 1492 | "a b v g d e yo zh z i y k l m n o p r s t u f kh ts ch sh shch y e yu ya").Split(" "); 1493 | 1494 | for (int i = 0; i <= 60; i++) 1495 | newName = newName.Replace(russianAlphabet[i], englishAlphabet[i]); 1496 | 1497 | return newName; 1498 | } 1499 | public string GermanMilitaryRank() => 1500 | "Standartenführer"; 1501 | } 1502 | 1503 | static void Main() 1504 | { 1505 | Console.WriteLine("Search for a Soviet spy!\n" + 1506 | "based on 'Seventeen Moments of Spring' (1973)\n"); 1507 | 1508 | var rand = new Random(); 1509 | 1510 | var sovietOfficer = new SovietOfficer("Максим Максимович Исаев", "полковник", "Штирлиц"); 1511 | 1512 | Console.WriteLine("Soviet spy: {0} {1} {2} (моя легенда: {3})", 1513 | sovietOfficer.Greeting(), 1514 | sovietOfficer.SovietMilitaryRank(), 1515 | sovietOfficer.Name(), 1516 | sovietOfficer.FakeName()); 1517 | 1518 | var germanOfficers = new List(); 1519 | 1520 | germanOfficers.Add(new GermanOfficer("Müller", "Gruppenführer")); 1521 | germanOfficers.Add(new GermanOfficer("Schellenberg", "Brigadeführer")); 1522 | germanOfficers.Add(new GermanOfficer("Bormann", "Reichsminister")); 1523 | germanOfficers.Add(new GermanOfficer("Wolff", "Obergruppenführer")); 1524 | germanOfficers.Add(new SpyDisguise(sovietOfficer)); 1525 | 1526 | germanOfficers = germanOfficers 1527 | .OrderBy(x => rand.Next()) 1528 | .ToList(); 1529 | 1530 | Console.WriteLine("\nGerman officers:"); 1531 | 1532 | var i = 0; 1533 | 1534 | foreach (IGermanOfficer germanOfficer in germanOfficers) 1535 | { 1536 | Console.WriteLine("{0}. {1} {2} {3}", 1537 | ++i, 1538 | germanOfficer.Greeting(), 1539 | germanOfficer.GermanMilitaryRank(), 1540 | germanOfficer.Name()); 1541 | } 1542 | 1543 | Console.WriteLine("\nWho is soviet spy?"); 1544 | 1545 | do 1546 | { 1547 | string responseLine = Console.ReadLine(); 1548 | 1549 | if (String.IsNullOrEmpty(responseLine)) 1550 | break; 1551 | 1552 | var okResponse = int.TryParse(responseLine, out int response); 1553 | 1554 | if (!okResponse || (response > germanOfficers.Count) || (response < 1)) 1555 | { 1556 | Console.WriteLine("Invalid response! Try again!"); 1557 | } 1558 | else if (germanOfficers[response - 1] is GermanOfficer) 1559 | { 1560 | Console.WriteLine("No. Try again!"); 1561 | } 1562 | else 1563 | { 1564 | Console.WriteLine("YES! You WIN!"); 1565 | break; 1566 | } 1567 | } 1568 | while (true); 1569 | } 1570 | } 1571 | ``` 1572 | 1573 | ## Facade pattern 1574 | 1575 | ```c# 1576 | using System; 1577 | 1578 | class Program 1579 | { 1580 | class Hero 1581 | { 1582 | public int Punch() 1583 | { 1584 | Console.WriteLine("Punch!"); 1585 | return 5; 1586 | } 1587 | 1588 | public int Kick() 1589 | { 1590 | Console.WriteLine("Kick!"); 1591 | return 6; 1592 | } 1593 | 1594 | public int Headbutt() 1595 | { 1596 | Console.WriteLine("Headbutt!"); 1597 | return 3; 1598 | } 1599 | 1600 | public int ElbowStrike() 1601 | { 1602 | Console.WriteLine("Elbow strike!"); 1603 | return 4; 1604 | } 1605 | 1606 | public int KneeStrike() 1607 | { 1608 | Console.WriteLine("Knee strike!"); 1609 | return 5; 1610 | } 1611 | } 1612 | 1613 | class Combo 1614 | { 1615 | Hero hero; 1616 | 1617 | public Combo(Hero setHero) => 1618 | hero = setHero; 1619 | 1620 | public int Make() 1621 | { 1622 | Console.WriteLine("Combo..."); 1623 | 1624 | var damage = 0; 1625 | 1626 | Console.Write("..."); 1627 | damage += hero.Kick(); 1628 | 1629 | Console.Write("..."); 1630 | damage += hero.Punch(); 1631 | 1632 | Console.Write("..."); 1633 | damage += hero.ElbowStrike(); 1634 | 1635 | Console.Write("..."); 1636 | damage += hero.KneeStrike(); 1637 | 1638 | return damage; 1639 | } 1640 | } 1641 | 1642 | class EvilOrc 1643 | { 1644 | private int _hitponts; 1645 | public int Hitpoints 1646 | { 1647 | get => _hitponts; 1648 | 1649 | set 1650 | { 1651 | _hitponts = value; 1652 | Console.WriteLine("\tEvil Orc said: AUCH!! {0} hitpoints left.", _hitponts); 1653 | } 1654 | } 1655 | 1656 | public EvilOrc(int setHitpoints) => 1657 | _hitponts = setHitpoints; 1658 | } 1659 | 1660 | static void Main() 1661 | { 1662 | Console.WriteLine("Fight against Evil Orc!"); 1663 | Console.WriteLine("'P' - punch, 'K' - kick, 'H' - headbutt"); 1664 | Console.WriteLine("'E' - elbow strike, 'N' - knee strike, 'C' - combo"); 1665 | 1666 | var orc = new EvilOrc(50); 1667 | var hero = new Hero(); 1668 | var combo = new Combo(hero); 1669 | 1670 | do 1671 | { 1672 | var action = Console.ReadKey(); 1673 | Console.WriteLine(); 1674 | 1675 | if (action.Key == ConsoleKey.P) 1676 | { 1677 | orc.Hitpoints -= hero.Punch(); 1678 | } 1679 | else if (action.Key == ConsoleKey.K) 1680 | { 1681 | orc.Hitpoints -= hero.Kick(); 1682 | } 1683 | else if (action.Key == ConsoleKey.H) 1684 | { 1685 | orc.Hitpoints -= hero.Headbutt(); 1686 | } 1687 | else if (action.Key == ConsoleKey.E) 1688 | { 1689 | orc.Hitpoints -= hero.ElbowStrike(); 1690 | } 1691 | else if (action.Key == ConsoleKey.N) 1692 | { 1693 | orc.Hitpoints -= hero.KneeStrike(); 1694 | } 1695 | else if (action.Key == ConsoleKey.C) 1696 | { 1697 | orc.Hitpoints -= combo.Make(); 1698 | } 1699 | else 1700 | { 1701 | Console.WriteLine("I did not understand you...\n"); 1702 | } 1703 | 1704 | } 1705 | while (orc.Hitpoints > 0); 1706 | 1707 | Console.WriteLine("\nYOU WON THIS BATTLE!\nNot surprisingly, but still..."); 1708 | Console.ReadLine(); 1709 | } 1710 | } 1711 | ``` 1712 | 1713 | ## Template method pattern 1714 | 1715 | ```c# 1716 | using System; 1717 | 1718 | class Program 1719 | { 1720 | abstract class Spell 1721 | { 1722 | public abstract string SpellName(); 1723 | 1724 | public string Speak() => 1725 | String.Format("You say: {0}...", SpellName()); 1726 | 1727 | public string WandGesture() => 1728 | "You wave your wand..."; 1729 | 1730 | public abstract string MagicEffect(); 1731 | } 1732 | 1733 | class Accio : Spell 1734 | { 1735 | public override string SpellName() => 1736 | "Accio"; 1737 | public override string MagicEffect() => 1738 | "Objects are flying towards us!"; 1739 | } 1740 | 1741 | class Reducto : Spell 1742 | { 1743 | public override string SpellName() => 1744 | "Reducto"; 1745 | public override string MagicEffect() => 1746 | "Objects are broken and destroyed!"; 1747 | } 1748 | 1749 | class Lumos : Spell 1750 | { 1751 | public override string SpellName() => 1752 | "Lumos"; 1753 | public override string MagicEffect() => 1754 | "The bright light is on!"; 1755 | } 1756 | 1757 | class Riddikulus : Spell 1758 | { 1759 | public override string SpellName() => 1760 | "Riddikulus"; 1761 | public override string MagicEffect() => 1762 | "Boggart was ridiculed!"; 1763 | } 1764 | 1765 | static void Main() 1766 | { 1767 | Console.WriteLine("Hi!\nMy name is Professor Lupin!\n" + 1768 | "Now we will learn a few spells!"); 1769 | 1770 | var spells = new List 1771 | { 1772 | new Accio(), 1773 | new Reducto(), 1774 | new Lumos(), 1775 | new Riddikulus(), 1776 | }; 1777 | 1778 | foreach (Spell spell in spells) 1779 | { 1780 | Console.ReadLine(); 1781 | 1782 | Console.WriteLine(spell.Speak()); 1783 | Console.WriteLine(spell.WandGesture()); 1784 | Console.WriteLine(spell.MagicEffect()); 1785 | } 1786 | 1787 | Console.WriteLine("\nIt's all for today!\nLesson is over!"); 1788 | } 1789 | } 1790 | ``` 1791 | 1792 | ## Iterator pattern 1793 | 1794 | ```c# 1795 | using System; 1796 | 1797 | class Program 1798 | { 1799 | class Hero 1800 | { 1801 | public string Name; 1802 | public int Age; 1803 | public string Weapon; 1804 | } 1805 | 1806 | class Orc : Hero 1807 | { 1808 | public int VillainyLevel; 1809 | 1810 | public static IEnumerable CreateIterator(List orcs) 1811 | { 1812 | foreach (Orc orc in orcs) 1813 | yield return orc; 1814 | } 1815 | } 1816 | 1817 | class Elf : Hero 1818 | { 1819 | public int NobilityLevel; 1820 | 1821 | public static IEnumerable CreateIterator(Dictionary elfs) 1822 | { 1823 | foreach (Elf elf in elfs.Values) 1824 | yield return elf; 1825 | } 1826 | } 1827 | 1828 | static void PrintAll(IEnumerable heroes) 1829 | { 1830 | int i = 0; 1831 | 1832 | foreach (Hero hero in heroes) 1833 | Console.WriteLine("\t{0}. {1} with {2}.", ++i, hero.Name, hero.Weapon); 1834 | } 1835 | 1836 | static void Main() 1837 | { 1838 | var orcs = new List(); 1839 | 1840 | orcs.Add(new Orc { Name = "Azog", Age = 5, Weapon = "sword", VillainyLevel = 10 }); 1841 | orcs.Add(new Orc { Name = "Ugluk", Age = 2, Weapon = "axe", VillainyLevel = 5 }); 1842 | orcs.Add(new Orc { Name = "Grishnakh", Age = 3, Weapon = "knife", VillainyLevel = 6 }); 1843 | 1844 | var elfs = new Dictionary(); 1845 | 1846 | elfs.Add("Legolas", new Elf { Name = "Legolas", Age = 1000, Weapon = "bow", NobilityLevel = 9 }); 1847 | elfs.Add("Galadriel", new Elf { Name = "Galadriel", Age = 5000, Weapon = "magic", NobilityLevel = 10 }); 1848 | elfs.Add("Haldir", new Elf { Name = "Haldir", Age = 1000, Weapon = "sword", NobilityLevel = 9 }); 1849 | 1850 | Console.WriteLine("ORCS:"); 1851 | PrintAll(Orc.CreateIterator(orcs)); 1852 | 1853 | Console.WriteLine("ELFS:"); 1854 | PrintAll(Elf.CreateIterator(elfs)); 1855 | 1856 | Console.ReadLine(); 1857 | } 1858 | } 1859 | ``` 1860 | 1861 | ## Composite pattern 1862 | 1863 | ```c# 1864 | using System; 1865 | 1866 | class Program 1867 | { 1868 | abstract class Line 1869 | { 1870 | protected string Name; 1871 | 1872 | public Directory Parent { get; set; } 1873 | 1874 | public Line(string name) => 1875 | Name = name; 1876 | 1877 | public abstract void Display(int nesting); 1878 | } 1879 | 1880 | class Directory : Line 1881 | { 1882 | private List children = new List(); 1883 | 1884 | public Directory(string name) : base(name) { } 1885 | 1886 | public void Add(Line component) 1887 | { 1888 | component.Parent = this; 1889 | children.Add(component); 1890 | } 1891 | 1892 | public override void Display(int nesting) 1893 | { 1894 | Console.WriteLine(new String(' ', nesting) + Name); 1895 | 1896 | foreach (Line component in children) 1897 | component.Display(nesting + 2); 1898 | } 1899 | } 1900 | 1901 | class File : Line 1902 | { 1903 | public File(string name) : base(name) { } 1904 | 1905 | public override void Display(int nesting) => 1906 | Console.WriteLine(new String(' ', nesting) + Name); 1907 | } 1908 | 1909 | static void Main() 1910 | { 1911 | var files = 0; 1912 | var filesInCurrent = 0; 1913 | var nesting = 0; 1914 | 1915 | var rand = new Random(); 1916 | var root = new Directory("root"); 1917 | var current = root; 1918 | var nestingLevel = new Dictionary(); 1919 | 1920 | Console.Write("Nesting level game!\n\nDifficulty level (number of files or folders)? "); 1921 | var difficultyOk = int.TryParse(Console.ReadLine(), out int difficulty); 1922 | 1923 | if (!difficultyOk) 1924 | difficulty = 10; 1925 | 1926 | for (int i = 0; i < difficulty; i++) 1927 | { 1928 | var action = rand.Next(3); 1929 | 1930 | if (action == 0) 1931 | { 1932 | nesting += 1; 1933 | filesInCurrent = 0; 1934 | 1935 | Directory newComposite = new Directory("Directory"); 1936 | current.Add(newComposite); 1937 | current = newComposite; 1938 | } 1939 | else if (action == 1) 1940 | { 1941 | files += 1; 1942 | filesInCurrent += 1; 1943 | 1944 | current.Add(new File(String.Format("File {0}", files))); 1945 | nestingLevel.Add(files, nesting); 1946 | } 1947 | else if (current != root) 1948 | { 1949 | if (filesInCurrent == 0) 1950 | current.Add(new File("(empty)")); 1951 | 1952 | nesting -= 1; 1953 | current = current.Parent; 1954 | } 1955 | } 1956 | 1957 | root.Display(1); 1958 | 1959 | for (int r = 0; r < 3; r++) 1960 | { 1961 | var file = rand.Next(files) + 1; 1962 | 1963 | do 1964 | { 1965 | Console.Write("\nWhat is the nesting level of file {0}? ", file); 1966 | 1967 | var responseLine = Console.ReadLine(); 1968 | 1969 | if (String.IsNullOrEmpty(responseLine)) 1970 | Environment.Exit(0); 1971 | 1972 | var responseOk = int.TryParse(responseLine, out int response); 1973 | 1974 | if (!responseOk) 1975 | { 1976 | Console.WriteLine("Invalid response!"); 1977 | } 1978 | else if (response != nestingLevel[file]) 1979 | { 1980 | Console.WriteLine("Wrong response!"); 1981 | } 1982 | else 1983 | { 1984 | Console.WriteLine("WIN!"); 1985 | break; 1986 | } 1987 | 1988 | } 1989 | while (true); 1990 | } 1991 | } 1992 | } 1993 | ``` 1994 | 1995 | ## State pattern 1996 | 1997 | ```c# 1998 | using System; 1999 | 2000 | class Program 2001 | { 2002 | abstract class Healthbar 2003 | { 2004 | public abstract void Wound(EvilOrc orc); 2005 | } 2006 | 2007 | class Healthy : Healthbar 2008 | { 2009 | public override void Wound(EvilOrc orc) 2010 | { 2011 | Console.WriteLine("Auch! Evil orc is injured now!"); 2012 | orc.Health = new Injured(); 2013 | } 2014 | } 2015 | 2016 | class Injured : Healthbar 2017 | { 2018 | public override void Wound(EvilOrc orc) 2019 | { 2020 | Console.WriteLine("Auch! Evil orc is seriously wounded now!"); 2021 | orc.Health = new Wounded(); 2022 | } 2023 | } 2024 | 2025 | class Wounded : Healthbar 2026 | { 2027 | public override void Wound(EvilOrc orc) 2028 | { 2029 | Console.WriteLine("Auch! Evil orc is killed!"); 2030 | orc.Health = new Killed(); 2031 | } 2032 | } 2033 | 2034 | class Killed : Healthbar 2035 | { 2036 | public override void Wound(EvilOrc orc) 2037 | { 2038 | Console.WriteLine("No abuse of the corpse, please!"); 2039 | } 2040 | } 2041 | 2042 | class EvilOrc 2043 | { 2044 | public Healthbar Health { get; set; } 2045 | 2046 | public EvilOrc(Healthbar startState) => 2047 | Health = startState; 2048 | 2049 | public void Punch() => 2050 | Health.Wound(this); 2051 | } 2052 | 2053 | static void Main() 2054 | { 2055 | Console.WriteLine("Fight against Evil Orc!"); 2056 | Console.WriteLine("Ented 'punch' for attack...\n"); 2057 | 2058 | var orc = new EvilOrc(new Healthy()); 2059 | 2060 | do 2061 | { 2062 | Console.Write("> "); 2063 | var action = Console.ReadLine(); 2064 | 2065 | if (String.IsNullOrEmpty(action)) 2066 | { 2067 | break; 2068 | } 2069 | else if (action == "punch") 2070 | { 2071 | orc.Punch(); 2072 | 2073 | if (orc.Health is Killed) 2074 | Console.WriteLine("YOU WIN!\nNot surprisingly, but still..."); 2075 | } 2076 | else 2077 | { 2078 | Console.WriteLine("I did not understand you..."); 2079 | } 2080 | 2081 | } 2082 | while (true); 2083 | } 2084 | } 2085 | ``` 2086 | 2087 | ## Proxy pattern 2088 | 2089 | ```c# 2090 | using System; 2091 | 2092 | class Program 2093 | { 2094 | static List Pazzles = new List(); 2095 | 2096 | abstract class Pazzle 2097 | { 2098 | protected bool IsOpened { get; set; } 2099 | abstract public void Open(); 2100 | abstract public bool IsOpen(); 2101 | abstract public int GetNear(); 2102 | } 2103 | 2104 | class EmptyPazzle : Pazzle 2105 | { 2106 | private int Near { get; set; } 2107 | 2108 | public EmptyPazzle(int near) 2109 | { 2110 | IsOpened = false; 2111 | Near = near; 2112 | } 2113 | 2114 | public override void Open() => 2115 | IsOpened = true; 2116 | 2117 | public override bool IsOpen() => 2118 | IsOpened; 2119 | 2120 | public override int GetNear() => 2121 | Near; 2122 | } 2123 | 2124 | class Bomb : Pazzle 2125 | { 2126 | EmptyPazzle emptyPazzle; 2127 | 2128 | public Bomb(int near) => 2129 | emptyPazzle = new EmptyPazzle(near); 2130 | 2131 | public override void Open() 2132 | { 2133 | Console.WriteLine("\n BOOOOOOOM!!!!!!"); 2134 | emptyPazzle.Open(); 2135 | } 2136 | 2137 | public override bool IsOpen() => 2138 | emptyPazzle.IsOpen(); 2139 | 2140 | public override int GetNear() => 2141 | emptyPazzle.GetNear(); 2142 | } 2143 | 2144 | private static void Show() 2145 | { 2146 | Console.WriteLine(" 1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8"); 2147 | 2148 | foreach (Pazzle Pazzle in Pazzles) 2149 | { 2150 | var near = Pazzle.GetNear(); 2151 | string symbol; 2152 | 2153 | if (!Pazzle.IsOpen()) 2154 | { 2155 | symbol = " X "; 2156 | } 2157 | else if (near == 2) 2158 | { 2159 | symbol = "BOMB "; 2160 | } 2161 | else 2162 | { 2163 | symbol = String.Format(" {0} ", near); 2164 | } 2165 | 2166 | Console.Write(symbol); 2167 | } 2168 | Console.WriteLine(); 2169 | } 2170 | 2171 | static void Main() 2172 | { 2173 | var rand = new Random(); 2174 | var bombPosition = rand.Next(8); 2175 | 2176 | Console.WriteLine("Mini Minesweeper\n"); 2177 | 2178 | for (int i = 0; i < 8; i++) 2179 | { 2180 | if (i == bombPosition) 2181 | { 2182 | Pazzles.Add(new Bomb(2)); 2183 | } 2184 | else 2185 | { 2186 | var near = (i == bombPosition + 1) || (i == bombPosition - 1) ? 1 : 0; 2187 | Pazzles.Add(new EmptyPazzle(near)); 2188 | } 2189 | } 2190 | 2191 | int newPazzle; 2192 | var openedPazzles = 0; 2193 | 2194 | do 2195 | { 2196 | Show(); 2197 | 2198 | Console.Write("\n > "); 2199 | var action = Console.ReadLine(); 2200 | 2201 | if (String.IsNullOrEmpty(action)) 2202 | { 2203 | break; 2204 | } 2205 | else if (!int.TryParse(action, out newPazzle) || (newPazzle > 8)) 2206 | { 2207 | Console.WriteLine(" I did not understand you..."); 2208 | } 2209 | else 2210 | { 2211 | Pazzles[newPazzle - 1].Open(); 2212 | openedPazzles += 1; 2213 | 2214 | var fail = newPazzle == (bombPosition + 1); 2215 | 2216 | if (fail || (openedPazzles == 7)) 2217 | { 2218 | Console.WriteLine(fail ? "\n Fail..." : "\n WIN!!"); 2219 | Show(); 2220 | break; 2221 | } 2222 | } 2223 | } 2224 | while (true); 2225 | } 2226 | } 2227 | ``` 2228 | --------------------------------------------------------------------------------