四子棋人工智能.docx
《四子棋人工智能.docx》由会员分享,可在线阅读,更多相关《四子棋人工智能.docx(36页珍藏版)》请在冰豆网上搜索。
四子棋人工智能
人工智能作业
姓名:
guojl
学号:
2620139012
指导老师:
刘峡壁
1.要求
每一道编程题需提交四份文件:
(1)可执行程序;
(2)源代码;(3)程序设计说明;(4)程序使用说明。
注:
以上文件请打包成一个压缩文件,以“学号_姓名_大作业名称”方式命名后提交。
在文件中请留下你的个人联系方式,以便在出现文件不能解压、不能打开、程序不能编译运行等各种情况时与你联系
Implementacomputergameprogramwhichmustsatisfythefollowingrequirements:
1.Usealpha-betaalgorithmtosearchthesolutions;
2.Theallowedmaximumdepthofthegametreeis8;
3.Useneuralnetworktoevaluatethestatesofleavesinthegametree;
4.Usesomemachinelearningmethodtotrainthisneuralnetworkintheprocessofcompetingagainstitselforothers.
TicTacToeona4x4Board(4x4一字棋)
PlayingRules:
1)Xalwaysgoesfirst.
2)ThePlayersalternateplacingXsandOsontheboarduntileither(a)oneplayerhasfourinarowhorizontally,verticallyordiagonally;or(b)all16squaresarefilled.
3)IfaplayerisabletodrawfourXsorfourOsinarow,thatplayerwins.
4)Ifall16squaresarefilledandneitherplayerhasfourinarow,thegameisadraw.
1,给电脑安装JDK1.6以上版本,推荐JDK1.7
2,请将BP_net_weight.txt文件拷贝到我的电脑的C盘根目录下
3,点击运行Tic-Toc-Too.jar或者Tic-Toc-Too-*.exe
其中
包结构如下:
1,BpNeuralNetworks代码如下:
packagencse.bpNeuralNetworks;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
/**
*神经网络评估
*@authorguojl
*@version20141124
*/
publicclassBpNeuralNetworks{
privatestaticdoubleETA=0.7;
privatestaticintN=4;//输入层节点数
privatestaticintSIZE=N*N;
privatestaticintMAXVAL=Short.MAX_VALUE;
privatestaticintMINVAL=Short.MIN_VALUE;
privatedoubleinput_layer[];//输入层
privatedoublecompetition_layer[];//隐藏层
privatedoubleoutput_layer;//输出层(激活函数作用之前)
privatedoubley_i;//神经网络输出(经过激活函数作用)
privatedoublew_ji[];//隐藏层到输出层权重,隐藏层N个节点到输出层1个节点
privatedoublew_kj[][];//输入层到隐藏层权重,输入层N个节点到隐藏层N个节点
privatedoubley_j[];//隐藏层经过激活函数作用之后,即出输出的输入
//privateStringfilepath=System.getProperty("user.dir")+"//src//ncse//res//BP_net_weight.txt";
//privateStringfilepath=getClass().getResource("/")+"//ncse//res//BP_net_weight.txt";
privateStringfilepath="C:
//BP_net_weight.txt";
//神经网络初始化
publicBpNeuralNetworks(){
input_layer=newdouble[SIZE];
competition_layer=newdouble[SIZE];
w_ji=newdouble[SIZE];
w_kj=newdouble[SIZE][SIZE];
y_j=newdouble[SIZE];
init_net();
}
//初始化神经网络的输入层隐藏层输出层
privatevoidinit_net(){
for(inti=0;iinput_layer[i]=0.0;
competition_layer[i]=0.0;
}
output_layer=0.0;
}
//初始化权重
publicvoidinit_weight(){
for(inti=0;iw_ji[i]=Math.random();
}
for(inti=0;ifor(intj=0;jw_kj[i][j]=Math.random();
}
}
}
//激活函数。
采用双曲正切函数。
//输入:
整合函数值(整合函数为加权求和)。
//返回值:
激活函数值。
privatedoublelogistic_s(doubletheta){
return(1.0-Math.exp(-theta))/(1.0+Math.exp(theta));
}
//BP神经网络应用函数。
输入棋盘,立即得到其倒推值。
//输入:
当前棋盘状态。
//返回值:
神经网络输出值(需要乘以MAX才等于倒推值)。
publicdoubleBP_net_value(int[]chess_board){
init_net();
//输入层赋值,当前棋盘状态
for(inti=0;iinput_layer[i]=(double)chess_board[i];
}
//计算隐藏层
for(intj=0;jfor(intk=0;kcompetition_layer[j]+=w_kj[k][j]*input_layer[k];
}
}
//计算输出层
for(intj=0;jy_j[j]=logistic_s(competition_layer[j]);
output_layer+=w_ji[j]*y_j[j];
}
y_i=logistic_s(output_layer);
returny_i;
}
//调整权值函数。
进行不超过最大迭代次数的正向/反向传播过程,不断调整权值。
如果误差小于允许值则结束。
//输入:
一组学习样本(代表棋盘的16维向量以及对应倒推值)。
//返回值:
void
publicvoidadjust_BP_net_weight(int[]chess_board,intbacked_up_value){
intiteration_times=1000000;
inttemp_iteration_times=0;
while(true){
y_i=BP_net_value(chess_board);
//如果达到允许的最小误差或最大迭代次数,退出并结束本次学习
if(Math.abs(y_i-(double)backed_up_value/(double)MAXVAL)<0.000001
||temp_iteration_times>=iteration_times){
break;
}
//开始反向传播误差,调整权重
for(intj=0;jw_ji[j]=w_ji[j]-ETA*y_j[j]*(1-y_i*y_i)
*(y_i-(double)backed_up_value/(double)MAXVAL);
}
for(intk=0;kfor(intj=0;jw_kj[k][j]=w_kj[k][j]
-ETA
*input_layer[k]
*(1-y_j[j]*y_j[j])
*w_ji[j]
*(1-y_i*y_i)
*(y_i-(double)backed_up_value/(double)MAXVAL);
}
}
temp_iteration_times++;
}
return;
}
//读取神经网络的权重,即神经网络训练的模型
//按照写入顺序读取,数字之间用空格分开
//两组权重为两行(第一组之后又换行符)
publicvoidread_weight(){
Stringnum[];
try{
Stringencoding="utf-8";
//Filefile=newFile("./../res/BP_net_weight.txt");
Filefile=newFile(filepath);
if(file.isFile()&&file.exists()){//判断文件是否存在
System.out.println("******************************************");
InputStreamReaderread=newInputStreamReader(newFileInputStream(file),encoding);
BufferedReaderbufferedReader=newBufferedReader(read);
StringlineTxt=null;
lineTxt=bufferedReader.readLine();
num=lineTxt.split("");
for(inti=0;iw_ji[i]=Double.parseDouble(num[i]);
}
lineTxt=bufferedReader.readLine();
num=lineTxt.split("");
for(inti=0;ifor(intj=0;jw_kj[i][j]=Double.parseDouble(num[i*SIZE+j]);
}
}
read.close();
}else{
System.out.println("read_weight找不到指定的文件");
}
}catch(Exceptione){
System.out.println("read_weight读取文件内容出错");
e.printStackTrace();
}
}
//保存神经网络训练的模型
//此函数与publicvoidread_weight()对应
publicvoidwrite_mode(){
try{
Filefile=newFile(filepath);
file.createNewFile();
OutputStreamWriterow=newOutputStreamWriter(newFileOutputStream(file),"utf-8");
BufferedWriterbwrite=newBufferedWriter(ow);
for(inti=0;ibwrite.write(w_ji[i]+"");
}
bwrite.write("\n");
for(inti=0;ifor(intj=0;jbwrite.write(w_kj[i][j]+"");
}
}
bwrite.close();
}catch(Exceptione){
System.out.println("write_mode找不到指定的文件");
}
}
}
2,Checker棋盘程序如下:
packagencse.checkerOP;
importncse.bpNeuralNetworks.BpNeuralNetworks;
/**
*棋盘程序
*@authorguojl
*@version20141124
*/
publicclassChecker{
privatestaticintN=4;
privatestaticintSIZE=N*N;
//MAXVALMINVAL分别是默认的最大值、最小值点
privatestaticintMAXVAL=Short.MAX_VALUE;
privatestaticintMINVAL=Short.MIN_VALUE;
//电脑一直使用1代替
//人一直使用-1代替
//在显示时,根据是否先手,确定棋子是“O”还是“X”
privatestaticintcomputer=1;//电脑
privatestaticintplayer=-1;//人
privateintwhofirst=1;//默认电脑先手
privateintm_chess_board[];//棋盘,用一维数组(N*N)表示二维数组(N,N)
privateBpNeuralNetworksbpnet;//神经网络
//设置先手
publicvoidsetWhofirst(intwhofirst){
this.whofirst=whofirst;
}
//初始化棋盘对象
publicChecker(){
this.m_chess_board=newint[SIZE];
bpnet=newBpNeuralNetworks();
//读取神经网络训练的模型
bpnet.read_weight();
//清空棋盘
this.clear_board();
}
//清空棋盘
publicvoidclear_board(){
for(inti=0;ithis.m_chess_board[i]=0;
}
}
//获取棋盘某一点值
//0:
表示没有棋子
//1:
表示是电脑的棋子
//-1:
表示是人的棋子
publicintget_chess_board_val(inti,intj){
returnthis.m_chess_board[i*N+j];
}
//打印棋盘函数,调试用。
//输入:
void
//返回值:
void
privatevoidprint_chess_board(int[]chess_board){
inti=0,j=0;
for(i=0;ifor(j=0;jif(jSystem.out.println(chess_board[i*N+j]+"");
}else{
System.out.println(chess_board[i*N+j]+"\n");
}
}
}
return;
}
//在棋盘(x,y)处放置棋子。
棋子类型为枚举piece∈{A,B}。
//输入:
棋盘、x、y、棋子类型。
//返回值:
void
privatevoidplace_piece_on_chess_board(int[]chess_board,intx,inty,
inttype){
intpos=x*N+y;
if(pos<16&&pos>=0)//防止计算结果出错,导致数组越界
chess_board[x*N+y]=type;
else{
//如果计算结果越出数组大小,打印当前x,y值
//调试用
System.out.println("x="+x+"y="+y);
}
}
//功能同重载函数
//不同点为,此函数默认对当前棋盘操作
//是对外提供的在棋盘上下棋子的接口函数
publicvoidplace_piece(intx,inty,inttype){
place_piece_on_chess_board(this.m_chess_board,x,y,type);
}
//测试指定起点与步长的N个数数否相等,相等返回数值
//否则返回0
//用于判断当前棋盘是否有N个相同的棋子连续
privateinttest_N_num_equal(int[]chess_board,intstart,intstep){
/*
*原理:
一行棋子相同,则是在数组中N倍数点起始连续N个点相同且不是0
*一列棋子相同,则是判断前N个点中某一点起始,隔N的倍数个点的值都相同且不为0
*对角线,间隔分别是:
主对角线(N+1)
*次对角线(N-1)
*以上判断,都是相隔固定个点,
**/
inti=0;
intcheck_flag=1;
for(i=0;iif(chess_board[start+i*step]!
=chess_board[start+(i+1)
*step]){
check_flag=0;
break;
}
}
if(check_flag==1&&chess_board[start+i*step]!
=0){
returnchess_board[start+i*step];
}
return0;
}
//测试当前棋局谁赢。
//输入:
棋盘。
//返回值:
为0表示A、B都没赢,为1表示A胜,为-1表示B胜。
privateinttest_who_win(int[]chess_board){
//分别测试一行、一列、两个对角线连成一线四种情况下的输赢
intret=0;
for(inti=0;i//行
ret=test_N_num_equal(chess_board,(i*N),1);
if(ret!
=0)
returnret;
//列
ret=test_N_num_equal(chess_board,i,N);
if(ret!
=0)
returnret;
}
//主对角线
ret=test_N_num_equal(chess_board,0,(N+1));
if(ret!
=0)
returnret;
//次对角线
ret=test_N_num_equal(chess_board,(N-1),(N-1));
if(ret!
=0)
returnret;
return0;
}
//同privateinttest_who_win(int[]chess_board)
//此函数式对外提供的接口函数
publicintwho_win(){
returntest_who_win(this.m_chess_board);
}
//测试当前棋盘(博弈树结点)属于极大结点或极小结点。
//输入:
棋盘。
//返回值:
为