在Swift中打造一个完整的篮球运动员

我们回来了另一篇文章! 我们仍在打造令人惊叹的篮球比赛的道路上。 如果您已经阅读了我以前的文章,欢迎您回来,如果您是第一次阅读,也谢谢您。 1月中旬,我撰写了第一篇有关创建篮球模拟iOS应用程序的文章,从而踏上了这一旅程。 如果您想了解更多有关该项目的动机和开始设计的信息,请查看! 对于本篇文章,我想重新了解我们的篮球运动员的初始模板,并看看我们是否可以建立一个更加充实的表示形式。

当前的球员阶级,以及为什么我们应该提高它

这是我们当前播放器类的第一个版本。

我们只有两个不同的变量来总结玩家的全部技能。 我确定您会想到此实现可能存在的问题。 我在下面概述了一些我想到的优点和缺点:

优点

  • 易于跟踪玩家的技能,并在计算中使用
  • 对于其他开发人员来说很容易理解,特别是如果他们不熟悉篮球的话
  • 没有歧义或主观解释的余地

缺点

  • 不太详细或有趣
  • 玩家不是那么独特。 除名字外,与众不同或脱颖而出的有限方法
  • 同样,这是BORING

现在,考虑到这些事实,很明显,我们需要改进此设计。 试想一下:是什么使篮球运动员如此特别? 有些人真的是伟大的三分射手,例如史蒂芬·库里,还有一些是伟大的传球手,例如克里斯·保罗。 像鲁迪·戈伯特(Rudy Gobert)这样的人确实很擅长防守底线。 在我们当前的Player类中,这些技能都没有唯一体现,并且如果没有像上面这样的专门技能,任何体面的篮球模拟都将变得乏味。

新篮球运动员班

这是一个新类,其中包含更多的变量列表。 如前几篇文章所述,我已经为该应用程序创建了一个Xcode项目,并创建了一个PlayerFunctions.swift来保存我的Player类。

与以前的版本没有太大不同。 我们只是将进攻扩展为给定球员的防守,以扩大防守范围。 此外,如果您曾经打过NBA 2K或其他流行的篮球比赛,我们还会提供一些您可能熟悉的统计数据。

使用播放器类型初始化播放器

接下来,我们需要编写init函数来创建Player的实例。 为此,我们需要将所有评级变量都设置为默认值。 我们可以将其留给函数的调用者来设置所有这些值。 或者,我们可以有不同的玩家原型! 这意味着我们可以根据特定的预设类型设置所有球员技能:

在这里,我们有三种不同类型的玩家:神枪手,大幅削减得分手和后卫。 神枪手的三分球和罚球命中率很高,但在其他类别中却遭受损失。 出色的得分手拥有出色的内线得分能力,但很难与其他位置投篮。 防守者没有良好的进攻技巧,但在球的另一侧占优势。 现在,我们可以创建一个具有以下功能的播放器,该函数从我们的一种类型中随机选择以初始化播放器:

这样,我们的球员就会更加专业。 尽管我们仍然可以添加功能以允许自定义每个分级,但是我们可以暂时简化它,并在需要时进行扩展。 但是,我们在玩家中还有另一个重要的概念要表达:玩家倾向。

什么是玩家倾向?

不同的玩家不仅拥有不同的技能,而且在不同的时间做不同的事情。 让我们以NBA为例。 看看金州勇士队的史蒂芬·库里和克莱·汤普森。 尽管他们都是出色的三分射手,但是库里作为控球后卫意味着他更有可能更多地传球。 同时,当汤普森从外部成为如此出色的射手时,他不太可能在内部射门。 玩家的倾向是他们在特定时间可能执行的动作的列表,按执行每个动作的机会来组织。 现在,我不知道像NBA 2K这样的篮球比赛如何代表球员的倾向。 从字面上看是不知道的。 我花了几个小时写下各种实现,找到了一些明显的问题,然后完全重写以最终制定策略。

玩家倾向的早期想法存在问题

我认为,如果我包含无法解决的问题,那么我认为这篇文章将对人们有用得多,而不仅仅是直接进入我确定的最终实现。 也许其他人可以接受这些想法之一,并比我可能更好地加以改进。 这是我想出的最佳替代解决方案:

理念1:将趋势与玩家评分相匹配,并且进攻/防御评分总计为100。

  • 示例:90分的三分意味着玩家将有90%的时间投三分。
  • 优点:无需添加任何其他代码,因为我们将使用玩家评分来确定他们的行动。
  • 劣势:不太现实,如果我们想让不同技能的玩家参与,将会引起问题。 理论上,明星球员的总评分会更高,但这种模式下的总得分不能超过100。

