本文共 1765 字,大约阅读时间需要 5 分钟。
五子棋实验报告
人工智能课程实验第一小组
成员:赖昌灏(组长黄黄徐
揭 赖斯 刘银一.实验题目
五子棋对弈程序
二.实验要求
要求有一个良好的界面,方便裁判把对方的下子填入棋盘相应的位置。先手为黑子,后手为白子。棋盘大小为15*15。
要求既支持先手、又支持后手的方式。比赛时通过抓阄决定先手还是后手。
如果黑子(先手方)下了禁手子,则后手方(白子)的程序必须输出提示黑子禁手,否则比赛继续,不能判黑子负。
三.算法设计分析:
1)数据的存储
五子棋的棋盘是15X15的,可以用一个二维数组来存储当前的棋盘状态。程序中用int board[15][15]来存储。其中用数值0表示人下过的棋子,用数值1表示电脑下过的棋子,用数值2表示还未被下过的棋子。
2)平局以及胜负的判断。
程序中使用了一个函数Judge()来进行判断,具体设计如下:
平局:
五子棋对战双方加起来最多下的棋子为15X15=225颗,所以当下过的总的棋子数为225且双方都没有赢的情况下,视为平局,此次对战结束。用一个bool变量tie来表示,置为true。
胜负:
(1)在这种15X15的棋盘中,任何一方能取胜的格局数总的为572,横竖方向总的有11*15*2=330种。两个对角方向总的有((1+10)*10/2*2+11)*2=242种,故总的有572种。
(2)在对战中,使用辅助的bool类型的三维数组来分别对人跟电脑的格局,即人的为ptable[15][15][572],电脑的为ctable[15][15][572]。初始值都设为true。另外用一个二维变量来存储双方能赢的格局。即int win[2][572].数组中没一项的初始值都为0.其中win[0][0…571]表示人能赢的格局,win[1][0…571]表示电脑能赢的格局。如果在对战中人的一方下了位置为m,n的子,则进行如下的操作。
for(i = 0 ; i<572; i++)
//对于鼠标所点的那个点转化成棋盘数组中某个具体的值后应该对跟这个点相关的赢法都加一
{
if(ptable[m][n][i] && win[0][i] != 8)
{
/*win[0][i] != 8(8只是一个标记而已,表明这个子的赢的格局还没被电脑封杀*/
win[0][i]++; //将人能赢的该格局的子数加1(当达到5时表示五子连珠了)
}
if(ctable[m][n][i])
//另一方面将电脑能赢的格局中与这个位置的子相关的相置为否,即与这点相关的赢法都被封杀了
{
ctable[m][n][i] = false;
win[1][i] = 8;
}
}
(3)要判断哪一方赢的话,只需分别遍历win[0][0…571],win[1][0…571]。如果其中有一项为5,则说明有一方胜了,另一方败了。
3)电脑的ai,即如何根据当前的棋局来决定要下的子
(1)一开始的时候,如果电脑先手,则下在棋盘中央的点,否则则下在位置为8,8的点上面。
(2)总体来说,电脑是通过给能下的每一个子赋权值,这个包括电脑自己与人的,然后分别选取权值最大的点,如果电脑方的权值更大,则选择这个点进攻,如果人方的权值更大,则选择下那个点防守。
(3)分别用cgrade[15][15],pgrade[15][15]来记录计算过程中电脑与人各个点的权值,当然只针对还没有被下过的点,然后分别用cgrade,pgrade来表示电脑与人的点中权值的最大值。
下面的代码只是一小部分,关于如何计算电脑一方的可下棋子的权值的:
for(i = 0 ; i<= 14; i++)
for(j=0 ; j<=14;j++)
{
ccgrade[i][j] = 0 ;
if( board[i][j]==2) //还没被下过
for(k=0 ; k <572 ; k++)
if(ctable[i][j][k]) //这个位置涉及的赢法还没被封杀
{
switch(win[1][k])
{
case 1: //该赢法格局中只有一个子
ccgrade[i][j] +=5;
break;
case 2:
ccgrade[i][j] +=50;
break;
case 3:
ccgrade[i][j] +=100;
转载地址:http://tmdnv.baihongyu.com/