书:游戏开发中的人工智能(P314):遗传算法的初步认识以及代码实现

来源:互联网 发布:广州淘宝模特招聘 编辑:程序博客网 时间:2024/04/29 14:40

1.算法的来源

我感觉:遗传的来源就是达尔文的物种起源,由于适者生存这一准则。粗略来说,生存的好的物种就有好的基因,生存的不好没有好的基因,直接死亡,好的基因传给下一代,下一代就能更好的生存,因为对环境不适应的逐渐死亡了。再此过程中,还有基因突变,基因突变也许会使物种更适应环境,也许不会,不会的又会死亡。这样,逐渐形成对环境非常适应的物种。
逐渐形成对环境非常适应的物种
意味着
这个算法是可以用于找到最优解。

那么其中,好的基因是如何传给下一代的呢?
通过杂交。就是从父本和母本各取一个染色体(包含所有基因)。通过这样方式,有可能获取到父本和母本的最佳基因。


2.用代码实现该算法

用 植物生命演化 演示这一过程。


1:花生长的最高代表生长的最好。
2:花有六种属性(每个属性代表一个基因),

分别是:temperature,

water,

sunlight,
nutrition,
beneficalInsect,
harmfulInsect.
3.当前环境也有这6个属性,如果某花的属性值离环境的属性值越近,那么就应该生长的越高,代表生长的越好。


4.生长过程为
第一代初始化:初始化花的属性,相当于基因
适合度分等:根据花的属性与环境的差距,可以知道花生长的等级情况,画出花的最终生长图。
选择:选出最好的两朵花
演化:交配,这里,我们就是从父本那里取3个基因,再从母本那里取另外3个基因。最后,生出同等数量的花,其中不要忘了还要进行基因突变,处理过程的每个基因有5%增加或者减少5。
重复适合度分等至演化的过程。


当交配生殖了几代之后,花将会越来越高,表示生长的越来越好,也就是其属性值越来越接近环境值。

这样就找到了最优解。

请先稍稍理解一下代码里的图:如下图所示




代码运行结果:

有两份事例子,第一个是每次都选出最优秀的作为父母本,最后经过很多的代的繁殖后,所有的花生长状况变好,也可以说是找到最优解。

请看下面两张图:


出现最佳:



第二个例子,也只有两张图,第一张是我选择了自选父母本,我选择了长得最差的两个花作为父母本。



3.该算法在游戏中的利用

理论上讲:遗传算法是用于找到问题的最优解的算法。那么所有此类问题都可以用遗传算法,但并不是那么方便。比如:寻路问题可以用,但是通常不用。因为有更适合的A*算法。
从书中介绍的一个例子来看,是逐渐形成一个非常智能的怪物。这个怪物不再只是遇见治疗是会上去打,遇见战士的就会逃。
它会根据自己的经验来判断,遇见治疗是打还是跑,遇见战士是打还是跑,这种经验是来自于父母双亲的遗传。
为了便于说明,我们要先找到适合度,我现在认为的适合度,就是适应环境的能力。
一只怪,如果攻击玩家的次数越多,那么我们认为它适合度越高。


对比一下,即可知道利用了遗传算法的怪物是有利于游戏的进行。
没有遗传特性的怪:遇见治疗就打,遇见战士就跑。但是实际游戏的进程是:治疗可以轻松杀死怪,但是战士却很难杀死。大概可以理解为,治疗输出低,但可以通过加血延长作战时间。这些事从一开始就要游戏设计者考虑到是非常辛苦的事。更重要的事,游戏还在不断的升级,也许开始的时候游戏的治疗很不适合作战,确实打不过怪物,但是升级过,治疗轻松打败怪物。但是怪物还是见着治疗打。这样这个怪物,就很失败了,完全不能带给玩家挑战性,成就感,只会不断的送经验。


有遗传特性的怪物:
我假设的情况是:
开始第一代,所有的怪对玩家将会随机做出反应,一个时间段后,会从其中选出适合度最高,依其为父母,重生所有怪物,其中还要加入突变基因,再过一段时间后,又重新选出适合度最高的,重生所有怪。逐渐,最能抵抗玩家的怪物就产生了。
当游戏升级时,也只需重新生成随机的属性的怪物,再进行一次进化即可。这样,游戏设计者轻松了很多。

遗传算法在游戏中的利用,我就理解到此了。
我个人觉得非常爽!!!

4.全部源代码


