C++黑白棋实验报告文档格式.docx

上传人:b****5 文档编号:16010429 上传时间:2022-11-17 格式:DOCX 页数:25 大小:24.14KB
下载 相关 举报
C++黑白棋实验报告文档格式.docx_第1页
第1页 / 共25页
C++黑白棋实验报告文档格式.docx_第2页
第2页 / 共25页
C++黑白棋实验报告文档格式.docx_第3页
第3页 / 共25页
C++黑白棋实验报告文档格式.docx_第4页
第4页 / 共25页
C++黑白棋实验报告文档格式.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

C++黑白棋实验报告文档格式.docx

《C++黑白棋实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《C++黑白棋实验报告文档格式.docx(25页珍藏版)》请在冰豆网上搜索。

C++黑白棋实验报告文档格式.docx

下面一一介绍各自功能的作用和实现方式。

3、悔棋

悔棋功能即为返回上一步下棋之前的状态,通过数组记录前一步棋盘状态,悔棋时返回上一步棋盘状态。

悔棋功能可以无穷悔棋,如果已经是开局状态会提示无发悔棋。

4、存档与读档

存档和读档通过二进制文件流实现,共有三个存档位置,存在游戏安装目录下,存档时可选择三个存档中的一个存档。

读档是若读取的是未存储的存档位置,会提示重新读档。

5、提示功能

提示功能是这个程序比较独特的功能之一,主要是在玩家不知道该怎么下时可以由AI代替玩家下一步棋,实现较为简单。

一、AI部分介绍

1、最大最小值搜索

AI部分的主干采取的是博弈问题中常见的敌对搜索,原理较为简单,不在过多赘述。

模拟自己下棋以及对手下棋,当到达一定深度时通过估值函数给出对局面的估价。

然后再对手下棋层取子节点中的最小值(对手不想让“我”赢),自己下棋的层取子节点最大值。

2、剪枝:

α-β剪枝和节点排序

Alpha-beta剪枝是敌对搜索中较为常见的最优性剪枝,由于每层中先搜索的节点(为简单,以下称为兄节点)的返回值实际上给出了本层同父节点(上一个节点相同)的界限,例如在最小值节点A的子节点中a的返回值为5,那么A的返回值至多为5。

若A的兄节点B的返回值为6,则AB的父节点X必定不会取A的值。

故A节点的其他子节点的搜索已经无意义。

此时A节点直接返回5。

我们发现在α-β剪枝中剪枝的效率同节点搜索顺序有极大关系,如果最先搜索的是最优解,那么剪枝效率极高。

如果在最糟糕的情形下,先搜索的节点总比后搜索的节点糟糕,那么实际上不会进行剪枝。

由此产生了对剪枝的进一步优化:

节点排序。

节点排序是在搜索之前先对所有待搜索的点做一步预搜索(本程序中采用的是直接估值的方式),按照大小顺序排序之后。

按顺序进行搜索。

这样先搜索的枝则有较大可能为较优枝,而预搜索层数很少,所以在时间上代价并不大。

3、估价函数

估价函数是决定棋力高低的重要因素,较常见的估价包括行动力(可以下棋的位置)、稳定子、内部子(相对稳定子),外部子(危险子)、奇偶性(最后一步谁下)。

因为估价函数的复杂性会使得AI思考时间迅速上升,故在折中考虑以及多次实践之后,我采取了以行动力为主,同时对于绝对稳定子(四个角上的子)和最大危险子(2,22,77,27,7)进行考虑。

在试验多次后和考虑全部稳定子相比差距并不大,而时间上略有减少。

因此采用这种方式。

4、残局搜索(终局搜索)

黑白棋在即将结束时的考虑因素和中局不太相同,中局时主要考虑稳定子和行动力。

但是在残局时应该考虑最多的是最终棋子数目,而且残局是可下棋位置逐渐变少,搜索层数限制的不大,因此在残局时直接搜索至游戏结束,从中选出必胜策略。

 

代码:

文件1:

“MyFunction,h”

#include<

iostream>

iomanip>

fstream>

string>

cstdio>

cstring>

cstdlib>

