美文网首页
Python笔记-模拟病毒传染(第三版:Pygame图片方式)

Python笔记-模拟病毒传染(第三版:Pygame图片方式)

作者: 我开心0536 | 来源:发表于2020-03-03 11:05 被阅读0次

    【功能】
    模拟病毒传染,用Pygame图片方式做个模拟
    (python 3.7版本下调试成功)
    【比第二版的改变】
    1、显示方式为 调用pygame的图片方式

    传染初期截图.jpg
    传染中期截图(全部被感染).jpg
    传染最终截图(全部死亡).jpg

    【以下为代码,右上角有复制按钮,可一键复制】

    #用数组模拟病毒传染(Pygame图片方式)    仅做演示 Ver:20200302.03
    #目前代码有点乱,继续整理中...
    import numpy as np  #导入numpy库,用于数组生成
    import random   #导入random库,主要用做下面代码中的生成随机数功能
    import sys
    import time
    import pygame
    from pygame.locals import *
    
    #  ==============================
    #  开始请设定以下初始值:
    #  ==============================
    changdi_x = 15      # 【场地X】初始空白场地高度,也就是几行,默认15行
    changdi_y = 8       # 【场地Y】初始空白场地宽度,也就是几列,默认8列
    renshu_1  = 20      # 【人数1】在这个空白场地上,初始有多少个健康的人(人数不能超过行x列的总和),默认20人
    renshu_2  = 1       # 【人数2】在这个空白场地上,健康人中,初始有多少个感染病毒人员(初始感染病毒人数必须小于初始健康人数)(初始病毒人数越大,传染速度越快),默认1人
    bingqingjibie = 99  # 【病情级别】病人病情级别达到多少级别时,代表这个病人已经死亡。 每一局病人病情自动增加1,代表病情加重1级,默认99级
    
    #创建指定长度或者形状的全零数组 zeros()函数, 此处代表创建空白场地,用全是0的数组来表示
    arr = np.zeros((changdi_x,changdi_y))
    
    #开始向里放置健康人员
    cishu=1  #循环次数,每放一个人加1次,当达到健康人数时停止循环
    while cishu <= renshu_1 :
        x = random.randint(0, changdi_x-1)  #在这个场地中,开始随机放置人员,这是随机生成位置的【行】
        y = random.randint(0, changdi_y-1)  #在这个场地中,开始随机放置人员,这是随机生成位置的【列】
        if  arr[x][y] != 1: #如果这个行列位置已经是1(代表有人了),就换一个位置,直到这个位置是没人的行和列
            arr[x][y]= 1
            cishu = cishu + 1 #每放置成功一个人,计数加1
    print('\n第二步:',renshu_1,'名健康人员已经随机放置进空白场地中')
    print(arr)
    
    #开始放置数值为2的人(2代表感染病毒人员)
    cishu=1  #循环次数,每放一个人加1次,当达到初始病毒人数时停止循环
    while cishu <= renshu_2 :
        x = random.randint(0, changdi_x-1)  #在这个场地中,开始随机放置人员,这是随机生成位置的【行】
        y = random.randint(0, changdi_y-1)  #在这个场地中,开始随机放置人员,这是随机生成位置的【列】
        if  arr[x][y] == 1: #如果这个行列位置已经是1(代表有人了)
            arr[x][y]= 2
            cishu = cishu + 1 #每放置成功一个人,计数加1
    print('\n第三步:初始',renshu_2,'名健康人员感染病毒发作')
    print(arr)
    
    
    # ================================================
    # 开始规划 与窗口相关的内容
    # ================================================
    pygame.init() # 游戏的初始化
    
    #控制屏幕刷新频率,或者说游戏运行速度
    fpsClock = pygame.time.Clock()
    FPS = 1 # 窗口刷新频率,也就是游戏运行速度,数字越大,运行越快
    #fpsClock.tick(FPS)  # 配合本句才可生效,放在循环内结尾pygame.display.update()后
    
    windows_x = 1024 #设定窗口宽度,像素数,默认1024
    windows_y = 600  #设定窗口高度,像素数,默认600
    screen = pygame.display.set_mode((windows_x,windows_y),0,32)   #创建游戏设置窗口大小
    pygame.display.set_caption('病毒传染模拟 Ver20200303.03')  #窗口标题
    GREEN = (255,255,255) #定义某种颜色
    
    myfont = pygame.font.Font(None,60)  #使用pygame.font将文打印到窗口。要打印文本的话首先需要创建一个文字对象。使用默认字体,不能显示中文
    #myfont = pygame.font.SysFont("C:/Windows/Fonts/simhei.ttf", 60)  #显示中文的设置和字体,及路径
    # 定义几个字体颜色
    BLACK=(0,0,0)
    BLACK100=(100,100,100)
    WHITE = (255, 255, 255)
    RED=(255,0,0)
    GREEN = ( 0, 255, 0)
    BLUE = ( 0, 0, 255)
    YELLOW=(255,255,0)
    RED2=(255,0,255)
    
    #开始根据屏幕大小、场地长宽,计算每个小人显示多少像素
    img_w = int( (windows_x-100)/changdi_x )  #窗口宽度-100(左边右边各留50像素) 再除以场地准备放多少个人数
    img_h = int( (windows_y-60-100 )/changdi_y )  #窗口宽度- 60(上边下边各留30像素) 再除以场地准备放多少个人数
    Img0 = pygame.transform.scale(pygame.image.load('images/ren_00.png'),(img_w,img_h))  # 0空地
    Img1 = pygame.transform.scale(pygame.image.load('images/ren_01.png'),(img_w,img_h))  # 1健康人
    Img2 = pygame.transform.scale(pygame.image.load('images/ren_02.png'),(img_w,img_h))  # 2初染
    Img3 = pygame.transform.scale(pygame.image.load('images/ren_03.png'),(img_w,img_h))  # 3发作中
    Img4 = pygame.transform.scale(pygame.image.load('images/ren_04.png'),(img_w,img_h))  # 4病危
    
    Img_face = pygame.transform.scale(pygame.image.load('images/face.png'),(windows_x,windows_y))  # 封面
    
    def print_png():  #显示所有人员图片
        for x in range(0, changdi_x):  # 从第一行开始循环,直到最后一行
            for y in range(0, changdi_y):  # 每行从第一列开始循环,直接最后一列
                if arr[x][y] == 0:  #0代表空白场地
                    screen.blit(Img0,(50+x*img_w, 30+y*img_h ))
                elif  arr[x][y] == 1: #1代表健康人员
                    screen.blit(Img1,(50+x*img_w, 30+y*img_h ))
                elif  arr[x][y] <= 5:  #2代表初染人员
                    screen.blit(Img2,(50+x*img_w, 30+y*img_h ))
                elif  arr[x][y] >= bingqingjibie:  # 达到病情级别的人
                    screen.blit(Img4,(50+x*img_w, 30+y*img_h ))
                else:  #其它病情的人员
                    screen.blit(Img3,(50+x*img_w, 30+y*img_h ))
    
    
    def chuanran(): #自身加重,并传染相邻健康人员
        print('\n【第',cishu,'天模拟开始】 ')
        #  ==============================
        #  每局病人自身加重1级(数值加1),并且检测上下左右相邻是否有健康(数值是1)的人员,如果有就传染他(健康人员的数值从1变成2)
        #  ==============================
        for x in range(0,changdi_x):        # 从第一行开始循环,直到最后一行
            for y in range(0,changdi_y):       #每行从第一列开始循环,直接最后一列
                if arr[x][y] > 1 and  arr[x][y]< 200 :   #如果当前位置是不健康的人(数值不是0或1的人,0代表空地,1代表健康的人,大于等于2的代表带病毒的人)
    
                    #如果检测到病毒人员,每局病情自身加重1级
                    if arr[x][y] < bingqingjibie:     #如果病人严重程度没有到99级,就对这个病人每局病情加重一级。如果已经到了99级,权当代表这个病人已经OVER了
                        arr[x][y] = arr[x][y] + 1     #每局,自身数字+1,代表每一局病情又严重了1级
                        print('  坐标为',x+1,',',y+1,'的病人病情加重1级,达到',arr[x][y],'级')
                    else:
                        print('  坐标为',x+1,',',y+1,'的病人已达到最高',bingqingjibie,'级')
    
                    #开始检测这个病毒人员上下左右是否有相邻的健康人员,有的话就传染给这个相邻的健康人员
                    if x > 1:                 #先确定当前人员X坐标不是在第一行(因为第一行人员上面就不可能再有一行了)
                        if arr[x-1][y] == 1:  #检测上面相邻的人是否为1(1代表相邻有健康的人),如果是就传染他(把1变成2)
                            arr[x-1][y] = 2
                            print('        他传染了上面相邻的人,感染人数 +1')
    
                    if x < changdi_x-1:       #先确定当前人员X坐标不是在最后一行
                        if arr[x+1][y]==1:    #检测下面相邻的人是否为1,如果是就把1变成2并放大100倍.(放大100倍,是为了防止新病人再被重新计算一次)
                            arr[x+1][y] = 200
                            print('        他传染了下面相邻的人,感染人数 +1')
    
                    if y > 1 :                #先确定当前人员y坐标不是在最左边,即第一列
                        if arr[x][y-1] == 1:  #检测左面相邻的人是否为1,如果是就把1变成2
                            arr[x][y-1] = 2
                            print('        他传染了左面相邻的人,感染人数 +1')
    
                    if y < changdi_y-1 :      #先确定当前人员y坐标不是在最右边,即最后一列
                        if arr[x][y+1]==1:    #检测右面相邻的人是否为1,如果是就把1变成2并放大100倍(放大100倍,是为了防止新病人再被重新计算一次)
                            arr[x][y+1] = 200
                            print('        他传染了右面相邻的人,感染人数 +1')
    
        #上面为了防止向右、向下被传染的人员,在同一局中再一次传染别人,所以在上面将数值放大了100倍。本局传染结束,通过下面再缩小100倍还原回原数值
        for x in range(0,changdi_x):        # changdi_x
            for y in range(0,changdi_y):    # changdi_y
                if arr[x][y] >=200 :        # 将上面为了防止重复移动而放大100倍的数值再缩小回来。
                    arr[x][y] = arr[x][y] / 100
    
    
    def yidong():  #人员移动
        #  ==============================
        #  所有人员开始移动位置,代表人员可以流动。 每人每局可移动一次,一次只能上下左右移动一格,并且移动到的位置要没有人才可。
        #  ==============================
        for x in range(0,changdi_x):        # changdi_x
            for y in range(0,changdi_y):    # changdi_y
                if arr[x][y] > 0 and arr[x][y] <bingqingjibie :   # 如果这个位置有人(0代表空地,1代表健康人,2及以上代表病人),则该人随机上下左右移动  #病情级别达到最高的就不移动了
                    fangxiang = random.choice(['向上','向下','向左','向右']) #随机生成移动方向
                    if fangxiang == '向上' and x > 0 :   #随机数字=1,代表准备向上移动。 如果要向上,必须保证当前人员不是在最顶上一行
                        if  arr[x-1][y] == 0 :      #并且上面位置没有人
                            arr[x-1][y] = arr[x][y] #上面的位置 变成 当时位置的数值
                            arr[x][y] = 0           #原先的位置空出来,变成0
                            print(x+1,',',y+1,'  向上移动了一步')
    
                    if fangxiang == '向下' and x < changdi_x-1 :  #随机数字=2,代表准备向下移动。如果要向下,必须保证当前人员不是在最底下一行
                        if  arr[x+1][y] == 0 :               #并且下面位置没有人
                            arr[x+1][y] = arr[x][y]*100      #下面的位置变成 当时位置的数值*100。 乘以100,以为了防止在本局再移动一次!
                            arr[x][y] = 0                    #原先的位置空出来,变成0
                            print(x+1,',',y+1,'  向下移动了一步')
    
                    if fangxiang == '向左' and y > 0 :     #随机数字=3,代表准备向左移动。如果要向左,必须保证当前人员不是在最左头
                        if  arr[x][y-1] == 0 :        #并且左面位置没有人
                            arr[x][y-1] =  arr[x][y]  #在面的位置 变成 当时位置的数值
                            arr[x][y] = 0             #原先的位置空出来,变成0
                            print(x+1,',',y+1,'  向左移动了一步')
    
                    if fangxiang == '向右' and y < changdi_y-1 :     #随机数字=4,代表准备向右移动。 如果要向左,必须保证当前人员不是在最右边
                        if  arr[x][y+1] == 0 :                  #并且右面位置没有人
                            arr[x][y+1] = arr[x][y]*100         #右面的位置变成 当时位置的数值*100。 乘以100,以为了防止在本局再移动一次!
                            arr[x][y] = 0                       #原先的位置空出来,变成0
                            print(x+1,',',y+1,'  向右移动了一步')
    
        #上面为了防止向右、向下移动后的人员,在同一局中再一次被重复移动,所以在上面将数值放大了100倍。现在移动结束,通过下面再缩小100倍还原回原数值
        for x in range(0,changdi_x):        # changdi_x
            for y in range(0,changdi_y):    # changdi_y
                if arr[x][y] >=100 :        # 将上面为了防止重复移动而放大100倍的数值再缩小回来。
                    arr[x][y] = arr[x][y] / 100
    
    
    # ================================================
    # 开始主体循环!!!
    # ================================================
    cishu=1
    start=0  #判断是否开始
    
    while True:
        # 检测是否要关闭窗口
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        # 检测键盘,并检测是否按下Esc键
        keys = pygame.key.get_pressed()
        if keys[K_ESCAPE]:
            sys.exit()
        if keys[K_SPACE] and start==0:
            start=1
    
        if start==0:
            screen.fill(WHITE)  # 填充背景
            #开始显示封面
            screen.blit(Img_face, (0, 0))
            pygame.display.update()
    
        screen.fill(WHITE)  # 填充背景
    
        if start==1 and sum(sum(arr)) < renshu_1 * bingqingjibie :   #如果全部人员,还没有达到最严重级别
            #在屏幕上显示文本:第几天
            text_image1 = myfont.render( "The "+str(cishu)+" Day", True, BLACK100)  # render函数第一个参数是文本,第二个参数是抗锯齿字体,第三个参数是一个颜色值(RGB值)
            screen.blit(text_image1, (50, windows_y-80))   #文字显示位置
    
            if 1 not in arr:  #如果全部被感染,则显示 健康人员:0
                text_image2 = myfont.render("Health: 0 !", True, RED2)  # render函数第一个参数是文本,第二个参数是抗锯齿字体,第三个参数是一个颜色值(RGB值)
                screen.blit(text_image2, (400, windows_y - 80))  # 文字显示位置
                FPS = 10  # 窗口刷新频率,也就是游戏运行速度,数字越大,运行越快。  全部被感染后,游戏速度加快!!!
    
            if bingqingjibie in arr:  #如果出现级别最高的人员,则显示 死亡开始!
                text_image2 = myfont.render("Death Start !", True, RED)  # render函数第一个参数是文本,第二个参数是抗锯齿字体,第三个参数是一个颜色值(RGB值)
                screen.blit(text_image2, (700, windows_y - 80))  # 文字显示位置
                FPS = 20  # 窗口刷新频率,也就是游戏运行速度,数字越大,运行越快。  出现死亡人后,游戏速度再加快!!!
    
            #开始数组的具体变化
            print_png()
            chuanran()
            if cishu==1: #如果是第一次,暂停5秒
                pygame.display.update()
                time.sleep(3)
    
            print_png()
            yidong()
    
            cishu=cishu+1
    
            #开始更新屏幕画面
            pygame.display.update()
            #控制游戏速度, 一般放在结尾pygame.display.update()后
            fpsClock.tick(FPS)
    

    代码中用到的图片,请下载并保存到代码下面的 images 文件夹
    文件名分别为ren_0.png、ren_1.png、ren_2.png、ren_3.png、ren_4.png

    ren_00.png ren_01.png ren_02.png ren_03.png ren_04.png face.png

    相关文章

      网友评论

          本文标题:Python笔记-模拟病毒传染(第三版:Pygame图片方式)

          本文链接:https://www.haomeiwen.com/subject/hvcqlhtx.html