游戏编程中的人工智能技术-遗传算法入门(三)
2016-06-01 07:17
886 查看
先请教大家一个问题,为什么我的遗传算法入门(一)一直处于“待审核”状态?
好,言归正传,继续研究代码。先看看CBobsMap类的定义。
在AI算法的使用中,最关键的是什么?是算法的理论吗?我感觉最关键的应该是如何将算法应用到实际中去。在本游戏中,如何构造一个算法的具体实现,最为关键。
接下来研究TestRoute()函数。
这个函数的作用是根据实际游戏情境设计遗传算法的染色体,并计算他的适应度函数。
一句一句来。
Bob开始走路了!这个是Bob的初始位置。
那么在本程序中,染色体的基因个数为多少呢?
在Define.h中有定义:
可以通过调试看到实际染色体长度。在CgaBob类中,函数UpdateFitnessScores()中如下所示
可以看到vecDirections的长度到0x22结束,对应十进制就是34。
以上是解释染色体的长度为多少。
接下来继续分析程序。
到了其中的一个基因了。一共有四个case, case 0, case 1, case 2, case 3。即00,01,10,11。为基因的种类,分别表示向北走一步,向南走一步,向东走一步,向西走一步。vecPath[dir]储存了这个基因。即vecPath[dir]=00,01,10,11.
这个是编程思想的关键,以后再实际操作中,首先要考虑如何来根据游戏来构造染色体?本例中,因为Bob要走迷宫,那么实际操作是向北走一步,向南走一步,向东走一步,向西走一步,则可以用00.01.10.11来表示每个操作。
如果不是上述两种情况,则Bob可往北走一步,则Bob的位置变化一格。即posY -= 1;再break
同上。
适应度函数的计算,适应值为Bob离迷宫出口的距离值,这个程序中,没有用实际距离,而只是将x坐标和y坐标简单的相加。为了取适应度的最大值,当然要return 1/(double)(DiffX+DiffY+1);啦。
可以通过调试看到实际染色体长度。在CgaBob类中,函数UpdateFitnessScores()中如下所示
好,言归正传,继续研究代码。先看看CBobsMap类的定义。
class CBobsMap { private: //storage for the map static const int map[MAP_HEIGHT][MAP_WIDTH]; //设计一个数组,用来构造地图 static const int m_iMapWidth;//地图的宽度 static const int m_iMapHeight;//地图的高度 //index into the array which is the start point static const int m_iStartX; //起始点的x坐标 static const int m_iStartY; //起始点的y坐标 //and the finish point static const int m_iEndX; //终止点的x坐标 static const int m_iEndY; //终止点的y坐标 public: //we can use this array as Bobs memory if rqd int memory[MAP_HEIGHT][MAP_WIDTH]; //记录下Bob走过的路线,重新定义一个地图数组 CBobsMap() { ResetMemory(); //路线记忆清零 } //takes a string of directions and see's how far Bob //can get. Returns a fitness score proportional to the //distance reached from the exit. double TestRoute(const vector<int> &vecPath, CBobsMap &memory);//走迷宫了!该如何操作? //given a surface to draw on this function uses the windows GDI //to display the map. void Render(const int cxClient, const int cyClient, HDC surface); //draws whatever path may be stored in the memory void MemoryRender(const int cxClient, const int cyClient, HDC surface); void ResetMemory(); };
在AI算法的使用中,最关键的是什么?是算法的理论吗?我感觉最关键的应该是如何将算法应用到实际中去。在本游戏中,如何构造一个算法的具体实现,最为关键。
接下来研究TestRoute()函数。
double CBobsMap::TestRoute(const vector<int> &vecPath, CBobsMap &Bobs) { int posX = m_iStartX; int posY = m_iStartY; for (int dir=0; dir<vecPath.size(); ++dir) { int NextDir = vecPath[dir]; switch(vecPath[dir]) { case 0: //North //check within bounds and that we can move if ( ((posY-1) < 0 ) || (map[posY-1][posX] == 1) ) { break; } else { posY -= 1; } break; case 1: //South //check within bounds and that we can move if ( ((posY+1) >= m_iMapHeight) || (map[posY+1][posX] == 1) ) { break; } else { posY += 1; } break; case 2: //East //check within bounds and that we can move if ( ((posX+1) >= m_iMapWidth ) || (map[posY][posX+1] == 1) ) { break; } else { posX += 1; } break; case 3: //West //check within bounds and that we can move if ( ((posX-1) < 0 ) || (map[posY][posX-1] == 1) ) { break; } else { posX -= 1; } break; }//end switch //mark the route in the memory array Bobs.memory[posY][posX] = 1; }//next direction //now we know the finish point of Bobs journey, let's assign //a fitness score which is proportional to his distance from //the exit int DiffX = abs(posX - m_iEndX); int DiffY = abs(posY - m_iEndY); //we add the one to ensure we never divide by zero. Therefore //a solution has been found when this return value = 1 return 1/(double)(DiffX+DiffY+1); }
这个函数的作用是根据实际游戏情境设计遗传算法的染色体,并计算他的适应度函数。
一句一句来。
double CBobsMap::TestRoute(const vector<int> &vecPath, CBobsMap &Bobs)TestRoute为CBobsMap类中的函数,参数为const vector<int> &vecPath,表示一个int型向量的首地址,其实也就是表示这个向量;CBobsMap &Bobs,表示一个CBobsMap类的首地址,其实也就是定义了一个CBobsMap的实例,叫做Bobs。
int posX = m_iStartX; int posY = m_iStartY;
Bob开始走路了!这个是Bob的初始位置。
for (int dir=0; dir<vecPath.size(); ++dir)这个是遍历一条染色体内的整个基因。vecPath.size()表示染色体的长度,即基因的个数。
那么在本程序中,染色体的基因个数为多少呢?
在Define.h中有定义:
<pre name="code" class="cpp">#define WINDOW_WIDTH 450 #define WINDOW_HEIGHT 300 #define MAP_WIDTH 15 #define MAP_HEIGHT 10 #define CROSSOVER_RATE 0.7 #define MUTATION_RATE 0.001 #define POP_SIZE 140 #define CHROMO_LENGTH 30 #define GENE_LENGTH 2 #endif
可以通过调试看到实际染色体长度。在CgaBob类中,函数UpdateFitnessScores()中如下所示
void CgaBob::UpdateFitnessScores() { m_iFittestGenome = 0; m_dBestFitnessScore = 0; m_dTotalFitnessScore = 0; CBobsMap TempMemory; //update the fitness scores and keep a check on fittest so far for (int i=0; i<m_iPopSize; ++i) //这个是种群的数量,不是染色体的长度 { //decode each genomes chromosome into a vector of directions vector<int> vecDirections = Decode(m_vecGenomes[i].vecBits);这个就是染色体 //get it's fitness score m_vecGenomes[i].dFitness = m_BobsMap.TestRoute(vecDirections, TempMemory);//TestRoute的第一个向量参数,即表示染色体 //update total m_dTotalFitnessScore += m_vecGenomes[i].dFitness; //if this is the fittest genome found so far, store results if (m_vecGenomes[i].dFitness > m_dBestFitnessScore) { m_dBestFitnessScore = m_vecGenomes[i].dFitness; m_iFittestGenome = i; m_BobsBrain = TempMemory; //Has Bob found the exit? if (m_vecGenomes[i].dFitness == 1) { //is so, stop the run float a = m_vecGenomes[i].dFitness; vector<int> b = m_vecGenomes[i].vecBits; m_bBusy = false; } } TempMemory.ResetMemory(); }//next genome }可以通过断点调试观察vecDirections的长度。
可以看到vecDirections的长度到0x22结束,对应十进制就是34。
以上是解释染色体的长度为多少。
接下来继续分析程序。
for (int dir=0; dir<vecPath.size(); ++dir) { int NextDir = vecPath[dir]; switch(vecPath[dir]) { case 0: //North //check within bounds and that we can move if ( ((posY-1) < 0 ) || (map[posY-1][posX] == 1) ) { break; }
到了其中的一个基因了。一共有四个case, case 0, case 1, case 2, case 3。即00,01,10,11。为基因的种类,分别表示向北走一步,向南走一步,向东走一步,向西走一步。vecPath[dir]储存了这个基因。即vecPath[dir]=00,01,10,11.
这个是编程思想的关键,以后再实际操作中,首先要考虑如何来根据游戏来构造染色体?本例中,因为Bob要走迷宫,那么实际操作是向北走一步,向南走一步,向东走一步,向西走一步,则可以用00.01.10.11来表示每个操作。
if ( ((posY-1) < 0 ) || (map[posY-1][posX] == 1) )posY-1<0表示已经到了迷宫的北墙了,所以不能再往北走了,map[posY-1][posX] == 1表示往北走一步就撞到障碍物了,当然也就无法实现往北走一步的操作了。因此两种情况Bob的位置不会发生变化,直接break.
如果不是上述两种情况,则Bob可往北走一步,则Bob的位置变化一格。即posY -= 1;再break
case 1: //South //check within bounds and that we can move if ( ((posY+1) >= m_iMapHeight) || (map[posY+1][posX] == 1) ) { break; } else { posY += 1; } break; case 2: //East //check within bounds and that we can move if ( ((posX+1) >= m_iMapWidth ) || (map[posY][posX+1] == 1) ) { break; } else { posX += 1; } break; case 3: //West //check within bounds and that we can move if ( ((posX-1) < 0 ) || (map[posY][posX-1] == 1) ) { break; } else { posX -= 1; } break; }//end switch
同上。
Bobs.memory[posY][posX] = 1;无论走还是没走,Bob的记忆地图里存储了操作后的位置,这个是用来画图用的。
int DiffX = abs(posX - m_iEndX); int DiffY = abs(posY - m_iEndY); //we add the one to ensure we never divide by zero. Therefore //a solution has been found when this return value = 1 return 1/(double)(DiffX+DiffY+1);
适应度函数的计算,适应值为Bob离迷宫出口的距离值,这个程序中,没有用实际距离,而只是将x坐标和y坐标简单的相加。为了取适应度的最大值,当然要return 1/(double)(DiffX+DiffY+1);啦。
可以通过调试看到实际染色体长度。在CgaBob类中,函数UpdateFitnessScores()中如下所示
相关文章推荐
- Hard-题目47:336. Palindrome Pairs
- 区间动规--区分两道题--【cqoi】涂色&【cdoi】string painter
- 游戏编程中的人工智能技术-遗传算法入门(二)
- RAII(资源创建即释放)
- root.sh Fails to Start HAIP as Default Gateway is Configured for Private Network VLAN (文档 ID 1366211
- HDU 2653 - Waiting ten thousand years for Love
- LeetCode 70. Climbing Stairs
- 3.INSTALL_FAILED_UPDATE_INCOMPATIBLE
- main Runloop
- 游戏编程中的人工智能技术-第三章:遗传算法入门(一)
- Seaborn-PairGrid
- grails指定端口运行工程
- [LeetCode]problem 70. Climbing Stairs
- HDOJ--Fibonacci Again
- Middle-题目122:220. Contains Duplicate III
- 1079. Total Sales of Supply Chain (25)
- leetcode 217. Contains Duplicate
- 1282 - Leading and Trailing ---LightOj1282(快速幂 + 数学)
- 【BZOJ1664】[Usaco2006 Open]County Fair Events 参加节日庆祝【线段覆盖】【贪心】
- Palindrome Pairs