ctime>

queue>

conio.h>

windows.h>

usingnamespacestd;

/*引用外部变量*/

externHANDLEhout;

externHANDLEhin;

externINPUT_RECORDmouseRec;

//控制台输入信息

externDWORDres;

externstringsidestr[3];

//输出字符

externintturn_side[2];

//表示走棋次序对应黑棋/白棋

externintdir[8][2];

//方向

externintboard[9][9];

//棋盘

externintformer_board[64][9][9];

//记录历史棋盘

externintstep;

//步数

externintdepth;

//搜索深度

externintplayerside;

//玩家的颜色

externintaput_x,aput_y;

//每次AI走的棋子

externintturn[2];

//表示走棋次序对应玩家/AI

/*-------------------------------------------基本功能函数-------------------------------------------*/

/*清屏函数*/

inlinevoidclear_screen()

{

COORDhome={0,0};

DWORDdummy;

CONSOLE_SCREEN_BUFFER_INFOcsbi;

GetConsoleScreenBufferInfo(hout,&

csbi);

FillConsoleOutputCharacter(hout,'

'

csbi.dwSize.X*csbi.dwSize.Y,home,&

dummy);

SetConsoleCursorPosition(hout,home);

}

/*隐藏光标*/

inlinevoidhide()

CONSOLE_CURSOR_INFOcursor_info={1,0};

SetConsoleCursorInfo(hout,&

cursor_info);

/*光标定位*/

inlinevoidlocate(intx,inty)

COORDcoord;

//光标位置

coord.X=x;

coord.Y=y;

SetConsoleCursorPosition(hout,coord);

//光标定位

/*读取当前鼠标点击位置*/

inlineCOORDget_mouse()

while

(1){

COORDpos;

ReadConsoleInput(hin,&

mouseRec,1,&

res);

if(mouseRec.EventType==MOUSE_EVENT)

{

if(mouseRec.Event.MouseEvent.dwButtonState==FROM_LEFT_1ST_BUTTON_PRESSED)

{

pos=mouseRec.Event.MouseEvent.dwMousePosition;

returnpos;

}

}

/*鼠标定位(功能选择)*/

inlineintmouse_locate(COORDpos)

intx=pos.X,y=pos.Y;

if(y==0&

&

x>

11&

x<

16)return1;

//1表示点击的是存档键

16&

21)return2;

//2表示点击的是读档键

21&

26)return3;

//3表示点击的是悔棋

26&

30)return5;

//5表示点击退出键

30)return6;

//表示点击的是作弊键

if(y>

2&

y<

18&

y%2)

if(x>

1&

34)return4;

//4表示点击的是落子区域

return0;

//0表示点击非法区域

/*复制棋盘*/

voidcopy(intorg_board[9][9],intcopy_board[9][9])//复制棋盘

for(inti=1;

i<

9;

i++)

for(intj=1;

j<

j++)

copy_board[i][j]=org_board[i][j];

/*求棋子数*/

intsum(intnow_board[9][9],intmy_side)//求棋子数

ints=0;

if(now_board[i][j]==my_side)s++;

returns;

/*翻转棋盘*/

voidchange(intx,inty,intmy_side){

board[y][x]=my_side;

for(intj=0;

8;

j++)//八个方向

inttempx=x+dir[j][0],tempy=y+dir[j][1],i=1;

while(tempx>

0&

tempx<

9&

tempy>

tempy<

9)//不超过边界

if(board[tempy][tempx]==0)break;

//遇到空位置跳出

elseif(board[tempy][tempx]==my_side)

{

for(intk=1;

k<

i;

k++)

board[y+k*dir[j][1]][x+k*dir[j][0]]=my_side;

break;

}

i++;

tempx+=dir[j][0];

tempy+=dir[j][1];

/*判断该位置是否合法*/

boolcheck(intx,inty,intmy_side)

if(x==0||y==0||x>

8||y>

8)return0;

if(board[y][x]!

=0)return0;

if(i>

1)return1;

//如果遇到己方子并且中间至少有一个对方子,说明可以下

//遇到己方子跳出

/*----------

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1