模拟的草地

'''
整体思路
植物生长分7个阶段,遵循以下规则
1> 每经过一回合就进入下一阶段
2> 部分阶段是敏感期(2,4,6)临近区域的植物'过壮'就死亡(我设计成15)
3> 死亡时,会留下遗骸,遗骸的生命力是负值,是hp的相反数(越大的植物死亡,腐化时间越长)
4> 遗骸每回合恢复1,恢复到0之前,种子无法在这里萌发
5> 后四个生育阶段,都会释放种子 分别释放 1231个

备注
1> 因为我的错误 规则2>并没有起到预期的作用
2> 246阶段死亡,hp = -hp,7阶段死亡就成了hp = -hp*4 这里纯粹是我个人的疏忽

个人认为的要点:
1> 棋盘的复制, 同回合的棋子不相互影响!!!!!!格子只受上回合棋盘的影响.
假定AB临近 A根据周边(包括B)变成的 新A ,'B 变 新B '的过程参考的应该是 旧A 而不是新A
2> 如果棋盘是 双层嵌套的list ,请注意"深浅拷贝"

'''


from copy import deepcopy
from random import sample,randint
import pygame
import os
#  图形界面是pygame,只有这个模块需要安装

'''
aound_dict全局常量,只读不改,内容是
(0, 0), (-1, 0), (1, 1),
(1, 0), (-1, 1), (0, -1),
(-1, -1), (1, -1), (0, 1)}
是以(0,0)为中心的 3x3 区域的相对坐标
'''
around_dict = {(i,j) for i in range(-1,2) for j in range(-1,2) }
# around_dict应当是列表,是我错写成集合了,但不影响结果

#-----------------导入结束-----------------------

def ask(z):
    # z是坐标,二元元组
    # 返回该坐标在上回合的值
    # 超范围的默认为0
    x,y = z
    if 0 <= x < x_max and 0 <= y < y_max:
        return max_copy[y][x]
    return 0

def probe(z):
    # 判断坐标是否越界
    x,y = z
    return 0 <= x < x_max and 0 <= y < y_max

def around(x,y):
 
    return sum(list(map(ask,around_dict)))
    # 返回 x,y 为中心的3x3区域的"总生命值"
    # 我当初写错了....
    # 应当是
'''
def around(x,y):
    around_dict = [(x+i,y+j) for i,j in around_dict]
    return sum(list(map(ask,around_dict)))
'''

def release_seed(x,y,n):
    # 以x,y为中心 释放n枚种子
    l = [(x+i,y+j)for i,j in sample(k49,n)]
    l = filter(probe,l)
    # 过滤越界的种子
    seeds.update(set(l))
    # set成 集合 过滤重复元素
    # 因为seed本身就是set, set(l)有些多余

def drow():
    # 绘制界面的函数
    screen.fill((255,255,255))
    for x in range(x_max):
        for y in range(y_max):
            hp = max_list[y][x]
            pygame.draw.rect(screen, colors[hp], (x * 5, y * 5, 5, 5))
            # colors是字典 key是hp,value是对应颜色的RGB值
    pygame.display.update()

#-----------------函数定义结束-------------------


x_max = 180
y_max = 120

max_list = [[0 for i in range(x_max)]for j in range(y_max)]
# max_list 是"棋盘",以双重列表的形式储存每一块的值,这里初始化棋盘
max_copy = []
# max_copy 是"棋盘的拷贝",此处相当于声明变量
seeds = {(90,60)}
# 最开始的种子
k49 = [(i,j)for i in range(-3,4)for j in range(-3,4)]
# 和aound_dict类似,但是这个是7x7范围的表,以0,0为中心,所以是-3到3

def run_one():
    # 这是个每个回合都要执行的函数
    global max_copy,max_list

    max_copy = deepcopy(max_list)
    #deepcopy是copy模块的内容,用来拷贝棋盘,不懂的请自行了解"深浅拷贝"

    #ss = 10 - len(seeds)//30
    # ss是"发芽率" 因图形不好看废弃这个设定
    # 这是是要根据种子数量,实现"动态发芽率",种子少,发芽率高
    # 种子多,发芽率低,用来限制草地规模

    for x,y in seeds:
        if max_list[y][x] :
            pass
        else:
            max_list[y][x] = 1 #if randint(1,10)<=ss else 0
    # seeds 是所有"种子"的列表, 如果种子落到了有植物(>0)或是荒地(<0)的格子,则什么都不会发生
    # 如果恰好为0,则发芽,hp更新成1
    # '#if randint(1,10)<=ss else 0'是废弃的发芽率设定

    seeds.clear()
    # 清空种子

    for x in range(x_max):
        for y in range(y_max):
            # 两层for遍历所有方格
            hp = max_list[y][x]
            # 读取hp
            #  4-7 1231

            # 连续的if 不同的hp有不同的处理流程
            if not hp:
                pass
            elif hp < 0:
                hp += 1
            elif hp in {2,4,6}:
                if around(x,y) > 15 :
                    hp = -hp*1
                if hp-3 > 0:
                    release_seed(x,y,hp-3)
                hp+=1
            elif hp in {1,3,5}:
                hp += 1
                if hp == 5:
                    release_seed(x,y,2)
            elif hp == 7:
                release_seed(x,y,1)
                hp = -7*4
            max_list[y][x] = hp
        
#-----------------pygame时间----------------      
pygame.init()
screen = pygame.display.set_mode((900,600))
pygame.display.set_caption("begin")

fps = 100
fclock = pygame.time.Clock()

colors = {-7: (181, 181, 181), -6: (181, 181, 181), -5: (181, 181, 181),
          -4: (181, 181, 181), -3: (181, 181, 181),-2: (181, 181, 181),
          -1: (181, 181, 181), 0:(232, 232, 232),1: (154, 255, 154),
          2: (154, 255, 154), 3: (154, 255, 154),4: (0, 255, 0),
          5: (0, 255, 0), 6: (0, 255, 0), 7: (0, 255, 0)  }
colors.update( {i:(181, 181, 181)for i in range(-35,-7)} )



go = True
# go = False
# go是暂停用的....按空格暂停/继续
time = 0
num = 0
# time 是用来控制更新频率的
# 因为我的更改 现在time是虚设....
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            os._exit(0)
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                go = not go
    if go:
        time += 100
    if time >= 50:
        run_one()
        drow()
        num+=1
        pygame.display.set_caption("第%d轮"%(num))
        time = 0
    else:
        time+=0

    fclock.tick(fps)
                

 

posted @ 2020-10-12 23:24  ansver  阅读(242)  评论(0编辑  收藏  举报