采取ActorRefs的数组的演员建设者

时间:2018-01-15 02:10:35

标签: scala parameters constructor akka actor

我需要在Scala中编写一个程序,它有3个actor和一个object-ball。一个演员必须把球传给另一个。 Actor的构造函数必须包含两个参数:

class Player(val num: Int, val players: Array[ActorRef]) extends Actor { … }

这是我的问题:如何调用此构造函数来组成三个actor并同时将它们的数组传递给所有actor?

以下是我的其余代码:

case class Ball(count: Int)

class Player(val num: Int, val players: Array[ActorRef]) extends Actor {
  def receive = {
    case Ball(count) =>
      println("I've got a ball!")
      var nextPlayer = self
      do {
        nextPlayer = players((Math.random() * 3).toInt)
      } while(nextPlayer == self)
      self.tell(Ball(count + 1), nextPlayer)
  }
}

2 个答案:

答案 0 :(得分:0)

我说你的整个逻辑有点破碎。简单的解决方案是让一个父母演员称为例如Game。逻辑上,多个Player's可以参与单个游戏。所以,看起来应该是这样的:

import akka.actor.{ Actor, ActorLogging, ActorRef, Props }

object Game {
  final case class StartGame(playerCount: Int)
  def apply() = Props(new Game)
}

final class Game extends Actor with ActorLogging {
  import Game._
  var players = Set.empty[ActorRef]

  override def receive: Receive = {
    case StartGame(playerCount) =>
      for (i <- 1 to playerCount) {
        players = players + context.actorOf(Player.apply(playerCount), i.toString)
      }

    case (ball: Player.Ball, playerId: Int) =>
      context.child(playerId.toString) match {
        case Some(actorRef) => actorRef ! ball
        case None           => log.warning("Player not found!")
      }
  }
}

object Player {
  case class Ball(count: Int = 0)
  def apply(playerCount: Int) = Props(new Player(playerCount))
}

final class Player(playerCount: Int) extends Actor with ActorLogging {
  import Player._

  override def receive: Receive = {
    case Ball(count) =>
      log.info(s"Player with id: ${self.path.name} has the ball --- Ball count: $count")
      context.parent ! (Ball(count + 1), 1 + (Math.random() * playerCount).toInt)
  }
}

因此,相反,每个Player actor都有对其他actor的引用,Game父actor将拥有Player个actor的集合。当每个Player&#34;踢出&#34; Ball,消息被发送到父actor,然后调度下一个选定的actor。

答案 1 :(得分:0)

演员将用来互相交谈的合约,

case object StartTheGame
case object StopTheGame

case class PlayerJoin(player: ActorRef)
case class PlayerLeave(player: ActorRef)
case class GetNextPlayer(player: ActorRef)

case class Ball(count: Int)
case class BallThrow(ball: Ball)    

球员演员,

class Player extends Actor with ActorLogging {
  override def receive = {
    case Ball(count) => {
      log.info("player has caught the ball - {}", self)
      sender() ! BallThrow(Ball(count + 1))
      log.info("player has thrown the ball - {}", self)
    }
  }
}

object Player {
  def props: Props = Props(classOf[Player])
}

游乐场,

class PlayGround extends Actor with ActorLogging {

  var players = Set.empty[ActorRef]

  var gameOnGoing = false

  def passBallToNextPlayer(player: ActorRef, ball: Ball): Unit = {
    if (gameOnGoing) {
      getRandomNextPlayer(sender()) ! ball
    }
    else {
      log.info("Game has stopped. Ball is falling to the ground.")
    }
  }

  def getRandomNextPlayer(player: ActorRef): ActorRef = {
    val otherPlayers = (players - player).toVector
    val otherPlayersCount = otherPlayers.size
    if (otherPlayersCount > 0) {
      otherPlayers((Math.random() * (otherPlayersCount - 1)).toInt)
    }
    else {
      player
    }
  }

  override def receive = {
    case StartTheGame => startTheGame()
    case StopTheGame => stopTheGame()
    case PlayerJoin(player) => {
      log.info("A new player has joined the game - {}", player)
      players = players + player
    }
    case PlayerLeave(player) => {
      log.info("A player has left the game - {}", player)
      players = players - player
    }
    case BallThrow(ball) => passBallToNextPlayer(sender(), ball)
  }

  def startTheGame(): Unit = {
    gameOnGoing = true
    players.head ! Ball(0)
  }

  def stopTheGame(): Unit = {
    gameOnGoing = false
  }

}

object PlayGround {
  def props: Props = Props(classOf[PlayGround])
}

游戏,

object Akka1 {

  def main(args: Array[String]): Unit = {
    val actorSystem = ActorSystem("game_system")

    val playGround = actorSystem.actorOf(PlayGround.props)

    playGround ! PlayerJoin(actorSystem.actorOf(Player.props))
    playGround ! PlayerJoin(actorSystem.actorOf(Player.props))
    playGround ! PlayerJoin(actorSystem.actorOf(Player.props))

    playGround ! StartTheGame
  }

}