#include <iostream>#include "math.h"#define MaxFlowers 21#define MaxGrowingHeight 75struct gene{int temperature;int water;int sunlight;int nutrient;int beneficalInsect;int harmfulInsect;};struct flower{gene Gene;int Height;};struct world{gene Environment; };flower Flower[MaxFlowers];//虽然有定义了21个,但是只想用1到20号。共20朵world World;int generations=1;flower mom;flower dad;void getdadmon(){int dadCount=1;for (int i=2;i<MaxFlowers;i++){if (Flower[i].Height>=Flower[dadCount].Height){dadCount=i;}}int momCount=1;for (int i=2;i<MaxFlowers;i++){if ((Flower[i].Height>=Flower[momCount].Height)&&i!=dadCount){momCount=i;}}dad=Flower[dadCount];mom=Flower[momCount];printf("最佳父本和母本应为:第 %d 花和第 %d 花",dadCount,momCount);}void mutate(){int mutateion;for (int i=1;i<MaxFlowers;i++){if (rand()%3==0){mutateion=Flower[i].Gene.beneficalInsect+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.beneficalInsect=mutateion;}}if (rand()%3==0){mutateion=Flower[i].Gene.harmfulInsect+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.harmfulInsect=mutateion;}}if (rand()%3==0){mutateion=Flower[i].Gene.nutrient+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.nutrient=mutateion;}}if (rand()%3==0){mutateion=Flower[i].Gene.sunlight+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.sunlight=mutateion;}}if (rand()%3==0){mutateion=Flower[i].Gene.temperature+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.temperature=mutateion;}}if (rand()%3==0){mutateion=Flower[i].Gene.water+rand()%20-rand()%20;if (mutateion<=75&&mutateion>=0){Flower[i].Gene.water=mutateion;}}}}void mating(flower mom,flower dad){for (int i=1;i<MaxFlowers;i++){Flower[i].Gene.beneficalInsect=mom.Gene.beneficalInsect;Flower[i].Gene.nutrient=mom.Gene.nutrient;Flower[i].Gene.sunlight=mom.Gene.sunlight;Flower[i].Gene.harmfulInsect=dad.Gene.harmfulInsect;Flower[i].Gene.water=dad.Gene.water;Flower[i].Gene.temperature=dad.Gene.temperature;}mutate();}//初始化第一代花和世界的环境的属性int getAbsolute(int result){if (result<0){result=-result;}return result;}void getHeight(){for (int i=1;i<MaxFlowers;i++){//与世界的属性的差值的绝对值,再被75减,6个加起来再被6除。求平均值Flower[i].Height=((75-getAbsolute((Flower[i].Gene.harmfulInsect-World.Environment.harmfulInsect)))+(75-getAbsolute((Flower[i].Gene.sunlight-World.Environment.sunlight)))+(75-getAbsolute((Flower[i].Gene.nutrient-World.Environment.nutrient)))+(75-getAbsolute((Flower[i].Gene.water-World.Environment.water)))+(75-getAbsolute((Flower[i].Gene.temperature-World.Environment.temperature)))+(75-getAbsolute((Flower[i].Gene.beneficalInsect-World.Environment.beneficalInsect))))/6;}}void Init(){World.Environment.beneficalInsect=rand()%75+1;World.Environment.harmfulInsect=rand()%75+1;World.Environment.nutrient=rand()%75+1;World.Environment.sunlight=rand()%75+1;World.Environment.temperature=rand()%75+1;World.Environment.water=rand()%75+1;for (int i=1;i<MaxFlowers;i++){Flower[i].Gene.beneficalInsect=rand()%75+1;Flower[i].Gene.harmfulInsect=rand()%75+1;Flower[i].Gene.nutrient=rand()%75+1;Flower[i].Gene.sunlight=rand()%75+1;Flower[i].Gene.temperature=rand()%75+1;Flower[i].Gene.water=rand()%75+1;}}void inputGrowth() {printf("………………第%d代……………………",generations++);for (int j=1;j<MaxFlowers;j++){printf("\n第%d号花,营:%d 温:%d 益:%d 害:%d 阳:%d 水:%d   \n",j,Flower[j].Gene.nutrient,Flower[j].Gene.temperature,Flower[j].Gene.beneficalInsect,Flower[j].Gene.harmfulInsect,Flower[j].Gene.sunlight,Flower[j].Gene.water);for (int i=0;i<Flower[j].Height;i++){printf("-");}printf("*");int blank =Flower[j].Height;while ((75-blank)>0){printf(" ");++blank;}printf("|");}printf("\n世界的环境,营:%d 温:%d 益:%d 害:%d 阳:%d 水:%d \n",World.Environment.nutrient,World.Environment.temperature,World.Environment.beneficalInsect,World.Environment.harmfulInsect,World.Environment.sunlight,World.Environment.water);}void main(){int growthModel;printf("选择生长模式:\n1.自选 父母本。\n2.机选选择最佳 父母本\n");scanf("%d",&growthModel);int monFromUser=0,dadFromUser=0;Init();while(1){getHeight();inputGrowth();getdadmon();if (growthModel==2){system("pause");}else if (growthModel==1){printf("\n请选择父本和母本:\n");scanf("%d %d",&monFromUser,&dadFromUser);printf("\n您选择了第%d号花和第%号花作为父母\n",monFromUser,dadFromUser);mom=Flower[monFromUser];dad=Flower[dadFromUser];}mating(mom,dad);}}




遗传算法在游戏中的利用,我就理解到此了。
我个人觉得非常爽!!!
原创粉丝点击