首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python OOP -足球仿真

Python OOP -足球仿真
EN

Stack Overflow用户
提问于 2019-10-31 23:40:01
回答 3查看 865关注 0票数 4

我是新来的。我想模拟足球比赛。如何访问牌手/罪犯/后卫类中的Play实例变量?如果另一种结构更好,请帮忙。

代码语言:javascript
复制
class Player:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def move_to(self, x, y):
        self.x = (self.x + x) / 2
        self.y = (self.y + y) / 2

    ## Loop through Play.Players to find nearest. How do I access Play.Players?
    def nearest(self):
        return nearest

class Offender(Player):
    def __init__(self, x, y):
        super().__init__(x, y)

    # Move to ball.
    def strategy():
        ball_x = Play.ball_x # how do I access Play.ball_x
        ball_y = Play.ball_y # how do I access Play.ball_y
        self.move_to(ball_x, ball_y)

class Defender(Player):
    def __init__(self, x, y):
        super().__init__(x, y)

    # Move to nearest player
    def strategy(self):
        nearest = self.nearest()
        self.move_to(nearest)          

class Play:
    def __init__(self, offense_players, defense_players, ball_x, ball_y):
        self.offense = [Offender(player) for player in offense_players]
        self.defense = [Defender(player) for player in defense_players]
        self.players = self.offense + self.defense
        self.ball_x = ball_x
        self.ball_y = ball_y

    def simulate(self):
        while True:
            for player in self.players:
                player.strategy()

if __name__ == "__main__":
    Play().simulate()

我没有使用OffenderDefender类,而是为每个职位设置了一个类,即Striker(Player)Midfielder(Player)Goalie(Player)等,这就是为什么我希望将它们各自的strategy存储在它们的类中,而不是在Play类中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-11-01 00:17:55

我只是从马丁诺的注释中详细阐述了这个想法:我们只是将Play实例作为参数传递给Player的相关方法。我还为nearest()方法编写了第一个草案,但您可能希望改进它的逻辑。我只是起草这个演示如何解决您的OOP设计问题。

代码语言:javascript
复制
import typing


class Player:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def move_to(self, x: float, y: float) -> None:
        self.x = (self.x + x) / 2
        self.y = (self.y + y) / 2

    def nearest(self, play: "Play") -> "Player":
    # This must yet be adapted to handle the edge case of two players 
# having equal distance to the current player. You didn't specify the 
# desired output for that case, hence I just ignored that scenario for now.
        return min([
            p for p in play.players 
            if p.x != self.x or p.y != self.y, # this is to 
# exclude the player itself. 
# This is a buggy logic, because it relies on an assumption that is not  
# validated in the code (the assumption that two different players never 
# have identical coordinates). You might want to introduce a uniqe `id` 
# instance variable to the Player class, to handle this identification in a 
# clean way.
            ],
            key=lambda p: (self.x - p.x)**2 + (self.y - p.y)**2
        ) 


class Offender(Player):
    def __init__(self, x: float, y: float):
        super().__init__(x, y)

    # Move to ball.
    def strategy(self, play: "Play") -> None:
        self.move_to(play.ball_x, play.ball_y)


class Defender(Player):
    def __init__(self, x: float, y: float):
        super().__init__(x, y)

    # Move to nearest player
    def strategy(self, play: "Play") -> None:
        self.move_to(self.nearest(play=play)          


class Play:
    def __init__(
    self, 
    offense_players: typing.List["Offender"], 
    defense_players: typing.List["Defender"],
    ball_x: float, 
    ball_y: float,
):
        self.offense = offense_players
        self.defense = defense_players
        self.players = self.offense + self.defense
        self.ball_x = ball_x
        self.ball_y = ball_y

    def simulate(self) -> None:
        while True:  # this is still a bad condition, you might want to change this. However you didn't specify your desired logic, so I didn't change it.
            for player in self.players:
                player.strategy(self, play=self)
票数 1
EN

Stack Overflow用户

发布于 2019-11-01 01:16:40

不确定这对您有多大的帮助,因为实现是在C++中

您可以为类似的问题语句https://github.com/rimpo/footballcpp签出我的实现。

要了解上面写的bot所用的街机游戏框架实现,请签出http://richard-shepherd.github.io/coding-world-cup/index.html

票数 2
EN

Stack Overflow用户

发布于 2019-11-01 00:09:20

我要做以下几点:

在另一个(数据)类中跟踪游戏状态:

代码语言:javascript
复制
class GameState:

    def __init__(self, offense_players, defense_players, ball_x, ball_y):
        self.offense = offense_players
        self.defense = defense_players
        self.players = self.offense + self.defense
        self.ball_x = ball_x
        self.ball_y = ball_y

您甚至可能希望为此使用python3.7 dataclasses (和一些 其他特性)(尽管它根本不是必要的)。

代码语言:javascript
复制
from dataclasses import dataclass
from typing import List 


@dataclass 
class GameState:

    offense: List[Offender]
    defense: List[Defender]
    ball_x: float 
    ball_y: float 

    @property 
    def players(self):
        return offense + defense 

然后玩家在他们的策略中接受这个状态,并被期望更新他们的内部状态(比如位置)。nearest player是通过使用min的键参数获取其他玩家之间的最小l2距离来实现的,该参数接受另一个播放器的函数p,该函数是使用lambda编写的。

代码语言:javascript
复制
class Player:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def move_to(self, x, y, other_players):
        self.x = (self.x + x) / 2
        self.y = (self.y + y) / 2

    def nearest(self):
        return nearest

class Offender(Player):
    def __init__(self, x, y):
        super().__init__(x, y)

    # Move to ball.
    def strategy(self, game_state):
        ball_x = game_sate.ball_x # how do I access Play.ball_x
        ball_y = game_state.ball_y # how do I access Play.ball_y
        self.move_to(ball_x, ball_y)

class Defender(Player):
    def __init__(self, x, y):
        super().__init__(x, y)

    # Move to nearest player
    def strategy(self, game_state):
        # we assume you are moving to offensive players - which 
        # you will not be apart of 
        nearest = min(
            game_state.offense
            key=lambda p: (
                (self.x - p.x) **2 + (self.y - p.y) ** 2
            ) ** (1/2)  # take the l2 norm to find the "closest" player to you
        )
        self.move_to(nearest.x, nearest.y)      

然后,玩游戏

代码语言:javascript
复制
class Play:

    def __init__(self, game_state):
        self.game_state = game_state

    def simulate(self):
        while True:
            for player in self.game_state.players:
                player.strategy(self.game_state)

if __name__ == "__main__":
    Play(GameState(
        [Offender(-1, 0), Offender(-1, -1), ...]
        [Defender(1, 0), Offender(1, -1), ...]
    )).simulate()

然后您可以实现一些实际的玩家。

代码语言:javascript
复制
class TiernaDavidson(Defender):

    def strategy(self, *args, **kwargs):
        return better_strategy(*args, **kwargs)

您将不得不向请求better_strategy的实现;)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58652458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档