Advertisement
Ami777

Rozwiązanie: Challange walki robotow, JS ES2015 klasowosc lu

Jun 19th, 2018
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Stwórz klasę reprezentującą robota. Powinien on przyjmować w konstruktorze swoje ID,
  2. // imię, atak oraz obronę.
  3. // Jeżeli w konstruktorze podano atak lub obronę mniejszą niż 1 lub większą niż 10
  4. //to wyrzuć błąd (throw new Error("Złe statystyki!")).
  5. // Dodatkowo każdy robot powinien posiadać pole prywatne level, które na początku wynosi 1.
  6. // Wszystkie pola powinny być prywatne. ID powinno być tylko do odczytu. Do każdego pola
  7. //zastosuj tam gdzie pasują settery i gettery (możesz zmienić nazwy pól na takie z podkreślnikami, żeby nie było konfliktów nazw).
  8. // Robot powinien mieć dodatkowo metodę levelUp(), która zwiększa losowo jego obronę lub
  9. // atak o 1. Dodatkowo zwiększa to level o 1.
  10. // Następnie stwórz metodę fight(anotherRobot), która przyjmuje jako argument innego robota.
  11. // Sprawdź kto wygrał walkę, według wzoru: hitpoints = atakAtakujacego - obronaAtakowanego.
  12. // Wygrywa ten robot, który zadał więcej hitpoints. Jeżeli równo, to walka kończy się remisem.
  13. // Jeżeli nie było remisu, wykonaj na wygranym metodę .levelUp().
  14. // Wypisz w konsoli jaki był wynik. Zwróć ID zwycięzcy lub null w przypadku remisu.
  15. // Jeżeli chcesz i Cię to ciekawi to stwórz funkcję genRobot(), która wygeneruje nowego
  16. // robota, z losowymi statystykami w zakresie 1-10, dowolnym ID i losowym imieniem.
  17. //Imię możesz wylosować za pomocą:
  18. function randRoboName(){
  19.     const roboNameParts = ['robo', 'mech', 'zord', 'mega', 'tron', 'zulu', 'johnny5', 'x-512', 'bot', 'auto', 'prime', 'ultra', 'war', 'supreme', 'master', 'alpha', 'beta'];
  20.     const roboNameJoins = [' ', '-', '', '.'];
  21.     const partsCount = ~~(Math.random()*4+1);
  22.     let name = '';
  23.     for(let i = 0; i < partsCount; i++){
  24.         const joiner = i === (partsCount-1) ? '' : roboNameJoins[~~(Math.random()*roboNameJoins.length)];
  25.         name += roboNameParts[~~(Math.random()*roboNameParts.length)] + joiner;
  26.     }
  27.     return name.substr(0, 1).toUpperCase() + name.substr(1);
  28. }
  29. //Teraz stwórz arenę: wygeneruj 10 botów, następnie wykonaj walkę każdego z każdym.
  30. //Spróbuj wymyślić taki sposób, żeby walka była uczciwa, tzn. aby każdy robot zaczynał
  31. //walkę z innym robotem, który też jeszcze nie walczył itp. i wypisz w konsoli obiekt
  32. //zwycięzkiego robota. Wygrywa ten robot, który ma największy level.
  33.  
  34. class Robot{
  35.     private _level: number = 1;
  36.     //Dodatkowe pola dzięki którym będzie można ocenić ile walk przebył robot
  37.     private _numberOfGames: number = 0;
  38.     //oraz z kim już walczył
  39.     public foughtWithIds : number[] = [];
  40.  
  41.     constructor(private readonly _id : number, private _name : string, private _attack : number, private _defense : number){
  42.         if (_defense < 1 || _defense > 10 || _attack < 1 || _attack > 10){
  43.             throw new Error("Złe statystyki!");
  44.         }
  45.     }
  46.  
  47.     get id(){
  48.         return this._id;
  49.     }
  50.  
  51.     get name(){
  52.         return this._name;
  53.     }
  54.  
  55.     get attack(){
  56.         return this._attack;
  57.     }
  58.  
  59.     get defense(){
  60.         return this._defense;
  61.     }
  62.  
  63.     get level(){
  64.         return this._level;
  65.     }
  66.  
  67.     get numberOfGames(){
  68.         return this._numberOfGames;
  69.     }
  70.  
  71.     set numberOfGames(newNumber){
  72.         this._numberOfGames = newNumber;
  73.     }
  74.  
  75.     levelUp() : void{
  76.         this._level++;
  77.         const roll = Math.random() < 0.5;
  78.         if (roll){
  79.             this._attack++;
  80.         } else {
  81.             this._defense++;
  82.         }
  83.     }
  84. }
  85.  
  86. //Mini funkcja assert, dzięki której sprawdzimy czy walki są uczciwe
  87. function assert(toBeTrue, msg) {
  88.     if (!toBeTrue) throw new Error(msg);
  89. }
  90.  
  91. //Walka jest dosyć prosta i podąża za instrukcją - sprawdzamy który robot zadał więcej hitpoints
  92. function fight(firstRobot: Robot, anotherRobot: Robot): number | null{
  93.     assert(Math.abs(firstRobot.numberOfGames - anotherRobot.numberOfGames) <= 1, 'Robots don\'t have the same chances!');
  94.  
  95.     //Bardzo ważne jest zapisywanie w jakiejś formie z kim walczył robot i ile razy (do tego drugiego wystarczy oczywiście tablica.length, ale dla czytelności dodałem osobną zmienną)
  96.     firstRobot.numberOfGames++;
  97.     anotherRobot.numberOfGames++;
  98.     firstRobot.foughtWithIds.push(anotherRobot.id);
  99.     anotherRobot.foughtWithIds.push(firstRobot.id);
  100.  
  101.     const hitpointsMe = firstRobot.attack - anotherRobot.defense;
  102.     const hitpointsAnother = anotherRobot.attack - firstRobot.defense;
  103.     if (hitpointsAnother === hitpointsMe){
  104.         console.log('Remis');
  105.         return null;            
  106.     } else {
  107.         const winner : Robot = hitpointsAnother > hitpointsMe ? anotherRobot : firstRobot;
  108.         winner.levelUp();
  109.         console.log('Wygrał robot', winner.name, 'o ID', winner.id);
  110.         return winner.id;
  111.     }
  112. }
  113.  
  114. //Przechowujemy ID aktualnego robota
  115. let currId : number = 1;
  116.  
  117. //Funkcja losująca robota
  118. function genRobot() : Robot{
  119.     const name = randRoboName();
  120.     const id = currId++;
  121.     const attack = ~~(Math.random()*9+1);
  122.     const defense = ~~(Math.random()*9+1);
  123.     return new Robot(id, name, attack, defense);
  124. }
  125.  
  126. //Tworzymy ich 10
  127. let robots : Robot[] = [];
  128. for(let i = 0; i < 10; i++){
  129.     robots.push(genRobot());
  130. }
  131.  
  132. //Poniżej algorytm walki
  133. //Tak na prawdę system walki musi spełniać następujące założenia:
  134. // * Jeżeli to możliwe to powinny ze sobą walczyć takie roboty, które odbyły tyle samo walk
  135. // * Każdy robot powinien walczyć z każdym innym
  136. // * Dwa roboty nie powinny walczyć ze sobą dwukrotnie
  137. // * Robot nie może walczyć ze sobą
  138. // * Na koniec każdy robot powinien mieć taką samą liczbę odbytych walk
  139.  
  140. //Funkcja pomicnicza potrzebna do waruacji bez powtórzeń
  141. function factor(n : number) : number {
  142.     if ((n == 0) || (n == 1))
  143.        return 1
  144.     else {
  145.        var result = (n * factor(n-1) );
  146.        return result
  147.     }
  148.  }
  149.  
  150. //Liczba walk jakie muszą się odbyć jest równa wariacji bez powtórzeń podzielonej przez dwa (bo interesuje nas walka A-B, ale B-A już nie)
  151.  function numOfFights(numOfRobots : number) : number{
  152.     return factor(numOfRobots)/factor(numOfRobots-2) / 2; //Wariacja bez powtórzeń, podzielona przez dwa, ponieważ 2 roboty nie muszą się bić ze sobą 2 razy po 2 różnych stronach
  153.  }
  154.  
  155. //Najważniejsza część: znajdowanie walki, która spełni powyższe założenia:
  156. function oneEqualGame(robots: Robot[]) {
  157.     //Sortujemy tak, żeby najpierw walczyły roboty które najmniej walczyły
  158.     robots.sort((robotA, robotB) => robotA.numberOfGames - robotB.numberOfGames);
  159.     //Będzie walczył pierwszy. Szukamy innego robota, z którym jeszcze pierwszy robot nie walczył i który ma też jak najmniej walk
  160.     const robotToFightWith : Robot = robots.find(robot => robot.id !== robots[0].id && robot.foughtWithIds.indexOf(robots[0].id) === -1);
  161.  
  162.     //Kiedy już go znajdziemy uruchamiamy walkę
  163.     fight(robots[0], robotToFightWith);
  164.  }
  165.  
  166. //Liczymy ile ma być walk
  167. const totalNumberOfFights = numOfFights(robots.length);
  168.  
  169. console.log('Zostanie rozegranych', totalNumberOfFights, 'meczy');
  170.  
  171. //Tyle też "równych walk" przeprowadzamy
  172.  for(let i = 0; i < totalNumberOfFights; i++){
  173.     oneEqualGame(robots);
  174.  }
  175.  
  176. //Na koniec szukamy zwycięzcy - miał być to robot z najwyższym levelem
  177. robots.sort((robotA, robotB) => robotB.level - robotA.level);
  178. //Jeżeli chcesz - możesz pomyśleć jak wybrać wszystkie z najwyższym levelem - jeżeli będzie kilka ex aequo
  179.  
  180.  console.log('Zwycięzcą został robot', robots[0]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement