python模拟狙击手射击恐怖分子

场景需求

闹市中,有一个恐怖分子手持菜刀劫持了一个人质,狙击手接到命令,必须将恐怖分子击毙,这整个流程用python模拟实现,且必须用面向对象的方式来写。

分解需求

假设将狙击手击毙恐怖分子流程分解为:狙击手将子弹装入弹夹,将弹夹装入狙击枪,拿枪对准恐怖分子,扣动扳机,恐怖分子玩完。用面向对象的思维来提取这个流程中的对象,分别为:

  • 狙击手
  • 恐怖分子
  • 弹夹
  • 子弹

当然,你也可以将人质,恐怖分子持的菜刀这些作为对象,不过作为模拟示例,粒度没必要过细

狙击手.jpg

思路流程如下:

#_*_coding:utf8_*_
def main():
    """程序的执行流程"""
    # 创建狙击手sniper

    # 创建枪gun

    # 创建弹夹clip

    # 创建子弹bullet

    # 创建恐怖分子terrorist

    # 狙击手将子弹安装到弹夹中

    # 狙击手将弹夹安装到枪中

    # 狙击手拿起枪

    # 狙击手开枪射杀恐怖分子

if __name__ == '__main__':
    main()

创建对象

提取需求中的对象后,就可以来创建相应的类了:

狙击手和恐怖分子均属于人,只需建一个Person类,枪、弹夹、子弹分别创建独立的类

# 人物类
class Person(object):
    def __init__(self, name):
        super(Person, self).__init__()
        self.name = name

# 枪类
class Gun(object):
    def __init__(self, name):
        super(Gun, self).__init__()
        self.name = name

# 弹夹类
class Clip(object):
    def __init__(self, max_num):
        super(Clip, self).__init__()
        self.max_num = max_num # 表示弹夹能装的子弹数量

# 子弹类
class Bullet(object):
    def __init__(self):
        super(Bullet, self).__init__()

def main():
    """程序的执行流程"""
    # 创建狙击手sniper
    sniper = Person('狙击手')

    # 创建枪gun
    gun = Gun('狙击步枪')

    # 创建弹夹clip
    clip = Clip(15)

    # 创建子弹bullet
    bullet = Bullet()

    # 创建恐怖分子terrorist
    terrorist = Person('恐怖分子')

    #...

将子弹装到弹夹中

子弹是一个独立的对象,要装到弹夹中,就必须在弹夹类中创建一个属性来保存子弹的对象,每个子弹对象表示一颗独立的子弹,而装子弹这个动作是由狙击手发起的,因此在Person类中应新增装子弹的方法

Person 类新增方法: 装子弹

def install_bullet(self, clip, bullet):
    # 将子弹装入弹夹中
    clip.save_bullet(bullet)

Clip 弹夹类新增方法: 保存子弹

class Clip(object):
    def __init__(self, max_num):
        super(Clip, self).__init__()
        self.max_num = max_num # 弹夹的最大容量
        self.bullet_list = [] # 保存子弹对象的引用

    def save_bullet(self, bullet):
        # 将子弹存入弹夹
        self.bullet_list.append(bullet)

main() 中调用装子弹的方法:

def main():
    # ...
    # 狙击手将子弹安装到弹夹中
    sniper.install_bullet(clip, bullet)

狙击手将弹夹装到枪中

Person 类应新增装弹夹的方法,枪类需新增保存弹夹的方法

Person 新增方法:装弹夹

    def install_clip(self, gun, clip):
        # 将弹夹装入枪中
        gun.save_clip(clip)

Gun 枪类新增方法:保存弹夹

class Gun(object):
    def __init__(self, name):
        super(Gun, self).__init__()
        self.name = name
        self.clip = None # 记录弹夹对象的引用

    def save_clip(self, clip):
        self.clip = clip

main() 中调用装子弹的方法:

def main():
    # ...
    # 狙击手将弹夹安装到枪中
    sniper.install_clip(gun, clip)

测试枪、弹夹、子弹

测试往弹夹添加一些子弹,打印出弹夹、子弹和枪的相关信息

#_*_coding:utf8_*_
class Person(object):
    def __init__(self, name):
        super(Person, self).__init__()
        self.name = name

    def install_bullet(self, clip, bullet):
        # 将子弹装入弹夹中
        clip.save_bullet(bullet)

    def install_clip(self, gun, clip):
        # 将弹夹装入枪中
        gun.save_clip(clip)

class Gun(object):
    def __init__(self, name):
        super(Gun, self).__init__()
        self.name = name
        self.clip = None # 记录弹夹对象的引用

    def save_clip(self, clip):
        self.clip = clip

    def __str__(self):
        if self.clip:
            return '枪的信息为:%s, %s' % (self.name, self.clip)
        else:
            return '枪的信息为:%s, 没有弹夹' % self.name


class Clip(object):
    def __init__(self, max_num):
        super(Clip, self).__init__()
        self.max_num = max_num # 弹夹的最大容量
        self.bullet_list = [] # 保存子弹对象的引用

    def save_bullet(self, bullet):
        # 将子弹存入弹夹
        self.bullet_list.append(bullet)

    def __str__(self):
        return '弹夹能装%s颗子弹,当前有%s颗子弹' % (self.max_num, len(self.bullet_list))

class Bullet(object):
    def __init__(self):
        super(Bullet, self).__init__()


def main():
    """程序的执行流程"""
    # 创建狙击手sniper
    sniper = Person('狙击手')

    # 创建枪gun
    gun = Gun('狙击步枪')

    # 创建弹夹clip
    clip = Clip(15)

    # 创建子弹bullet
    for i in range(6):
        bullet = Bullet()
        sniper.install_bullet(clip, bullet)

    # 创建恐怖分子terrorist
    terrorist = Person('恐怖分子')

    # 狙击手将子弹安装到弹夹中
    # sniper.install_bullet(clip, bullet)

    # 狙击手将弹夹安装到枪中
    sniper.install_clip(gun, clip)

    # 测试弹夹信息
    print(clip)

    # 测试枪的信息
    print(gun)

    # 狙击手拿起枪

    # 狙击手开枪射杀恐怖分子

if __name__ == '__main__':
    main()

执行结果为:

弹夹能装15颗子弹,当前有6颗子弹
枪的信息为:狙击步枪, 弹夹能装15颗子弹,当前有6颗子弹

狙击手拿起枪

python 类新增方法:拿枪

class Person(object):
    def __init__(self, name):
        super(Person, self).__init__()
        self.name = name
        self.gun = None

    def install_bullet(self, clip, bullet):
        # 将子弹装入弹夹中
        clip.save_bullet(bullet)

    def install_clip(self, gun, clip):
        # 将弹夹装入枪中
        gun.save_clip(clip)

    def hold_gun(self, gun):
        # 举枪
        self.gun = gun

    def __str__(self):
        if self.gun:
            return "这是一个%s, 手持%s" % (self.name, self.gun.name)

塑造恐怖分子形象

狙击手和恐怖分子同属于Person类,在实例化时要有所区分(简单起见,以是否有枪为区分)

def __str__(self):
    if self.gun:
        return "这是一个%s, 手持%s" % (self.name, self.gun.name)
    else:
        return "这是一个恐怖分子,正手持菜刀劫持人质"

狙击手向恐怖分子射击

射击的动作分解为:狙击手发起射击,弹夹弹出最上面的一颗子弹,子弹射向恐怖分子,恐怖分子玩完

整个射击的动作将所有类都调动起来了

#_*_coding:utf8_*_
class Person(object):
    def __init__(self, name):
        super(Person, self).__init__()
        self.name = name
        self.gun = None

    def install_bullet(self, clip, bullet):
        # 将子弹装入弹夹中
        clip.save_bullet(bullet)

    def install_clip(self, gun, clip):
        # 将弹夹装入枪中
        gun.save_clip(clip)

    def hold_gun(self, gun):
        # 举枪
        self.gun = gun

    def __str__(self):
        if self.gun:
            return "这是一个%s, 手持%s" % (self.name, self.gun.name)
        else:
            return "这是一个恐怖分子,正手持菜刀劫持人质"

    def shoot(self, terrorist):
        # 向恐怖分子发起射击
        print('%s向%s射击' % (self.name, terrorist.name))
        self.gun.fire(terrorist)

    def game_over(self):
        # 被击中,玩完了
        print("%s被击中,已玩完" % self.name)

class Gun(object):
    def __init__(self, name):
        super(Gun, self).__init__()
        self.name = name
        self.clip = None # 记录弹夹对象的引用

    def save_clip(self, clip):
        self.clip = clip

    def __str__(self):
        if self.clip:
            return '枪的信息为:%s, %s' % (self.name, self.clip)
        else:
            return '枪的信息为:%s, 没有弹夹' % self.name

    def fire(self, terrorist):
        # 枪从弹夹中获取一发子弹,子弹向恐怖分子发射过去
        
        # 从弹夹取出一发子弹
        bullet = self.clip.pop_bullet()

        if bullet:
            bullet.hit(terrorist)
        else:
            print('坑啊,竟然没子弹了')
        


