如何在原型中创建过滤器?

时间:2018-05-30 16:42:23

标签: javascript

在“团队”类中有一个“踢”方法,其实质是分别随机选择一个目标,以造成伤害。如何使每个角色(弓箭手,法师,剑客)首先寻找其类的目的,(即射手“踢”弓箭手,剑客“踢”剑客等),如果它的“isAlive”=“假”英雄试图打一个随机目标?在原型重合的条件下,我得到“TypeError:sameTypeUnit .__ proto__不是函数”错误。

//constructor for creating a unit
function Unit(maxHealth, basicDamage,type) {
    this.maxHealth = maxHealth;
    this.currentHealth = maxHealth;
    this.basicDamage = basicDamage;
    this.type = type;
}
/*method for showing the status of life, true if the "health" is greater
 than 0 and false if equal to or lower */
Unit.prototype.isAlive = function () {
    return this.currentHealth > 0;
};
/* a method that
 shows the level of health*/
Unit.prototype.getFormattedHealth = function () {
    return this.currentHealth + "/" + this.maxHealth + " HP";
};
/*a method that returns the base damage of the hero and damage to the
 weapon (if it is set)*/
Unit.prototype.getDamage = function () {
    return this.basicDamage;
};
/* The method of hitting
 the hero for the chosen purpose*/
Unit.prototype.kick = function (target) {
    if (this.isAlive()) {
        target.currentHealth = Math.max(0,
            target.currentHealth - this.getDamage());
        console.log(this.type + " hit " + this.type);
    }
    return this;
};
/*method for showing all the characteristics of the hero and changes
 with them*/
Unit.prototype.toString = function () {
    return "Type - " + this.type + ", is alive - " +
        this.isAlive() + ", " + this.getFormattedHealth() +
        ', hero current damage - ' + this.getDamage() + ' points';
};
/*the constructors of the main types of units  which we will use*/
function Archer(maxHealth, basicDamage) {
    Unit.apply(this, arguments);
    this.type = "archer";
}
function Swordsman(maxHealth, basicDamage) {
    Unit.apply(this, arguments);
    this.type = "swordsman";
}
function Mage(maxHealth, basicDamage) {
    Unit.apply(this, arguments);
    this.type = "mage";
}
Archer.prototype = Object.create(Unit.prototype);
Swordsman.prototype = Object.create(Unit.prototype);
Mage.prototype = Object.create(Unit.prototype);
/*We create units of which we will then write to the teams.
 Three units per team*/
var archer = new Archer(60, 5);
var swordsman = new Swordsman(100, 10);
var mage = new Mage(40, 15);

var troll = new Archer(70, 5);
var orc = new Swordsman(150, 10);
var druid = new Mage(50, 15);

/*class for creating teams*/
function Team(name) {
    this.name = name;
    this.members = [];
    this.activeMember = 0;
}
/*method for adding a new unit with an arbitrary number of units*/
Team.prototype.addMember = function (...members) {
    this.members.push(...members);
}
/*method of life of the team, if all participants have
"currentHealth" <0 then this method = "false"*/
Team.prototype.isAlive = function () {
    return this.members.some(n => n.isAlive());
};
/*Damage method similar to that in "Unit" in it the choice
is made - who is attacking whom (the team members take turns
attacking the random participant of the other team)*/
Team.prototype.kick = function(targetTeam) {

    var sameTypeUnit = null;
    for(var i=0;i<this.members.length;i++) {
        sameTypeUnit = this.members[i];
    }
    if (sameTypeUnit.__proto__(sameTypeUnit) && sameTypeUnit.isAlive()) {
        while (sameTypeUnit.isAlive()) {
            sameTypeUnit.kick(sameTypeUnit);
        }
    }else if (!sameTypeUnit.isAlive()) {
        var m = targetTeam.members.filter(n => n.isAlive())
        target = m[Math.random() * m.length | 0];
        if (target && this.isAlive()) {
            var active = null;

            do  {
                active = this.members[this.activeMember];
                this.activeMember = (this.activeMember + 1)
                    % this.members.length;
            } while (!active.isAlive());

            active.kick(target);
        }
    }
};
/*method to output information about the team*/
Team.prototype.toString = function () {
    var res = "Name of team - " + this.name +  '\n'
        + "life of a team : " + this.isAlive() + '\n'
        +"members :\n";
    for (var i=0; i<this.members.length; i++)
        res += this.members[i]+"\n";
    return  res;
};
/*create team 1 and add units to it*/
var team1 =  new Team('Alliance');
team1.addMember(archer,swordsman,mage);
/*create team 2 and add units to it*/
var team2 = new Team('Orcs');
team2.addMember(troll,orc,druid);

/*class that organizes a battle between two teams until
 "currentHealth" of all units in the team will not be zero*/
function Game(team1, team2) {
    this.team1 = team1;
    this.team2 = team2;
}
/*the method in which the battle occurs until the
"isAlive" property of all participants of one of the commands
 is equal to "false"*/
Game.prototype.battle = function() {
    if (!this.team1.isAlive() || !this.team2.isAlive()) {
        if (this.team1.isAlive()) {
            alert("Team 1 is win");
        }
        if (this.team2.isAlive()) {
            alert("Team 2 is win");
        }
        console.log(`THE BATTLE IS END :
        ${this.team1.toString()}
        ${this.team2.toString()}
      ${this.team1.name} - ${this.team1.members.length} - 
${this.team1.members.map(n => n.currentHealth)}
      ${this.team2.name} - ${this.team2.members.length} -
${this.team2.members.map(n => n.currentHealth)}  
    `);
        return;
    }
    team1.kick(team2);
    team2.kick(team1);
    requestAnimationFrame(this.battle.bind(this));
};
var game = new Game(team1, team2);
game.battle();

