人工智能大作业——五子棋  |
这学期上人工智能导论,大作业我选择了写五子棋程序,用John Mc-Carthy经典的alpha-beta搜索进行剪枝,上个星期做了两天半,写了1500行左右的代码。虽然评价函数里仅有六条规则,但是这个AI已经达到了弱智走棋者的水平,呵呵。。。。 这几天作业和实验太多,而且快期末考试了,没时间继续加入更多的规则,这个月底就要交工了,抓紧时间。。。同志们提前帮我测试一把吧(C++写的,纯DOS界面,比较原始,但是应该很容易理解怎么下^_^)
//five.cpp#include "Chessboard.h"#include "Evaluation.h"#include "Computer_AI.h"#include "Alpha_Beta_Search.h"
#include <iostream>using namespace std;
void main(){test: Chessboard C; int turn_flag = 0; C.Print(); while(C.CheckWin()!=1){//未见输赢 if(turn_flag == 0){ turn_flag = C.human(); //cout<<"C.StateValue: "<<C.StateValue()<<endl; AlphaBetaSearch(C); } else{ turn_flag =C.computer_AI(); //C.StateValue(); } } if(C.humanWinFlag){ cout<<"你赢了!!!"<<endl; } if(C.computerWinFlag){ cout<<"你输了,电脑赢了,竟然输给了弱智电脑,哈哈哈......!!!"<<endl; } cout<<"再来一盘吧"<<endl; goto test;}
//Evaluation.h#ifndef EVALUATION_H#define EVALUATION_H
#include "Chessboard.h"#include <iostream>#include <math.h>#include <time.h>using namespace std;
/////////////////////////////////////////
int Chessboard::StateValue(){//评价函数 Livefive();//调用时一开始即将相关值赋为0 Livefour();//...... SingleLivethree();//...... Rushfour();//...... Livetwo();//...... TotalValue = 0 ; TotalValue+=live_five_c*100000+live_five_h*(-500000);//活五 TotalValue+=live_four_c*10000+live_four_h*(-50000);//活四 TotalValue+=rush_four_c*10000+rush_four_h*(-50000);//冲四 TotalValue+=single_live_three_c*1000+single_live_three_h*(-5000);//单活三 TotalValue+=live_two_c*100 + live_two_h*(-100);//活二
/* ////////test cout<<"Livefive_c: "<<live_five_c<<endl; cout<<"Livefive_h: "<<live_five_h<<endl; cout<<"Livefour_c: "<<live_four_c<<endl; cout<<"Livefour_h: "<<live_four_h<<endl; cout<<"Livethree_c: "<<single_live_three_c<<endl; cout<<"Livethree_h: "<<single_live_three_h<<endl; cout<<"Rushfour_c: "<<rush_four_c<<endl; cout<<"Rushfour_h: "<<rush_four_h<<endl; cout<<"Livetwo_c: "<<live_two_c<<endl; cout<<"Livetwo_h: "<<live_two_h<<endl; ////////test */ //cout<<"\nTotalValue is: "<<TotalValue<<endl; return TotalValue;}
//////////////////////////////////////////////////////////////////////////void Chessboard::Livefive(){//求出并修改电脑和人分别的活五的个数 live_five_c = 0; live_five_h = 0;
for( int i = 0 ; i<NumberX ; i++){//生成棋子盘 for( int j = 0 ; j<NumberY ; j++){ ChessMan[i][j] = board[i*2+2][j*4+3]; } }
///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 0 ; j<NumberY-4 ; j++){ if(ChessMan[i][j] == '#'){ if(ChessMan[i][j+1] == '#' && ChessMan[i][j+2] == '#' && ChessMan[i][j+3] == '#' && ChessMan[i][j+4] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(ChessMan[i][j] == 'O'){ if(ChessMan[i][j+1] == 'O' && ChessMan[i][j+2] == 'O' && ChessMan[i][j+3] == 'O' && ChessMan[i][j+4] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 0 ; i<NumberX-4 ; i++){ if(ChessMan[i][j] == '#'){ if(ChessMan[i+1][j] == '#' && ChessMan[i+2][j] == '#' && ChessMan[i+3][j] == '#' && ChessMan[i+4][j] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(ChessMan[i][j] == 'O'){ if(ChessMan[i+1][j] == 'O' && ChessMan[i+2][j] == 'O' && ChessMan[i+3][j] == 'O' && ChessMan[i+4][j] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }
int minNumber = (NumberX<=NumberY)?NumberX:NumberY;//取棋子横纵行数小的值 char * tempCharArray;//临时字符型数组,用于存储各对角线元素
//检查所有斜率为1的对角线 for( int i = 4 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(tempCharArray[n] == '#'){ if(tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n+4] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(tempCharArray[n] == 'O'){ if(tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n+4] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }
for( int i = 1 ; i<=minNumber-5; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
for( int n = 0 ; n<=minNumber-i-5 ; n++){ if(tempCharArray[n] == '#'){ if(tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n+4] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(tempCharArray[n] == 'O'){ if(tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n+4] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 4 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
for( int n = 0 ; n<=i-4 ; n++){ if(tempCharArray[n] == '#'){ if(tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n+4] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(tempCharArray[n] == 'O'){ if(tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n+4] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 4 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(tempCharArray[n] == '#'){ if(tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n+4] == '#' ){ live_five_h+=1;//人的活五数加1 } } if(tempCharArray[n] == 'O'){ if(tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n+4] == 'O' ){ live_five_c+=1;//电脑的活五数加1 } } } }}
//////////////////////////////////////////////////////////////////////////
void Chessboard::Livefour(){//求出并修改电脑和人分别的活四的个数 live_four_h = 0; live_four_c = 0;
for( int i = 0 ; i<NumberX ; i++){//生成棋子盘 for( int j = 0 ; j<NumberY ; j++){ ChessMan[i][j] = board[i*2+2][j*4+3]; } }
///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 0 ; j<NumberY-4 ; j++){ if( j>=1 && j<=NumberY-2){ if(ChessMan[i][j] == '#' && ChessMan[i][j+1] == '#' && ChessMan[i][j+2] == '#' && ChessMan[i][j+3] == '#' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+4] == ' '){ live_four_h+=1;//人的活四数加1 }
if(ChessMan[i][j] == 'O' && ChessMan[i][j+1] == 'O' && ChessMan[i][j+2] == 'O' && ChessMan[i][j+3] == 'O' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+4] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 0 ; i<NumberX-4 ; i++){ if( i>=1 && i<=NumberX-2){ if(ChessMan[i][j] == '#' && ChessMan[i+1][j] == '#' && ChessMan[i+2][j] == '#' && ChessMan[i+3][j] == '#' && ChessMan[i-1][j] == ' ' && ChessMan[i+4][j] == ' '){ live_four_h+=1;//人的活四数加1 } if(ChessMan[i][j] == 'O' && ChessMan[i+1][j] == 'O' && ChessMan[i+2][j] == 'O' && ChessMan[i+3][j] == 'O' && ChessMan[i-1][j] == ' ' && ChessMan[i+4][j] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } }
int minNumber = (NumberX<=NumberY)?NumberX:NumberY;//取棋子横纵行数小的值 char * tempCharArray;//临时字符型数组,用于存储各对角线元素
//检查所有斜率为1的对角线 for( int i = 5 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_h+=1;//人的活四数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } }
for( int i = 1 ; i<=minNumber-6; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
for( int n = 0 ; n<=minNumber-i-5 ; n++){ if(n>=1 && n<=minNumber-i-5){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_h+=1;//人的活四数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 5 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_h+=1;//人的活四数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 5 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == '#' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_h+=1;//人的活四数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == 'O' && tempCharArray[n-1] == ' ' && tempCharArray[n+4] == ' '){ live_four_c+=1;//电脑的活四数加1 } } } } }
//////////////////////////////////////////////////////////////////////////
void Chessboard::SingleLivethree(){//检查电脑和人分别的单活三的个数 single_live_three_h = 0; single_live_three_c = 0;
for( int i = 0 ; i<NumberX ; i++){//生成棋子盘 for( int j = 0 ; j<NumberY ; j++){ ChessMan[i][j] = board[i*2+2][j*4+3]; } }
///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 1 ; j<=NumberY-4 ; j++){ if(ChessMan[i][j] == '#' && ChessMan[i][j+1] == '#' && ChessMan[i][j+2] == '#' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+3] == ' '){ single_live_three_h+=1;//人的单活三数加1 }
if(ChessMan[i][j] == 'O' && ChessMan[i][j+1] == 'O' && ChessMan[i][j+2] == 'O' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+3] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 1 ; i<=NumberX-4 ; i++){ if(ChessMan[i][j] == '#' && ChessMan[i+1][j] == '#' && ChessMan[i+2][j] == '#' && ChessMan[i-1][j] == ' ' && ChessMan[i+3][j] == ' '){ single_live_three_h+=1;//人的单活三数加1 }
if(ChessMan[i][j] == 'O' && ChessMan[i+1][j] == 'O' && ChessMan[i+2][j] == 'O' && ChessMan[i-1][j] == ' ' && ChessMan[i+3][j] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
int minNumber = (NumberX<=NumberY)?NumberX:NumberY;//取棋子横纵行数小的值 char * tempCharArray;//临时字符型数组,用于存储各对角线元素
//检查所有斜率为1的对角线 for( int i = 4 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
for( int n = 1 ; n<=i-3 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_h+=1;//人的单活三数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
for( int i = 1 ; i<=minNumber-5; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
for( int n = 1 ; n<=minNumber-i-4 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_h+=1;//人的单活三数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 4 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
for( int n = 1 ; n<=i-3 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_h+=1;//人的单活三数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 4 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
for( int n = 1 ; n<=i-3 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == '#' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_h+=1;//人的单活三数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == 'O' && tempCharArray[n+3] == ' ' && tempCharArray[n-1] == ' '){ single_live_three_c+=1;//电脑的单活三数加1 } } }
///////////////////// ///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 0 ; j<NumberY-4 ; j++){ if( j>=1 && j<=NumberY-2){ if( ((ChessMan[i][j] + ChessMan[i][j+1] + ChessMan[i][j+2] + ChessMan[i][j+3] + ChessMan[i][j-1] + ChessMan[i][j+4]) == (35*3 +32*3) ) && (ChessMan[i][j-1] == ' ' && ChessMan[i][j+4] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 }
if( ((ChessMan[i][j] + ChessMan[i][j+1] + ChessMan[i][j+2] + ChessMan[i][j+3] + ChessMan[i][j-1] + ChessMan[i][j+4]) == (79*3 +32*3) ) &&(ChessMan[i][j-1] == ' ' && ChessMan[i][j+4] == ' ' ) ) { single_live_three_c+=1;//电脑的单活三数加1 } } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 0 ; i<NumberX-4 ; i++){ if( i>=1 && i<=NumberX-2){ if( ((ChessMan[i][j] + ChessMan[i+1][j] + ChessMan[i+2][j] + ChessMan[i+3][j] + ChessMan[i-1][j] + ChessMan[i+4][j]) == (35*3 +32*3)) && (ChessMan[i-1][j] == ' ' && ChessMan[i+4][j] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 } if( ((ChessMan[i][j] + ChessMan[i+1][j] + ChessMan[i+2][j] + ChessMan[i+3][j] + ChessMan[i-1][j] + ChessMan[i+4][j]) == (79*3 +32*3)) && (ChessMan[i-1][j] == ' ' && ChessMan[i+4][j] == ' ' ) ){ single_live_three_c+=1;//电脑的单活三数加1 } } } }
//检查所有斜率为1的对角线 for( int i = 5 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(( (tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (35*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 } if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (79*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_c+=1;//电脑的单活三数加1 } } } }
for( int i = 1 ; i<=minNumber-6; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
for( int n = 0 ; n<=minNumber-i-5 ; n++){ if(n>=1 && n<=minNumber-i-5){ if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (35*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 } if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (79*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_c+=1;//电脑的单活三数加1 } } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 5 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (35*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 } if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (79*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_c+=1;//电脑的单活三数加1 } } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 5 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
for( int n = 0 ; n<=i-4 ; n++){ if(n>=1 && n<=i-4){ if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (35*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_h+=1;//人的单活三数加1 } if(((tempCharArray[n] + tempCharArray[n+1] + tempCharArray[n+2] + tempCharArray[n+3] + tempCharArray[n-1] + tempCharArray[n+4]) == (79*3 + 32*3)) && (tempCharArray[n+4] == ' ' && tempCharArray[n-1] == ' ' ) ){ single_live_three_c+=1;//电脑的单活三数加1 } } } }
////////////////////}//////////////////////////////////////////////////////////////////////////
void Chessboard::Rushfour(){//检查电脑和人分别的冲四的个数 rush_four_c = 0; rush_four_h = 0;
for( int i = 0 ; i<NumberX ; i++){//生成棋子盘 for( int j = 0 ; j<NumberY ; j++){ ChessMan[i][j] = board[i*2+2][j*4+3]; } }
///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 0 ; j<=NumberY-6 ; j++){ char * sixChar = new char[6];//六个字符的数组,以检测有多种情况的冲四 for( int m = 0 ; m<6 ; m++){ sixChar[m] = ChessMan[i][j+m]; } if(sixChar[0] == '#'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(sixChar[5] == '#'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[0]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(sixChar[0] == 'O'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(sixChar[5] == 'O'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[0]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 0 ; i<=NumberX-6 ; i++){ char * sixChar = new char[6];//六个字符的数组,以检测有多种情况的冲四 for( int m = 0 ; m<6 ; m++){ sixChar[m] = ChessMan[i+m][j]; }
if(sixChar[0] == '#'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(sixChar[5] == '#'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[0]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(sixChar[0] == 'O'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(sixChar[5] == 'O'){ if( (sixChar[1] + sixChar[2] + sixChar[3] + sixChar[4] + sixChar[0]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } }
int minNumber = (NumberX<=NumberY)?NumberX:NumberY;//取棋子横纵行数小的值 char * tempCharArray;//临时字符型数组,用于存储各对角线元素
//检查所有斜率为1的对角线 for( int i = 5 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
int tempCharArrayLength = i+1; for( int m = 0 ; m<=tempCharArrayLength-6 ; m++){ if(tempCharArray[m] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(tempCharArray[m+5] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(tempCharArray[m] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(tempCharArray[m+5] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } }
for( int i = 1 ; i<=minNumber-6; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
int tempCharArrayLength = minNumber-i; for( int m = 0 ; m<=tempCharArrayLength-6 ; m++){ if(tempCharArray[m] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(tempCharArray[m+5] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(tempCharArray[m] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(tempCharArray[m+5] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 5 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
int tempCharArrayLength = i+1; for( int m = 0 ; m<=tempCharArrayLength-6 ; m++){ if(tempCharArray[m] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(tempCharArray[m+5] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(tempCharArray[m] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(tempCharArray[m+5] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 5 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
int tempCharArrayLength = i+1; for( int m = 0 ; m<=tempCharArrayLength-6 ; m++){ if(tempCharArray[m] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } } if(tempCharArray[m+5] == '#'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (79*4+32)){ rush_four_c+=1;//电脑的冲四数加1 } }
if(tempCharArray[m] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m+5]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } if(tempCharArray[m+5] == 'O'){ if( (tempCharArray[m+1] + tempCharArray[m+2] + tempCharArray[m+3] + tempCharArray[m+4] + tempCharArray[m]) == (35*4+32)){ rush_four_h+=1;//人的冲四数加1 } } } } }
//////////////////////////////////////////////////////////////////////////
void Chessboard::Livetwo(){//检查电脑和人分别的活二的个数 live_two_c = 0; live_two_h = 0 ;
for( int i = 0 ; i<NumberX ; i++){//生成棋子盘 for( int j = 0 ; j<NumberY ; j++){ ChessMan[i][j] = board[i*2+2][j*4+3]; } }
///////逐行逐列,逐对角线检查 for(int i = 0 ; i<NumberX ; i++){//检查所有行 for(int j = 1 ; j<=NumberY-3 ; j++){ if(ChessMan[i][j] == '#' && ChessMan[i][j+1] == '#' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+2] == ' '){ live_two_h+=1;//人的活二数加1 }
if(ChessMan[i][j] == 'O' && ChessMan[i][j+1] == 'O' && ChessMan[i][j-1] == ' ' && ChessMan[i][j+2] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
for(int j = 0 ; j<NumberY ; j++){//检查所有列 for(int i = 1 ; i<=NumberX-3 ; i++){ if(ChessMan[i][j] == '#' && ChessMan[i+1][j] == '#' && ChessMan[i+2][j] == ' ' && ChessMan[i-1][j] == ' '){ live_two_h+=1;//人的活二数加1 } if(ChessMan[i][j] == 'O' && ChessMan[i+1][j] == 'O' && ChessMan[i+2][j] == ' ' && ChessMan[i-1][j] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
int minNumber = (NumberX<=NumberY)?NumberX:NumberY;//取棋子横纵行数小的值 char * tempCharArray;//临时字符型数组,用于存储各对角线元素
//检查所有斜率为1的对角线 for( int i = 3 ; i<=minNumber-1; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ; j++){ tempCharArray[j] = ChessMan[i-j][j]; }
for( int n = 1 ; n<=i-2 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_h+=1;//人的活二数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
for( int i = 1 ; i<=minNumber-4; i++ ){ tempCharArray = new char[minNumber-i];
for( int j = 0 ; j<minNumber-i ; j++){ tempCharArray[j] = ChessMan[minNumber-1-j][i+j]; }
for( int n = 1 ; n<=minNumber-i-3 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_h+=1;//人的活二数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
//检查所有斜率为-1的对角线
//右半边 含对角线 for( int i = 3 ; i<=minNumber-1 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j][j+minNumber-i-1]; }
for( int n = 1 ; n<=i-2 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_h+=1;//人的活二数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
//左下半边,不含对角线(minNumber-2),含对角线(minNumber-1) for( int i = 3 ; i<=minNumber-2 ; i++){ tempCharArray = new char[i+1];
for( int j = 0 ; j<=i ;j++){ tempCharArray[j] = ChessMan[j+minNumber-i-1][j]; }
for( int n = 1 ; n<=i-2 ; n++){ if(tempCharArray[n] == '#' && tempCharArray[n+1] == '#' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_h+=1;//人的活二数加1 } if(tempCharArray[n] == 'O' && tempCharArray[n+1] == 'O' && tempCharArray[n+2] == ' ' && tempCharArray[n-1] == ' '){ live_two_c+=1;//电脑的活二数加1 } } }
}
//////////////////////////////////////////////////////////////////////////
#endif EVALUATION_H
//Computer_AI.h#ifndef COMPUTER_AI_H#define COMPUTER_AI_H
#include "Chessboard.h"
#include <iostream>#include <math.h>#include <time.h>using namespace std;
//////////////////////////////////////////////////////////////////////////
bool Chessboard::computer_AI(){//人工智能
AlphaBetaSearch(*this);//对此节点作goX 和goY 的修改 setXY( goX , goY , 'O');//放上棋子 cout<<"电脑走了( "<<goX<<" , "<< goY<<" )"<<endl; Print();//打印棋盘
return 0;}//////////////////////////////////////////////////////////////////////////
#endif COMPUTER_AI_H//Alpha_Beta_Search.h#ifndef ALPHA_BETA_SEARCH_H#define ALPHA_BETA_SEARCH_H
#include "Chessboard.h"#include <iostream>#include <math.h>#include <time.h>using namespace std;
//////////////////////////////////////////////////////////////////////////
void AlphaBetaSearch(Chessboard &state){//不对此状态作任何改动, 除了goX 和 goY Chessboard s = state;//new 节点 int v = maxValue(s);//对s可作任意修改 s.setChessMan();
for( int i = 0 ; i<s.childNumber ; i++){ s.childPointerArray[i]->setChessMan(); if( s.childPointerArray[i]->alphaValue == v){ for(int x = 0 ; x<NumberX ; x++){ for( int y = 0 ; y<NumberY ;y++){ if( (s.ChessMan[x][y] == ' ') &&(s.childPointerArray[i]->ChessMan[x][y] == 'O') ){//只适用于两步和一步搜索 state.goX = x; state.goY = y; return; } } } } } }
//////////////////////////////////////////////////////////////////////////
int maxValue(Chessboard &state){ if(state.treeDepth == SearchDepth){//达到边界 int sv = state.StateValue();//评价函数的值 state.alphaValue = sv;//设置alpha 值 state.betaValue = sv;//设置beta 值 return sv;//返回评价函数的值 }
int v = -999999999; state.GenerateChildPointerArray();//生成此节点的子节点数组,电脑走此步
for( int x = 0 ; x<NumberX ; x++ ){ for( int y = 0 ; y<NumberY ; y++){ if( state.usefuleSite[x][y] == ' ' ){ state.GenerateNextChild(x, y,'O');//引用 v = (v>=minValue(*state.childPointerArray[state.currentChildSite-1]))?v:minValue(*state.childPointerArray[state.currentChildSite-1]); /* if( v >= state.betaValue ){ return v; } */ } } } state.alphaValue = (state.alphaValue>=v)?state.alphaValue:v; state.betaValue = state.alphaValue;
return v;}
int minValue(Chessboard &state){ if(state.treeDepth == SearchDepth ){ int sv = state.StateValue();//评价函数的值 state.alphaValue = sv;//设置alpha 值 state.betaValue = sv;//设置beta 值 return sv;//返回评价函数的值 }
int v = +999999999; state.GenerateChildPointerArray();//生成此节点的子节点数组,电脑走此步 state.getUsefulSite();
for( int x = 0 ; x<NumberX ; x++ ){ for( int y = 0 ; y<NumberY ; y++){ if( state.usefuleSite[x][y] == ' ' ){ state.GenerateNextChild(x,y,'#'); v = (v<=maxValue(*state.childPointerArray[state.currentChildSite-1]))?v:maxValue(*state.childPointerArray[state.currentChildSite-1]); /* if(v <= state.alphaValue ){ return v; } */ } } } state.betaValue = (state.betaValue<=v)?state.betaValue:v; state.alphaValue = state.betaValue; return v;}
//////////////////////////////////////////////////////////////////////////
#endif ALPHA_BETA_SEARCH_H//Chessboard.h#ifndef CHESSBOARD_H#define CHESSBOARD_H
#include <iostream>#include <math.h>#include <time.h>using namespace std;
const int row = 22;//棋盘行数const int column = 42;//棋盘列数const int NumberX = (row-2)/2;//棋子横行数const int NumberY = (column-2)/4;//棋子纵行数
const int SearchDepth = 1;//搜索深度
/////////////////////////////////////////////////////棋盘类定义class Chessboard{public: Chessboard(); void Print();//print the chessboard to the Screen friend void PrintChildValue(Chessboard s); void setXY( int x , int y , char c);//set the char with x,y void setChessMan();//得到棋子的状态,设置棋子盘 char getXY( int x , int y);//get the char with x,y bool CheckWin(); int getUsefulSite();//得到棋盘上的有效的走点,暂定为有子的位置的周围8个位置
void GenerateChildPointerArray();//生成子节点数组,由字符C void GenerateNextChild( int x, int y , char c);//生成下一子节点 ~Chessboard(){}
////////////////////// bool human();//human acts on the chessboard , if human has go , return 1 ,else return 0
bool computer_AI();//人工智能走棋,利用Alpha_Beta搜索算法
bool computer_rand();//随机走棋程序
//////////////////////
public://评价函数!!!!!! int StateValue();
void Livefive();//检查电脑和人分别的活五的个数 void Livefour();//检查电脑和人分别的活四的个数 void Livetwo();//检查电脑和人分别的活二的个数 void SingleLivethree();//检查电脑和人分别的单活三的个数 void Rushfour();//检查电脑和人分别的冲四的个数
public: int TotalValue;//此局面的评价函数值,初始为0,说明和局
int live_five_c ;//电脑活五的个数,初始化时为0 int live_five_h ;//人活五的个数,初始化时为0
int live_four_c ;//电脑活四的个数,初始化时为0 int live_four_h ;//人活四的个数,初始化时为0
int live_two_c ;//电脑活2的个数,初始化时为0 int live_two_h ;//人活2的个数,初始化时为0
int rush_four_c ;//电脑冲四的个数,初始化时为0 int rush_four_h ;//人冲四的个数,初始化时为0
int double_live_three_c ;//电脑双活3的个数,初始化时为0 int double_live_three_h ;//人双活3的个数,初始化时为0
int single_live_three_c ;//电脑单活3的个数,初始化时为0 int single_live_three_h ;//电脑单活3的个数,初始化时为0
public: friend void AlphaBetaSearch(Chessboard &state);//搜索极大值 friend int maxValue(Chessboard &state );//搜索极大值 friend int minValue(Chessboard &state );//搜索极小值 //friend void fr
|
|
回复:人工智能大作业——五子棋 |
launching(游客)发表评论于2005/12/24 10:51:58 | 不好意思,这个blog对文章的长度有限制,后面的评价函数没有贴上来。这两天我把程序修缮了一下,再发一次。这个程序的智能已经到达初学者的水平了。可以设置alpha beta搜索的深度,最好设为2或者3。不要设成3以上,那样的话搜索时生成树所占的内存空间将会超过G的水平,虽然搜索完毕后内存会被释放到原来的水平。最好还是设为2,这样搜索也快,内存占用也很小。
|
|
回复:人工智能大作业——五子棋 |
游客(游客)发表评论于2005/12/24 0:49:37 | 我把你代码超到Vc里并分成五个文件,为什么不好用呢?
|
|
» 1 »
|

.: 公告
|
« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
|
.: 我的分类(专题)
|

.: 最新日志
.: 最新回复
|

blog名称:Launching Is Launching 日志总数:36 评论数量:79 留言数量:1 访问次数:230184 建立时间:2005年12月11日 |
|

.: 留言板
|

.: 链接
|

|