理念2:为每个操作设置一个趋势变量,每个变量都是一个整数,代表执行该操作的机会百分比。

  • 示例:给定的玩家可能有70%的三分球命中率,20%的内线命中率以及10%的传球机会。这意味着三分球命中率是70%,20%的机率内部得分的机会,还有10%的机会传球。
  • 优点:将用于定制趋势以匹配特定玩家。 而且,从功能的角度讲,这是最有意义的,新来的人可以轻松理解它。
  • 缺点:它可以工作,但是如果我们只有整数可以使用,我们将如何选择一个随机动作? 我们可以创建一个自定义随机函数来处理确定一个动作所需的逻辑,但是它可能很快变得复杂。 至少,我想不出一种简单的方法来实现它,除了我以外,对任何人都有意义!

我们将如何表示玩家倾向

我最终创建了一个PlayerTendency类,以防止我们的Player类过大(目前)。 这是我要跟踪的趋势:

是的,所有趋势对象都是范围似乎有些奇怪。 如果您不熟悉Range数据类型,请从Apple的开发人员文档中获取:“从下限到上限(但不包括上限)的半开间隔”。 我们为什么要使用这个? 当我们使用它来初始化我们的趋势时,我相信它会有意义。

此方法与将这些变量表示为整数的想法非常相似,但有所不同。 通过跟踪把握特定动作机会的界限,随机选择动作变得容易得多。 实际上,它看起来像这样:

这些是我添加到PlayerTendency类的附加功能。 真好! Range数据类型使我们能够设计一套精简而简单的功能,以便在需要时随机选择进攻和防御行动。 同样,如果我们想为自定义趋势提供功能,我们可以选择在init函数中接受将创建自定义范围的整数。 现在,让我们使用此新功能!

在游戏中整合玩家倾向

在上一篇文章中,我们创建了一个Team类,该类包含玩家花名册,一个Game类,其中包含两个Teams,并允许我们运行游戏。 让我们关注玩家直接参与的地方。 我们通过在每场比赛中给每支球队100进攻性财产来经营我们的比赛,他们有机会得分或不得分。 从第1队随机选择一名球员进攻,从第2队随机选择一名防守球员。 根据他们各自的技能,得分为2或0。

现在,事情将会变得更加有趣。 为了不使该初始版本过于复杂(您很快就会明白为什么),让我们看看我们现在是否只能跟踪得分,助攻和抢断。 我们将从获得随机玩家的进攻动作以及该动作的给定等级开始。 这些是我在Player类中添加的其他功能:

这些函数返回我们需要的元组信息。 玩家选择的动作和该动作的随机评分会一起返回。 当然,评级必须是随机的。 斯蒂芬·库里(Steph Curry)不会出手,是吗? 让我们用它来修改现有的playPossession函数:

如果您注意到了,我们在函数中添加了一个新参数。 那很快就会有意义。 在获得两个玩家的移动和等级之后,我们需要添加更多功能:

如果playerOne在特定举动上的进攻得分高于playerTwo的得分,就会发生这种情况。 我还添加了一些打印语句,以便我们可以看到何时选择了哪个动作。 在这里,我们正在以独特的方式处理“通过”动作。 我们将为同一支球队运行一个新的进攻性控球权,下一位进攻性球员将根据他们接下来选择的任何举动获得奖励。 这可能看起来很奇怪,但是可以满足我们的需求。

(在写这篇文章的时候,我意识到我没有考虑到玩家可能会沦为自己的情况。以为我仍然把它留给展示完整功能的永无止境的进步!)

TeamOneBoxScore和TeamTwoBoxScore是创建的Game类变量,用于跟踪玩家的所有给定统计信息:

接下来,我们将处理防守球员胜出时发生的情况:

然后,将点添加到boxScore并返回分数。

几乎在这里完成。 我们只需要对runGame函数进行一些其他调整,以适应我们正在跟踪的新统计信息。

我认为我们终于可以测试了。

看到我们的玩家行动趋势

我快速创建了一个UI,以选择一些随机的团队并运行游戏,而不是通过编写代码来运行每个功能:

在选择了一些随机的团队并运行了游戏之后,下面是一些结果:

助攻或抢断次数不多,但逐场比赛看上去不错! 我们肯定可以在以后的迭代中对其进行改进。

结论思想

到目前为止,这是我在Medium上最长的帖子。 我真的很喜欢制作这些文件并在应用程序上工作,但是哇。 我绝对精疲力尽! 如果您想帮助我重新振作起来,那么我真的很喜欢对该项目任何部分的反馈或评论。 所有批评都受到赞赏,希望篮球爱好者相信我的所作所为。 查看关于该应用程序的第一篇文章,然后在@ TobitheGreat3上向我发送推文!