基础项目框架是在我前面这个博客里开发的
1 决策树
决策树是一个基础的分类人工智能,听着挺高大上,实际上就是if-else双分支(嵌套)结构实现的分类,比如这就是一个简单的决策树
a = int(input('请输入一个整数:'))
if a % 2 == 0:
print('偶数')
else:
print('奇数')
这样的程序想必学到学习编写人工智能这个级别都随随便便写一堆吧,所以不要被高大上的名字耽误,决策树其实很简单
2 编写程序
2.1 设计本程序决策树框架
本程序是一个比较基础的程序,基本上人脑想一下就能想到大体框架,所以有这一步,比较复杂的程序就直接编一个决策树深度,然后通过计算相关性排序就开始调参了
我们想一下,在玩这个游戏时,我们看的就是最近的一个障碍与自己纵坐标的差以及最近这个障碍的类型(上、下),所以判断流程图大体是这样
这样的话,我们需要实现两个功能,获取最近的障碍的数据,以及实现这个决策树,养成一个好习惯,特定功能的程序封装在函数里,这样便于修改
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (5, 30)
import pgzrun
import random
WIDTH = 400
HEIGHT = 300
bird = Actor('bird', (50, 150))
pillar = [
lambda: Actor('pillar1', (500, -150)),
lambda: Actor('pillar2', (500, 450))
]
pillars = [random.choice(pillar)()]
speed = 0
begin = 0
score = 0
def fly():
global speed, begin, pillars, score
speed = 35
if begin == 2:
score = 0
del pillars
pillars = [random.choice(pillar)()]
begin = 1
def get(): # 获取最近的障碍数据
if pillars[0].x > bird.x:
i = 0
else:
i = 1
data = {
'pillar': int(pillars[i].image[-1]),
'y': pillars[i].y
}
return data
c1 = 200
c2 = 200
# 随意编的参数
def judge(): # 决策树
data = get()
p = data['pillar']
y = abs(data['y']-bird.y)
if p == 1:
if y > c1:
fly()
else:
if y > c2:
fly()
def draw():
screen.blit('background', (0, 0))
bird.draw()
for pl in pillars:
pl.draw()
screen.draw.text(str(score), (0, 0), color=(0, 0, 0))
def on_mouse_down():
fly()
def on_key_down():
fly()
def update():
global speed, pillars, begin, score
if begin == 1:
bird.y -= speed // 9
if bird.top < 0:
bird.top = 0
if bird.bottom > 300:
begin = 2
speed -= 1
if pillars[-1].x <= 250:
pillars.append(random.choice(pillar)())
for p in pillars:
p.x -= 5
if p.right <= 0:
pillars.remove(p)
score += 1
if p.colliderect(bird):
begin = 2
judge() # 调用
pgzrun.go()
2.2 调参
接下来就是人工智能训练中耗时间最长,最枯燥的部分——调参了,这一次就先手动调参,以后再讲怎么自动调参吧(主要是逻辑简单,考虑怎么自动调参的工夫手动已经调完了)
手动调参很简单粗暴,就是把设的参数(本程序为c1、c2)一遍遍调整,直到能实现目的
2.3 结果
这是最终程序
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (5, 30)
import pgzrun
import random
WIDTH = 400
HEIGHT = 300
bird = Actor('bird', (50, 150))
pillar = [
lambda: Actor('pillar1', (500, -150)),
lambda: Actor('pillar2', (500, 450))
]
pillars = [random.choice(pillar)()]
speed = 0
begin = 0
score = 0
def fly():
global speed, begin, pillars, score
speed = 35
if begin == 2:
score = 0
del pillars
pillars = [random.choice(pillar)()]
begin = 1
def get(): # 获取最近的障碍数据
if pillars[0].x > bird.x:
i = 0
else:
i = 1
data = {
'pillar': int(pillars[i].image[-1]),
'y': pillars[i].y
}
return data
c1 = 370
c2 = 310
def judge(): # 决策树
data = get()
p = data['pillar']
y = abs(data['y']-bird.y)
if p == 1:
if y > c1:
fly()
else:
if y < c2:
fly()
def draw():
screen.blit('background', (0, 0))
bird.draw()
for pl in pillars:
pl.draw()
screen.draw.text(str(score), (0, 0), color=(0, 0, 0))
def on_mouse_down():
fly()
def on_key_down():
fly()
def update():
global speed, pillars, begin, score
if begin == 1:
bird.y -= speed // 9
if bird.top < 0:
bird.top = 0
if bird.bottom > 300:
begin = 2
speed -= 1
if pillars[-1].x <= 250:
pillars.append(random.choice(pillar)())
for p in pillars:
p.x -= 5
if p.right <= 0:
pillars.remove(p)
score += 1
if p.colliderect(bird):
begin = 2
judge()
pgzrun.go()
参数选少了,还要考虑最近一个柱子的距离,下一个柱子的类型等,导致效果不大好,但能蹦跶几下,只是希望能抛砖引玉,让大家明白决策树,再多就复杂了