class Clip(object):
    def __init__(self, max_num):
        super(Clip, self).__init__()
        self.max_num = max_num # 弹夹的最大容量
        self.bullet_list = [] # 保存子弹对象的引用

    def save_bullet(self, bullet):
        # 将子弹存入弹夹
        self.bullet_list.append(bullet)

    def __str__(self):
        return '弹夹能装%s颗子弹,当前有%s颗子弹' % (self.max_num, len(self.bullet_list))

    def pop_bullet(self):
        # 弹出最上面的子弹
        if self.bullet_list:
            return self.bullet_list.pop()
        else:
            return None

class Bullet(object):
    def __init__(self):
        super(Bullet, self).__init__()

    def hit(self, terrorist):
        terrorist.game_over()



def main():
    """程序的执行流程"""
    # 创建狙击手sniper
    sniper = Person('狙击手')

    # 创建枪gun
    gun = Gun('狙击步枪')

    # 创建弹夹clip
    clip = Clip(15)

    # 创建子弹bullet
    for i in range(6):
        bullet = Bullet()
        # 狙击手将子弹安装到弹夹中
        sniper.install_bullet(clip, bullet)

    # 狙击手将弹夹安装到枪中
    sniper.install_clip(gun, clip)

    # 测试弹夹信息
    print(clip)

    # 测试枪的信息
    print(gun)

    # 狙击手拿起枪
    sniper.hold_gun(gun)
    print(sniper)

    # 创建恐怖分子terrorist
    terrorist = Person('恐怖分子')
    print(terrorist)

    # 狙击手开枪射杀恐怖分子
    sniper.shoot(terrorist)

if __name__ == '__main__':
    main()

执行结果为:

弹夹能装15颗子弹,当前有6颗子弹
枪的信息为:狙击步枪, 弹夹能装15颗子弹,当前有6颗子弹
这是一个狙击手, 手持狙击步枪
这是一个恐怖分子,正手持菜刀劫持人质
狙击手向恐怖分子射击
恐怖分子被击中,已玩完

总结

  • 面向对象是解决现实复杂问题的良好方式,可以将复杂问题分解为由各种对象交互传递消息,从而使问题简单化
  • 对象通常用属性来保存其他对象的引用,实现相互之间的关联

源码下载

源码包

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android常用基础

GreenDAO快速入门

之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有...

913
来自专栏码匠的流水账

聊聊kafka consumer offset lag increase异常

本文主要解析一下遇到的一个kafka consumer offset lag不断增大的异常。

561
来自专栏个人分享

Hive metastore整体代码分析及详解

  从上一篇对Hive metastore表结构的简要分析中,我再根据数据设计的实体对象,再进行整个代码结构的总结。那么我们先打开metadata的目录,其目录...

1403
来自专栏Jed的技术阶梯

Spark常用Transformations算子(二)

介绍以下Transformations算子: aggregateByKey join cogroup cartesian pipe repartit...

784
来自专栏码匠的流水账

reactor-netty的TcpClient如何往eventLoop提交task

本文主要研究一下reactor-netty的TcpClient如何往eventLoop提交task

1012
来自专栏互联网开发者交流社区

STC-单片机控制系统

1033
来自专栏码字搬砖

Spark Streaming 中使用 zookeeper 保存 offset 并重用 Java版

最近中使用spark Streaming +kafka,由于涉及到金额,所以需要保证at only one, 而网上关于java版的kafka offset...

1182
来自专栏Android开发与分享

【Android】Retrofit网络请求参数注解,@Path、@Query、@QueryMap...

3315
来自专栏函数式编程语言及工具

Akka(42): Http:身份验证 - authentication, authorization and use of raw headers

   当我们把Akka-http作为数据库数据交换工具时,数据是以Source[ROW,_]形式存放在Entity里的。很多时候除数据之外我们可能需要进行一些附...

2095
来自专栏Jack的Android之旅

刨解OkHttp框架

继AsyncTask,又把手术刀指向OkHttp,有时候解析源码会上瘾。因为源码里包含的东西仿佛就是组成计算机世界的砖头,水分,只要有这些东西,就可以保罗万物,...

762

扫码关注云+社区