2 个答案:

答案 0 :(得分:1)

如果我找对你,你只想基于当前的攻击者filter敌人成员:

Team.prototype.kick = function(targetTeam) {
  for(const member of this.members) {
    // Filter the enemies based on their type
    const enemies = targetTeam.members.filter(m => m.type === member.type);
    // If there are no enemies with the same type, take another one:
    if(!enemies.length) enemies.push(...targetTeam.members);
    // TODO: Shuffle
    // Attack enemies as long as there are some...
     while(enemies.length && member.isAlive()) {
       member.kick( enemies[0] );
       if(!enemies[0].isAlive()) enemies.shift();
     }
  }
}

另一种方法是对敌人进行排序,以使相同类型的敌人排在第一位,然后稍微改变它:

  /* Clones and Shuffles the array, but moves enemies with the same type to the front */
 function typeFirstShuffle(array, type) {
   return [...array].sort((a, b) => 
     (a.type === type) - (b.type === type) || // same type first
     Math.random() * 2 - 1 // otherwise shuffle
   );
}

可以用作

Team.prototype.kick = function(targetTeam) {
  for(const member of this.members) {
    const enemies = typeFirstShuffle(targetTeam.members, member.type);
   // ... Same as above
  }
}

答案 1 :(得分:1)

尝试使用ES6的课程和inhgeritance系统。它会让它变得更干净,更容易。但主要问题在于团队踢的逻辑。有太多冗余和不必要的条件。我使用类继承重写了整个事情,但是踢功能的所有逻辑都需要改变

&#13;
&#13;
class Unit {
  constructor(maxHealth, basicDamage, classType)
  {
    this.maxHealth = maxHealth;
    this.currentHealth = maxHealth;
    this.basicDamage = basicDamage;
    this.type = classType;


  }
  isAlive()
  {
    return this.currentHealth > 0;
  }

  getFormattedHealth()
  {
    return this.currentHealth + "/" + this.maxHealth + " HP";
  }

  getDamage()
  {
    return this.basicDamage;
  }

  kick(target)
  {
    if (this.isAlive()) {
      target.currentHealth = Math.max(0,
          target.currentHealth - this.getDamage());
      console.log(this.type + " hit " + target.type);
    }
    return this;
  }

  toString()
  {
    return "Type - " + this.type + ", is alive - " +
      this.isAlive() + ", " + this.getFormattedHealth() +
      ', hero current damage - ' + this.getDamage() + ' points';
  }
}


class Archer extends Unit
{
  constructor(maxHealth, basicDamage)
  {
    super(maxHealth, basicDamage, "archer");
  }
}
class Swordsman extends Unit
{
  constructor(maxHealth, basicDamage)
  {
    super(maxHealth, basicDamage, "swordsman");
  }
}
class Mage extends Unit
{
  constructor(maxHealth, basicDamage)
  {
    super(maxHealth, basicDamage, "mage");
  }
}

/*We create units of which we will then write to the teams.
 Three units per team*/
var archer = new Archer(60, 5);
var swordsman = new Swordsman(100, 10);
var mage = new Mage(40, 15);

var troll = new Archer(70, 5);
var orc = new Swordsman(150, 10);
var druid = new Mage(50, 15);


class Team
{
  constructor(name)
  {
    this.name = name;
    this.members = [];
    this.activeMember = 0;
  }

  addMember(...memebrsToAdd)
  {
    memebrsToAdd.forEach(mem => this.members.push(mem));
  }

  isAlive()
  {
    return this.members.some(n => n.isAlive());
  }

  selectRandomTarget(targetTeam)
  {
    let numberOfMembers = targetTeam.members.length;
    let target = null;
    while(target == null || !target.isAlive())
    {
      let randomIndex = Math.floor(Math.random() * numberOfMembers);
      target = targetTeam.members[randomIndex];
    }
    return target;
  }

  kick(targetTeam) {
    console.log(`\nTeam ${this.name} is attacking`);

    for(var i=0; i < this.members.length; i++) {
      let singleMember = this.members[i];

      if(!this.isAlive()) break;
      if(!singleMember.isAlive()) continue;
      let target = this.selectRandomTarget(targetTeam);
      singleMember.kick(target);
    }

    
  }

  toString() {
    var res = "Name of team - " + this.name +  '\n'
        + "life of a team : " + this.isAlive() + '\n'
        +"members :\n";
    for (var i=0; i<this.members.length; i++)
        res += this.members[i]+"\n";
    return  res;
  }
}

/*create team 1 and add units to it*/
var team1 =  new Team('Alliance');
team1.addMember(archer,swordsman,mage);
/*create team 2 and add units to it*/
var team2 = new Team('Orcs');
team2.addMember(troll,orc,druid);

class Game
{
  constructor(team1, team2)
  {
    this.team1 = team1;
    this.team2 = team2;
  }

  battle()
  {
    let currentTeam = team1
    while(this.team1.isAlive() && this.team2.isAlive())
    {
      let defendingTeam = currentTeam === team1 ? team2 : team1;
      currentTeam.kick(defendingTeam);
      currentTeam = currentTeam === team1 ? team2 : team1;
    }
    this.displayWinningMessage();
  }

  displayWinningMessage()
  {
    console.log(`THE BATTLE IS END :
      ${this.team1.toString()}
      ${this.team2.toString()}
      ${this.team1.name} - ${this.team1.members.length} - 
      ${this.team1.members.map(n => n.currentHealth)}
      ${this.team2.name} - ${this.team2.members.length} -
      ${this.team2.members.map(n => n.currentHealth)}`
    );
  }
}
var game = new Game(team1, team2);
game.battle();
&#13;
&#13;
&#13;