在刚刚过去的719RT年度派对上,我们的活动任务是现场为RT课堂经典小游戏“太空大逃亡”写一个ai,作为主持人我现场没有参与编程,但在前期准备我也有试着写过一个,采取的是纯人工,下面分享一下思路:
首先我把决策分为两类,宏观和局部——宏观是指从整个屏幕来看哪里的陨石密度最低或者用其他方法来量化“最好生存”,以此作为大的前进方向;局部则是指当附近存在威胁较大的陨石就需要优先避让。总结而言就是,先处理近在眼前的危险,在周围环境压力相对较低时尝试向更为安全的区域移动。#判断当前box相对方位并在满足距离要求时记录is_near和b_density
if 0 <= myBox.rect.top - b.rect.bottom <= 25:
b_density[0] += b.rect.height * b.rect.width
if 0 <= b.rect.top - myBox.rect.bottom <= 25:
b_density[1] += b.rect.height * b.rect.width
if 0 <= myBox.rect.left - b.rect.right <= 20:
b_density[2] += b.rect.height * b.rect.width
if 0 <= b.rect.left - myBox.rect.right <= 20:
b_density[3] += b.rect.height * b.rect.width
if (0 <= b.rect.top - myBox.rect.bottom <= 30) and\
(b.rect.right+1 >= myBox.rect.left) and \
(myBox.rect.right+1 >= b.rect.left): #在飞船下方
is_near[0] = 1
if (0 <= myBox.rect.top - b.rect.bottom <= 30) and\
(b.rect.right+1 >= myBox.rect.left) and\
(myBox.rect.right+1 >= b.rect.left): #在飞船上方
is_near[1] = 1
if (0 <= b.rect.left - myBox.rect.right <= 30) and\
(b.rect.bottom+1 >= myBox.rect.top) and\
(myBox.rect.bottom+1 >= b.rect.top): #在飞船右方
is_near[2] = 1
if (0 <= myBox.rect.left - b.rect.right <= 30) and\
(b.rect.bottom+1 >= myBox.rect.top) and\
(myBox.rect.bottom+1 >= b.rect.top): #在飞船左方
is_near[3] = 1
以上是非常简单的代码,统计以飞船为中心将屏幕分割为四个区域的陨石多少来判断那个方向更安全(宏观),然后检测上下左右方向是否有威胁大即距离近的陨石(局部)
接下来则是具体决策飞船速度,大体分为几类:①四面被包围,此时需要尽量在原地抽搐等待陨石自己撞开,或者优先向相对更空的方向跑,两种我都有尝试,效果好像差不多?可能是我程序本身就太简陋的原因②三面被包围/相邻两个方向有陨石/一个方向有陨石,这三种情况都是朝空处跑,三面的就往空的那面,相邻两面的就往反方向的角跑,一面的就往反方向跑③相对的两面有陨石,尝试从侧向逃离④周围没有陨石,听从宏观决策往安全区块跑
以上几种情况如果遇到多个速度方向都可以走的情况,我就会选择与宏观决策方位更一致的。
#当靠近边界且有被附近box向边界挤压时,把边界方向视为有box进行脱离
if is_near[0] == 1 and myBox.rect.y <= 5:
is_near[1] = 1
if is_near[1] == 1 and myBox.rect.y + myBox.rect.height - SCREEN_SIZE[1] >= 5:
is_near[0] = 1
if is_near[2] == 1 and myBox.rect.x <= 5:
is_near[3] = 1
if is_near[3] == 1 and myBox.rect.x + myBox.rect.width - SCREEN_SIZE[0] >= 5:
is_near[2] = 1
#四周均无靠近的box,向周围box数最少的方向前进
if sum(is_near) == 0:
if b_density[0] > b_density[1]:
myBox.speed[1] = 1
else:
myBox.speed[1] = -1
if b_density[2] > b_density[3]:
myBox.speed[0] = 1
else:
myBox.speed[0] = -1
#四个方向都有box,通过不断反向试图停在原地
elif sum(is_near) == 4:
#myBox.speed[0] = -myBox.speed[0]
#myBox.speed[1] = -myBox.speed[1]
if b_density[0] > b_density[1]:
myBox.speed[1] = 1
else:
myBox.speed[1] = -1
if b_density[2] > b_density[3]:
myBox.speed[0] = 1
else:
myBox.speed[0] = -1
#三个方向有box,向空位走
elif sum(is_near) == 3:
if is_near[0] == 0:
myBox.speed[1] = 1
#myBox.speed[0] = -myBox.speed[0]
if b_density[2] > b_density[3]:
myBox.speed[0] = 1
else:
myBox.speed[0] = -1
elif is_near[1] == 0:
myBox.speed[1] = -1
#myBox.speed[0] = -myBox.speed[0]
if b_density[2] > b_density[3]:
myBox.speed[0] = 1
else:
myBox.speed[0] = -1
elif is_near[2] == 0:
myBox.speed[0] = 1
#myBox.speed[1] = -myBox.speed[1]
if b_density[0] > b_density[1]:
myBox.speed[1] = 1
else:
myBox.speed[1] = -1
elif is_near[3] == 0:
myBox.speed[0] = -1
#myBox.speed[1] = -myBox.speed[1]
if b_density[0] > b_density[1]:
myBox.speed[1] = 1
else:
myBox.speed[1] = -1
else:
#两个对向有box,在此方向不断反向试图静止,另一方向选择box数更少的区域
if is_near[0] == is_near[1] == 1:
if b_density[2] > b_density[3]:
myBox.speed[0] = 1
else:
myBox.speed[0] = -1
myBox.speed[1] = -myBox.speed[1]
elif is_near[2] == is_near[3] == 1:
if b_density[0] > b_density[1]:
myBox.speed[1] = 1
else:
myBox.speed[1] = -1
myBox.speed[0] = -myBox.speed[0]
#相邻方向或只有一个方向有box,直接对应反向
else:
if is_near[0] == 1:
myBox.speed[1] = -1
if is_near[1] == 1:
myBox.speed[1] = 1
if is_near[2] == 1:
myBox.speed[0] = -1
if is_near[3] == 1:
myBox.speed[0] = 1
同样是实现难度很低的代码,主要还是脑子里把规则想好。
我个人也有问deepseek要过代码,但并未拿回来仔细改,只是尝试运行了一下,就不专门贴出来了,本次活动中有其他同学与ai的合作更加紧密,这方面我还是期待他们的分享吧。
【是ai就撑过30秒】 https://www.bilibili.com/video/B ... 768b04148b197d89075这是以上程序的运行结果,反正比我人力强点hhhhhh
希望能继续和大家讨论这个ai如何继续进化,大佬们有想法还请在评论区指点指点
也希望能炸出来有参加活动的同学分享你们的程序!
|