软件综合实习报告五子棋游戏的实现.docx
- 文档编号:5449716
- 上传时间:2022-12-16
- 格式:DOCX
- 页数:37
- 大小:1.09MB
软件综合实习报告五子棋游戏的实现.docx
《软件综合实习报告五子棋游戏的实现.docx》由会员分享,可在线阅读,更多相关《软件综合实习报告五子棋游戏的实现.docx(37页珍藏版)》请在冰豆网上搜索。
软件综合实习报告五子棋游戏的实现
软件综合实习报告
题目:
五子棋人机博弈游戏
院(系):
计算机学院
专业:
计算机科学与技术
姓名:
杨祺鹏
班级学号:
191072-0320071000566
指导教师:
王改芳
2010年9月18日
目录
一.系统需求分析与总体设计
1.需求分析
1问题描述
2数据流程图
2.总体设计
1开发背景
2开发语言
3开发平台和运行平台
4总体功能设计
二.详细设计与系统实现
1.类和类的方法设计
1类的设计
2类的方法设计
2.算法描述
三.系统测试
1.功能测试
2.性能测试
四.总结
1.系统仍存在的不足
2.结论和体会
一.系统需求分析与总体设计
1.需求分析
1问题描述
题目:
五子棋人机博弈游戏
题目要求:
实现五子棋游戏的人机博弈。
要求:
友好的人机图形化界面、方便的操作方式;自动判断输、赢或平;可选择黑白;可悔棋;可以基于人工智能方面的知识进行设计,如:
启发式搜索、搜索函数的设置、α_β算法、知识的表示及知识库,推理机等。
五子棋简介:
五子棋是起源于中国古代的传统黑白棋种之一。
顾名思义,只要连成五子即可获得胜利。
听上去好像很简单,但是不用技巧好似很难获胜的,这其中就有“活三”,“冲三”等等专业名词,这些我会在后续的程序中进行介绍。
五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。
五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为人民群众所喜闻乐见。
通过问题的描述,初步分析可得出此软件应具有以下的功能:
1.友好的界面,方面的操作方式——》可以快速开始游戏,功能明确而且界面明朗
2.自动判断输赢——》计算机可以根据棋子的状态判断胜负情况
3.可选择黑白——》可以先手下棋和后手下棋
4.可悔棋——》具有悔棋功能
5.计算机AI——》计算机需要具有一定的AI,需要AI攻守兼备
2数据流程图
数据流动很少,主要是在算法内部进行计算,实际进行交互的数据是没有的。
要求开始游戏落子,33禁手
棋子坐标
玩家落子
取最佳位置并落子(若不分胜负)
再来一盘胜负已分
2.总体设计
1开发背景
软件工程综合实习,因为我对算法很有兴趣,就决定通过这个程序学习一下。
2语言选择
使用C#平台在设计人机界面时更人性化,画图工具也更为简洁易用。
3开发环境及运行环境
开发环境:
操作系统名称MicrosoftWindows7旗舰版
版本6.1.7600版本7600
处理器AMDTurion(tm)X2Dual-CoreMobileRM-72,2100Mhz,
物理内存(RAM)3.00GB
开发平台:
MicrosoftVisualStudio2008专业版-简体中文MicrosoftVisualC#2008
运行平台:
Intel®Pentium®2及以上处理器,32M以上内存,4G以上硬盘
Microsoft®Windows™9X/NT操作系统
800*600或以上的屏幕分辨率
Net.framework2.0及以上版本
4具体功能设计
主要函数:
1.画棋子
2.画棋盘
3.先手判断
4.胜负判断
5.计算机AI算法(权值赋值,权值计算,找最大权值)
界面设计:
1.快速开始游戏
2.先手选择
3.悔棋,认输,电脑提示
4.棋子的坐标显示(计算电脑提示的附加功能)
5.帮助
这几个模块的重点是计算机AI算法的设计。
在参阅了很多资料以后,我发现解决五子棋问题的算法非常之多,遗传算法,α—β剪枝算法等等,这些算法的特点是对后续步骤进行无数次的推演并一一评分,最后去评分最高的一种方案的第一步,在下完一子之后再进行算法计算,虽然AI非常聪明但是计算繁琐且计算时间其长无比。
在网上发现的算法有更多的程序员是采用了权值计算的方法,具体来说就是根据每种情况每种可能对每个点都赋不同的权值,AI在判断应该进攻还是应该防守就是依靠权值的大小,权值最大的位置放棋子,采用这种方法虽然笨是笨了些,但是计算速度快,尤其是在棋盘比较小的时候(15*15棋盘),而且在对比中发现这种AI也很聪明。
在速度和计算精度之间权衡之后,我准备选择计算权值的方法来做,如果时间仍有富裕的话再使用别的算法来计算并进行对比。
二.详细设计与系统实现
1.类和类的方法设计
1类的设计(后面的方法设计也遵从这个顺序逐个进行详细注释)
棋盘类Chessboard
棋盘类主要实现对棋盘棋子,以及电脑和人下棋的显示,对虚拟棋盘的定义,对下棋路径的堆栈的初始化,对棋局的初始化。
棋子类Stone
棋子类主要实现对棋子的画图操作。
计算机类Computer
计算机类是本程序的核心模块,主要实现计算机对每个棋子每个位置的权值赋值,对每个棋盘位置的权值计算,求最大权值。
规则类Rule
规则类主要实现对胜负平局的判断,对黑棋禁手的判断,对每个方向上的连子数的计算,对棋局判断是依据连子数计算的。
主函数类frmMain
主函数主要是对界面上每个按键的功能进行实现,另实现对鼠标的move和click事件的定义,获取鼠标的坐标。
2类的方法的具体实现
1.Chessboard类中方法的实现
一.Chessboard中的变量定义
所谓的在棋盘上下棋,其实就是在相应坐标进行绘图,实际是不存在棋盘的,这里我定义一个15,15的二维数组来表示虚拟的棋盘进行下棋,其他见程序注释。
publicint[,]arrchessboard=newint[15,15];
//arrchessboard为棋盘情况数组,虚拟棋盘的定义,arrchessboard[i,j]=2表示此处无子arrchessboard[i,j]=0表示此处为黑子,arrchessboard[i,j]=1表示此处为白子
privateGraphicsmg;//绘制的对象
publicStonestone;//棋子对象
publicComputercomputer;//电脑对象
privateboolstoneflag=true;//判断当前棋子是黑(true)是白(false)
privateboolmplayfirstflag=false;//判断先手玩家(是电脑(true)还人(false),先手下黑棋)
privateStackmStarckHistory=newStack();//历史记录堆栈
二.Chessboard中对棋盘和棋子的绘制
对棋子和棋盘的绘图要用到system.draw这个系统自带的画图类,我使用的方式是先读取文件流中的文件,然后在每次画图的时候就不用再次读取了,直接可以进行绘图,这样处理速度比较快。
详细见注释。
publicvoidDraw()
{//从资源中获取,读取棋盘图像,就是在当前项目中读取文件
System.Reflection.AssemblythisExe;
thisExe=System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Streamfile=thisExe.GetManifestResourceStream("FiveStones.chessboard.gif");//棋盘文件
ImageimgChessboard=System.Drawing.Image.FromStream(file);//棋盘图片大小*600像素,每个棋子的点的坐标,个棋子,个空,两边线留空
file.Close();
mg.DrawImage(imgChessboard,0,0,imgChessboard.Width,imgChessboard.Height);
//绘制棋子
for(inti=0;i<15;i++)
{
for(intj=0;j<15;j++)
{
if(arrchessboard[i,j]==0)//对棋盘上的点进行判断后,根据虚拟数组的值来判断绘制哪一种棋子
{
stone.DrawStone(i,j,true);//Stone里面具体的绘制方法
}
if(arrchessboard[i,j]==1)
{
stone.DrawStone(i,j,false);
}
}
}
}
三.Chessboard中人下棋和电脑下棋
就是获取下棋的坐标,然后在该坐标进行相应的绘图,然后把该点的虚拟棋盘置成2,表示已经下过棋了。
publicvoidPersonDownStone(intx,inty)
{
if(x<600&&y<600)//取下棋点
{
intm=(int)Math.Floor((double)x/40);//求浮点数的“地板数”,就是求小于等于该点浮点数的整数
intn=(int)Math.Floor((double)y/40);
if(!
Rule.IsExist(m,n,arrchessboard))//如果这个位置没有子,则下子
{
DownStone(m,n);//人下子
ComputerDownStone();//电脑下子
}
}
}
privatevoidComputerDownStone()
{
intm,n,count=0;//count是计数器,每下一子就加1
do
{
computer.Down(arrchessboard);
m=computer.X;
n=computer.Y;
count++;
if(count>100)//如果下一百个子还不分胜负,就直接异常退出
{
MessageBox.Show("异常!
");
Start();
return;
}
}
while(Rule.IsExist(m,n,arrchessboard));//当判断该点没有子的时候下子
DownStone(m,n);
}
四.Chessboard对棋局的初始化
把初始化贴上来的目的是为了让每次下棋的流程更明显,构造对象啊,还有清空堆栈呀,这些看似很简单,但是其中的顺序是不可颠倒的,详细见注释。
privatevoidInitialization()//棋盘初始化
{
stoneflag=true;//置当前要走的棋为黑棋(黑棋先走)
for(inti=0;i<15;i++)
{
for(intj=0;j<15;j++)
{
arrchessboard[i,j]=2;//把棋盘所有位置置为空(未下子)
}
}
mStarckHistory.Clear();//清空历史记录堆栈
stone=newStone(mg);//构造棋子对象
}
privatevoidStart()//这个才是初始化函数
{
Initialization();
computer=newComputer(mplayfirstflag);//构造电脑对象
Draw();//画棋盘
if(mplayfirstflag)//如果是电脑先手的话就电脑下棋,否则等待
{
ComputerDownStone();
}
}
五.Chessboard中每下一子都要进行的处理做法,更改虚拟棋盘的数值,对禁手进行判断,将棋子坐标压入堆栈,下棋完成后交换下棋。
这个过程显示了下棋的步骤,在下棋之后,对虚拟棋盘也就是二维数组进行赋值,然后把该点压入堆栈,然后对黑棋是否禁手进行判断,这里用到了Rule传过来的值,详细见注释。
privatevoidDownStone(intm,intn)
{
stone.DrawStone(m,n,stoneflag);//下棋
if(stoneflag)//记录情况
{
arrchessboard[m,n]=0;//根据黑白标记对虚拟棋盘数组进行赋值
}
else
{
arrchessboard[m,n]=1;
}
if(stoneflag)//记录历史记录压入堆栈
{//压入堆栈的是棋子颜色和坐标
mStarckHistory.Push("黑:
"+m.ToString()+","+n.ToString());
}
else
{
mStarckHistory.Push("白:
"+m.ToString()+","+n.ToString());
}
if(Rule.Result(m,n,arrchessboard)<6)//判断结果,这个要调用Rule中的方法
{
switch(Rule.Result(m,n,arrchessboard))//禁手失败直接判黑棋负,重新开始
{
case1:
MessageBox.Show("黑棋双三禁手失败!
");
break;
case2:
MessageBox.Show("黑棋双四禁手失败!
");
break;
case3:
MessageBox.Show("黑棋长连禁手失败!
");
break;
case4:
if(stoneflag)
{
MessageBox.Show("黑棋胜利!
");
}
else
{
MessageBox.Show("白棋胜利!
");
}
break;
case5:
MessageBox.Show("平局!
");
break;
}
Start();//重新开始!
return;
}
else
{
stoneflag=!
stoneflag;//交换当前棋子颜色
}
}
2.Stone类中方法的实现
Stone类主要实现的就是对棋子的绘图,没什么好说的。
publicclassStone
{
privateGraphicsmg;
privateImageimgBlackStone;//黑子图片从文件获取
privateImageimgWhiteStone;//白子图片
publicStone(Graphicsg)
{
System.Reflection.AssemblythisExe;
thisExe=System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Streamwfile=thisExe.GetManifestResourceStream("FiveStones.whitestone.gif");//读取黑子,白子图片
System.IO.Streambfile=thisExe.GetManifestResourceStream("FiveStones.blackstone.gif");//从资源中获取
imgBlackStone=System.Drawing.Image.FromStream(bfile);
imgWhiteStone=System.Drawing.Image.FromStream(wfile);
bfile.Close();
wfile.Close();
mg=g;
}
publicvoidDrawStone(intm,intn,boolflag)//绘制棋子
{
if(flag)//判断是黑棋(true)还是白棋(false)
{
g.DrawImage(imgBlackStone,m*40,n*40,imgBlackStone.Width,imgBlackStone.Height);
}
else
{
g.DrawImage(imgWhiteStone,m*40,n*40,imgWhiteStone.Width,imgWhiteStone.Height);
}
}
}
3.Computer类中方法的实现
一.每下一子都要进行的过程Down方法
这个方法说明了下子之后的整个计算过程,先重新定义一个虚拟棋盘,然后对该虚拟棋盘有子的位置的权值赋值为-1,就是肯定不会走的,然后调用Check方法对没有子的位置进行权值计算,然后使用Check返回的权值在MaxQZ里面计算权值的最大值。
publicvoidDown(int[,]arrchessboard)//基本思路:
先计算每个点的权值,在权值最高的位置下棋
{
int[,]qz=newint[15,15];//权值数组
for(inti=0;i<15;i++)
{
for(intj=0;j<15;j++)
{
if(arrchessboard[i,j]<2)
{
qz[i,j]=-1;//当已有子时标注为-1
}
else
{
qz[i,j]=Check(i,j,arrchessboard);//Check方法在下面介绍,是计算权值的方法
}
}
}
MaxQZ(qz);//MaxQZ也在下面进行介绍,是计算最大权值的方法
}
二.计算权值的方法Check
上面的流程图写出了整体的过程,Check主要是对刚刚定义的权值数组进行赋值,先对己方进行赋值,然后对对手的进行赋值,然后判断是应该防守还是应该进攻。
电脑Ai的攻击力取决于权值的赋值,详细见注释。
privateintCheck(intm,intn,int[,]arrchessboard)
{
//赋值的原则决定了AI是进攻强还是防守强,进攻强则在AI和人都有三字连起时,给自己的赋值更高一些,防守强则是给人的赋值更高一些
intqz=0;
intw1=100000;//找自己的取胜点()
intw2=50000;//找对手的取胜点()
intw3=10000;//找自己的三个相连的点()
intw4=5000;//找对手的三个相连的点()
intw5=1000;//找自己的两个相连的点()
intw6=500;//找对手的两个相连的点()
intw7=100;//找自己的相连的点()
intw8=50;//找对方的相连的点()
intw9=999999;//找自己的失败点,无穷大,优先胜利
int[]arrf=newint[4];
if(mflag)//如果电脑是黑子
{
arrchessboard[m,n]=0;//如果该位置下我方的子的时候,进行下面的权值计算,白黑子都要进行计算
}
else//否则电脑是白子
{
arrchessboard[m,n]=1;//这里赋值的原因是因为不同色的值不一样
}
//分别计算四个方向上的连子数,调用Rule里面的四个方法
arrf[0]=Rule.Xnum(m,n,arrchessboard);//横向
arrf[1]=Rule.Ynum(m,n,arrchessboard);//竖向
arrf[2]=Rule.YXnum(m,n,arrchessboard);//左上右下
arrf[3]=Rule.XYnum(m,n,arrchessboard);//右上左下
if(m==7&&n==7){qz+=1;}//中心点权值加,这主要是为了电脑先手时,优先走中间点
for(inti=0;i<4;i++)
{
if(Math.Abs(arrf[i])==5)//连成五子
{
qz+=w1;
}
if(arrf[i]==4)//连成四子
{
qz+=w3;
}
if(arrf[i]==3)//连成三子
{
qz+=w5;
}
if(arrf[i]==2)//连成二子
{
qz+=w7;
}
if(mflag)//如果我方为黑棋,还要检查失败点
{
if(Rule.IsFail(arrf,arrchessboard[m,n])>0)
{
qz+=w9;
}
}
}
if(mflag)//如果该位置下对方的子
{
arrchessboard[m,n]=1;//对方白子
}
else//对方黑子
{
arrchessboard[m,n]=0;
}
arrf[0]=Rule.Xnum(m,n,arrchessboard);
arrf[1]=Rule.Ynum(m,n,arrchessboard);
arrf[2]=Rule.YXnum(m,n,arrchessboard);
arrf[3]=Rule.XYnum(m,n,arrchessboard);
for(inti=0;i<4;i++)
{
if(Math.Abs(arrf[i])==5)
{
qz+=w2;
}
if(arrf[i]==4)
{
qz+=w4;
}
if(arrf[i]==3)
{
qz+=w6;
}
if(arrf[i]==2)
{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件 综合 实习 报告 五子棋 游戏 实现