C++实现黑白棋
- 格式:doc
- 大小:60.50 KB
- 文档页数:11
基于C语言的黑白棋游戏设计黑白棋,也被称为翻转棋,在全球范围内广受欢迎。
它的玩法简单而富有挑战性,因此在计算机科学领域中,基于C语言的黑白棋游戏设计成为了一个常见的项目。
本文将详细介绍如何使用C语言设计一个功能完善的黑白棋游戏。
一、游戏规则黑白棋的规则很简单,游戏双方通过轮流下棋,在棋盘上放置自己颜色的棋子。
当一个棋子被夹在两个对方的棋子之间时,这个棋子就会被翻转成对方的颜色。
游戏继续进行,直到棋盘被填满或者双方都无法再下棋为止。
最后,棋盘上棋子数量较多的一方获胜。
二、程序设计1. 游戏界面设计在设计游戏界面时,我们可以使用C语言提供的字符画功能。
通过绘制合适大小的方格和棋子标识符,可以在控制台上模拟出一个棋盘。
同时,使用特殊字符来绘制提示信息和菜单栏,可以增强游戏的可玩性和视觉效果。
2. 数据结构设计为了表示棋盘和棋子的状态,我们需要设计相应的数据结构。
一个简单而有效的方法是使用二维数组来表示棋盘。
每个数组元素的值可以用来表示该位置的状态,比如1表示黑棋、2表示白棋、0表示空位。
这样,可以通过对数组的操作来实现棋子的落子和翻转。
3. 游戏逻辑设计黑白棋的游戏逻辑涉及到棋子落子、翻转以及胜负的判断。
在程序设计中,我们需要编写相应的函数来处理这些逻辑。
比如,可以编写一个函数来检查某一位置是否可以落子,以及另一个函数来实现棋子翻转的操作。
4. 用户交互设计为了使游戏更加友好和可操作性强,我们可以设计一些用户交互功能。
比如,在每次轮到玩家下棋时,程序可以提示玩家输入坐标来落子。
同时,我们可以设计一些额外的功能,比如悔棋、重新开始等,以提升游戏的易用性。
三、程序实现下面是一个简单的基于C语言的黑白棋游戏设计的示例代码:```c#include<stdio.h>#define SIZE 8void initializeBoard(int board[SIZE][SIZE]) {// 初始化棋盘}void printBoard(int board[SIZE][SIZE]) {// 绘制棋盘}int isLegalMove(int board[SIZE][SIZE], int row, int col) {// 检查是否可以落子}void makeMove(int board[SIZE][SIZE], int row, int col, int player) { // 落子}void flipPieces(int board[SIZE][SIZE], int row, int col, int player) { // 翻转棋子}int hasValidMove(int board[SIZE][SIZE], int player) {// 检查是否有可行的落子点}int countPieces(int board[SIZE][SIZE], int player) {// 统计棋盘上的棋子数量}int main() {int board[SIZE][SIZE];int currentPlayer = 1; // 1代表黑子,2代表白子initializeBoard(board);while (hasValidMove(board, currentPlayer)) {printBoard(board);int row, col;printf("Player %d's turn, please enter row and column: ", currentPlayer);scanf("%d %d", &row, &col);if (isLegalMove(board, row, col)) {makeMove(board, row, col, currentPlayer);flipPieces(board, row, col, currentPlayer);currentPlayer = (currentPlayer == 1) ? 2 : 1;} else {printf("Invalid move!\n");}}int blackCount = countPieces(board, 1);int whiteCount = countPieces(board, 2);printf("Game over! ");if (blackCount > whiteCount) {printf("Player 1 wins!\n");} else if (blackCount < whiteCount) {printf("Player 2 wins!\n");} else {printf("It's a draw!\n");}return 0;}```四、总结通过使用C语言,我们可以轻松地设计和实现一个黑白棋游戏程序。
引言黑白棋的简要历史:黑白棋,又叫反棋(Reversi)、奥赛罗棋(Othello),苹果棋,翻转棋。
黑白棋起源中世纪的英国,18世纪传入日本,并在日本得到了发展。
现在,黑白棋在西方和日本很流行。
游戏通过相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。
它的游戏规则简单,因此上手很容易,但是它的变化又非常复杂。
有一种说法是:只需要几分钟学会它,却需要一生的时间去精通它。
“黑白棋规则”:1)两人对奕,以轮流方式持黑子与白子。
2)开辟新局者持白子,加入者持黑子,之后以轮流方式将棋子置于棋盘格子中。
若无地方可下子,则跳过一回,由对方下子。
3)在提示的格子中,选择一个格子下子,当下子的位置与离最近的同色旗子中,若有其他棋子则中间的棋子变为与我方一样颜色。
4)当下满64个棋子,棋子多者为胜。
关于C语言:C语言是一种结构化设计语言,它兼顾有高级语言的特点和低级语言的功能。
其设计功能十分强大,既可用于编写应用软件,又可用于设计制作系统软件。
同时,C语言是一种较为通用的编程软件,在目前的软件行业中使用也是十分的广泛。
虽然C语言是面向DOS编程的,但它是计算机的底层编程工具之一。
由C语言编写的程序,它的代码质量和运行速度仅次于汇编语言编写的程序,C语言具有简单易学和可移植性好等特点,同时又具有汇编语言的特点,具有较强的生命力和广泛的应用前景。
第一章系统分析1、1 可行性分析科技的飞速发展,将人类带入了信息时代,计算机越来越贴近人的生活,速度成为人们成功的前提条件,以致于人们必须不断尝试着使用各种手段来提高自身的工作效率,其手段之一就是对键盘的充分利用和相应游戏软件的开发.智能型的游戏越来越深受广大游戏爱好者的喜欢.方便而快捷.黑白棋的游戏是要在一个8*8的网格中进行,而数组属于构造体类型,数组是具有相同数据类型的变量序列,序列中的每个变量成为元素,数组元素由一个统一标识的数组名和顺序好“下标”来表示。
顾需要在游戏中定义一个二维数从而实现游戏的走棋、落棋、判断棋盘的变化等。
C语⾔-⿊⽩棋(⼈机对战)1 #include <stdio.h>2 #include <stdlib.h>3/*4具体思路如下:51.定义⼀个⼆维数组chessboard[8][8],⽤于保存⿊⽩双⽅棋⼦的位置。
如果数组元素为0,表⽰该单元格未落⼦;如果是-1,表⽰该单元格是⿊⼦;如果是1,则表⽰该单元格是⽩⼦。
62.当⼀⽅下棋时,先检查是否有位置可下,如果有则⼰⽅下棋,如果没有就让对⼿下棋。
73.若玩家下,需要等待玩家输⼊棋⼦坐标,然后执⾏翻转对⼿棋⼦操作。
84.若计算机下,程序需对棋盘所有可以落⼦的位置进⾏判断,找出最佳的落⼦位置,然后执⾏翻转对⼿棋⼦操作。
95.重复步骤2~4,直到棋盘已满或双⽅都不能下⼦时结束。
10*/1112void Output(char chessboard[][8]); //显⽰棋盘中的下⼦情况13int Check(char chessboard[][8],int moves[][8],char player);//检查⼀⽅是否有位置下⼦14void PlayStep(char chessboard[][8],int row,int col,char player);//在指定位置下棋15void AutoPlayStep(char chessboard[][8],int moves[][8],char player);//计算机思考下⼦16int GetMaxScore(char chessboard[][8],char player);//获取分数17int BestPlay(char chessboard[][8],int moves[][8],char player);//最优下⼦位置181920int main(){21char chessboard[8][8];//保存棋盘中各单元格下⼦的状态22int isDown[8][8] = {0};//保存棋盘中的各个位置是否可以下⼦,可以下的位置为1,其余为023int row,col,x,y;24int iCount = 0;//以下⼦的数量25int player = 0;//下棋⽅26int SkipPlay = 0;//重置下⼦的次数为0,若为2,则表⽰双⽅都不能下⼦27int Score[2];//保存计算机和玩家的得分2829char select,ch;3031 printf("⿊⽩棋\n\n");32 printf("玩家执⿊⼦先⾏,计算机执⽩,按Enter开始\n");333435 scanf("%c",&select);3637do{3839if(player==0){40 player = 1;41 }else{42 player = 0;43 }4445for(row=0;row<8;row++){46for(col=0;col<8;col++){47 chessboard[row][col]=0;48 }49 }5051 iCount = 4;//游戏开始的四颗棋⼦52 chessboard[3][3] = chessboard[4][4] = 1;53 chessboard[3][4] = chessboard[4][3] = -1;5455 printf("\n棋盘初始状态:\n");56 Output(chessboard);5758//双⽅下棋59do{60if(player==1){//玩家下棋(⿊)61 player = 0;62if(Check(chessboard,isDown,2)){63while(1){64 fflush(stdin);65 printf("输⼊下⼦的位置(⾏,列):");66 scanf("%d%c",&x,&ch);67 x--;//因为数组是从0开始存的68if(ch>='a'){69 y = ch - 'a' + 1;70 } else{71 y = ch - 'A' + 1;72 }73 y--;74//判断是否越界、是否已有棋⼦75if(x>=0&&x<8&&y>=0&&y<8&&isDown[x][y]){76 PlayStep(chessboard,x,y,2);77 iCount++;78break;79 }else{80 printf("坐标输⼊有误,请重新输⼊。
c语言黑白棋程序设计文档本文将为您介绍一份经过精心设计的基于C语言的黑白棋程序设计文档。
这个文档旨在为开发者提供一个清晰易懂、易于扩展的代码框架,以便更好地完成黑白棋游戏。
以下是本文档的结构和内容:一、简介黑白棋是一款二人对弈的棋类游戏,在8x8的方格棋盘上进行。
本程序的目标是实现一个基本的黑白棋人机对战游戏。
玩家可以使用键盘来操作棋子落下的位置,程序会根据规则自动判断是否可以落子,并自动翻转另一方的棋子。
程序还可以提供简单的AI进行游戏,让玩家可以对战电脑。
本程序使用了C语言进行编写,并且采用简单易懂的函数式编程方法,使得程序更加易于维护和扩展。
二、程序设计在程序设计中,我们遵循了模块化、封装和数据隐藏的原则,使得代码结构更加清晰明了,易于理解和维护。
主要分为5个模块:负责程序的初始化工作,包括初始化棋盘、初始化玩家、初始化AI等等。
在main函数中,我们通过调用下面四个模块的函数来构建整个游戏的逻辑流程。
2. chessboard模块负责棋盘的初始化、显示、落子、判断是否合法等逻辑处理。
该模块中定义了结构体变量用于存储棋盘信息。
在该模块中定义了落子的函数check(),该函数根据当前棋子的位置、颜色和棋盘状态进行判断,如果可以落子,则将当前棋子位置上色,并调用翻转棋子的函数reverse(),否则提示玩家重新输入坐标。
3. player模块负责玩家的初始化、操作、胜负判断等逻辑处理。
在该模块中定义了结构体变量用于存储玩家信息。
该模块中定义了getinput()函数,该函数根据玩家从键盘输入的信息获取当前落子的位置。
4. AI模块负责人工智能的实现,其中包括随机落子AI、进攻型AI、防守型AI 等。
在该模块中定义了结构体变量用于存储AI信息。
AI的实现方式采用了启发式搜索,寻找最优解。
同时,AI还要判断当前落子位置是否合法,如果不合法则重新进行随机落子。
负责一些通用函数的实现,如计算得分、判断胜负等等。
运行结果:源码:#include<stdio.h>#include<math.h>int rule(int map[8][8],int x,int y,int order);////规则函数int judge(int map[8][8],int order);////判断函数void eat(int map[8][8],int x,int y,int order);//////吃子函数void refresh(int map[8][8]);/////刷新函数void main(){int x,y,order=1,count=0,can=0,end=2;int map[8][8]={0};map[3][3]=1;map[3][4]=-1;map[4][3]=-1;map[4][4]=1;/////-1 represent white 1 represent blackrefresh(map);while(end)/////如果双方同时不能落子则宣告结束{count=judge(map,order);if(order==1)printf("黑方下:");elseprintf("白方下:");if(count==0){printf("无法落子,请对方下\n");order=-order;end--;}else{end=2;scanf("%d %d",&x,&y);can=rule(map,x-1,y-1,order);if(can==0)printf("不符合落子规则\n");else{eat(map,x-1,y-1,order);order=-order;}}}printf(" game over\n");}int judge(int map[8][8],int order){int rule(int map[8][8],int x,int y,int order);int i,j,ju=0,n=0;for(i=0;i<8;i++)for(j=0;j<8;j++){n=rule(map,i,j,order);if(n>0){printf("横标%d竖标%d可以下子\n",i+1,j+1);ju++;}}return ju;}int rule(int map[8][8],int x,int y,int order){int arry[8][2]={{0,-1},{0,1},{-1,-1},{-1,0},{-1,1},{1,-1},{1,0},{1,1}};int i,ru=0,lx,ly;if(map[x][y]==0)////保证所下的子原来是空处{for(i=0;i<8;i++){lx=x+arry[i][0];ly=y+arry[i][1];if(map[lx][ly]!=-order)continue;while(map[lx][ly]==-order&&lx>-1&&ly>-1&&lx<8&&ly<8) {lx=lx+arry[i][0];ly=ly+arry[i][1];}if(map[lx][ly]==order&&lx>-1&&ly>-1&&lx<8&&ly<8)ru++;}}return ru;}void eat(int map[8][8],int x,int y,int order){void refresh(int map[8][8]);int arry[8][2]={{0,-1},{0,1},{-1,-1},{-1,0},{-1,1},{1,-1},{1,0},{1,1}};int i,lx,ly;for(i=0;i<8;i++){lx=x+arry[i][0];ly=y+arry[i][1];if(map[lx][ly]!=-order)continue;while(map[lx][ly]==-order&&lx>-10&&ly>-1&&lx<8&&ly<8){lx=lx+arry[i][0];ly=ly+arry[i][1];}if(map[lx][ly]==order&&lx>-1&&ly>-1&&lx<8&&ly<8){int m=0,n=0;if(lx-x!=0&&ly-y!=0){do{map[x+m][y+n]=order;m=m+(lx-x)/abs(lx-x);n=n+(ly-y)/abs(ly-y);}while(m!=lx-x);}else if(lx-x==0){do{map[x][y+n]=order;n=n+(ly-y)/abs(ly-y);}while(n!=ly-y);}else{do{map[x+m][y]=order;m=m+(lx-x)/abs(lx-x);}while(m!=lx-x);}}}refresh(map);}void refresh(int map[8][8]){int i,j,hei=0,bai=0;printf(" 1 2 3 4 5 6 7 8\n");printf(" +---+---+---+---+---+---+---+---+\n");for(i=0;i<8;i++){printf("%d",i+1);for(j=0;j<8;j++){switch(map[i][j]){case 0: printf(" | ");break;case 1: printf(" |○");hei++;break;///黑子case -1: printf(" |●");bai++;break;///白子}}printf(" |\n");printf(" +---+---+---+---+---+---+---+---+\n");}printf(" count of white %d\n count of black %d\n",bai,hei); }。
目录第1章课程设计的目的与要求 (1)1.1 课程设计目的 (1)1.2 课程设计的实验环境 (1)1.3 课程设计的预备知识 (1)1.4 课程设计要求 (1)第2章课程设计内容 (2)2.1程序功能介绍 (2)2.2程序整体设计说明 (3)2.2.1设计思路 (3)2.2.2数据结构设计及用法说明 (4)2.2.3程序结构(流程图) (6)2.2.4各模块的功能及程序说明 (8)2.2.5程序结果 (8)2.3程序源代码及注释 (9)第3章课程设计总结 (21)参考资料 (22)第1章课程设计的目的与要求1.1 课程设计目的本课程设计是计算机科学与技术专业重要的实践性环节之一,是在学生学习完《程序设计语言(C)》课程后进行的一次全面的综合练习。
本课程设计的目的和任务:1. 巩固和加深学生对C语言课程的基本知识的理解和掌握2. 掌握C语言编程和程序调试的基本技能3. 利用C语言进行基本的软件设计4. 掌握书写程序设计说明文档的能力5. 提高运用C语言解决实际问题的能力1.2 课程设计的实验环境硬件要求能运行Windows 2000/XP操作系统的微机系统。
C语言程序设计及相应的开发环境。
1.3 课程设计的预备知识熟悉C语言及C语言开发工具。
1.4 课程设计要求1. 分析课程设计题目的要求2. 写出详细设计说明3. 编写程序代码,调试程序使其能正确运行4. 设计完成的软件要便于操作和使用5. 设计完成后提交课程设计报告第2章课程设计内容2.1程序功能介绍只有在可以吃到对方棋子的方格里落子。
吃子规则:采用夹吃的原则,左图用红色标记的是黑方可落子的位置。
当黑方落子之后,则夹在两黑子中间的白子都将变为黑子。
右图是落子后的棋盘布局,蓝色标记的是白方可落子的位置。
夹子的方向包含:水平、竖直、斜对角。
1.点击“新游戏”,将从新初始化棋局。
2.打开游戏存档,默认是.bwc文件3.保存当前游戏,默认扩展名为.bwc4.后退一步,即悔棋5.前进一步,只有在前面的操作存在后退的基础上,该按钮才有效。
黑白棋规则介绍黑白棋是由黑方和白方两人进行的益智游戏。
棋盘为N×N方格,黑白棋总共使用N2个棋子,每个棋子分正反两面,分别是黑色和白色。
轮到一方下棋时,必须把棋下在与对方棋子相邻的空位上,要求所下的棋子和原有的已方棋子夹住对方的至少一个棋子(横竖斜夹均可),然后把被夹住的子变成己方的颜色(也叫吃子)。
下棋过程中,任何棋子既不会从棋盘上拿走,也不会从一个格子移到另一个格子,吃子时,不会发生连锁反应,吃进的棋子不能再夹吃其他的子。
当双方都无棋可下,或者方格全部占满后,棋局结束,子多的一方为胜方。
黑白棋人工智能的实现我们这里取棋盘大小为10×10个方格,用数组int state[10][10]来表示棋盘的状态,其中0表示方格为空,-1表示用黑方的棋,1表示白方的棋。
在10×10的棋盘上,除了那些已经有子的地方不能走子外,那些不能吃子的点也不能走。
如何判断某个点(x, y)能不能走子呢?通过分析黑白棋的规则我们知道,在这一个方格上的八个方向的任何一个方向上只要满足:在这个方向与之相邻的有连续若干个对方的棋子,接着有一个己方的子,我们就可以肯定这一点能够走子。
所以我定义了一个数组int dirstate[8](数组从右逆时针开始,如dirstate[0]表示右,dirstate[1]表示右上,以此类推)来表示个方向的状态,值1表示在这个方向上可以吃掉对方的子,值0则表示不能,同时定义一个函数movedir(int x,int y,int mover)来判断各方向的状态,函数movedir的具体实现见源代码,这里以右方向为例说明,其他各个方向类似,右方向的判断可以用以下语句实现:int tx=x+1,ty=y,step=0;//tx,ty分别用来表示右方向各点在数组中的索引dirstate[0]=0;//初始化为不能吃子while(1){if(tx>9) break;//处于边界,退出循环,该方向不能吃子if(state[ty][tx]==0) break; //空子,退出循环,该方向不能吃子if(state[ty][tx]!=mover) step++;//(tx,ty)所在的方格上的棋不一样,step加1,有连//续step个对方的棋子与(x,y)上的棋相邻else {if(step>0) dirstate[0]=1;break;}// (tx,ty)所在的方格上的棋一样,同时在(tx,ty)//和(x,y)之间如果有连续step个对方的棋子,则、//表示该方向上可以吃子,修改dirstate[0]状态。
tx++;}我们需要让计算机自己决定下一步走哪儿,必须让它知道走哪儿对它自己最有利,解决这个问题的基本思想就是对这个有利进行量化,我们有一个非常简单的方法就可以实现这个量化,那就是下该子能吃掉对方子的数目为该步的有利值,为了让计算机算出该值,我定义了一个int movetotal(int x,int y,int mover)函数,该函数返回该步能吃掉对方的子数,他的主要实现跟movedir类似,也是对各个方向进行统计,因此也可以用此函数来判断该位置能不能放子:int total=0;//total用来统计总的能够吃掉对方的子数,函数最后返回此值int tx=x+1,ty=y,step=0;while(1){if(tx>9) break;if(state[ty][tx]==0) break;if(state[ty][tx]!=mover) step++;else {if(step>0) total+=step;break;}//与movedir不同的地方,这里将step加到//total这个统计整数里面tx++;}有了这些函数,电脑就可以用这个有利值选择一个位置下棋,因此接下来我们就要考虑黑白棋的下棋后棋盘状态的变化了。
我们知道,当我们在(x,y)这个位置上下一个棋后,就会引起这个位置的八个方向上的符合条件(棋子和原有的已方棋子夹住对方的至少一个棋子)的方格上棋子状态的改变。
为此我们定义了函数move (int x,int y,int mover)实现这个功能,其中x,y为下棋的位置,mover为-1表示己方用黑棋,1表示己方用白棋,函数move的主要实现如下(以右方向为例,详细请看源代码):movedir(x,y,mover);//调用movedir函数,得到dirstate数组表示各个方向的状态state[y][x]=mover;//在该位置上下棋,改变棋盘在该位置的状态,将空状态改为moverint tx=x,ty=y;if(dirstate[0]==1)//为1则表示该方向可以吃掉对方的棋子,将已方棋子夹住对方棋子改//为己方{while(state[ty][++tx]==mover*(-1))//循环直到遇到己方的棋子{state[ty][tx]=mover;//将对方的棋子改为己方的棋子}}至此,一个非常简单的黑白棋就已经完成了,看到这里聪明的你当然会说,这样的电脑不是太容易赢了,没错,如果只看到当前能够吃掉对方子的个数最大数就下认为该步是最优的话,那明显是不对的,因为下一步对方有可能吃掉你更多的子,这样就得不偿失,所以我们必须增加一些算法,使计算机得到的位置接近最优,我们就必须判断该步后的几步,预测对方可能下的位置,计算机的高速运算能力和高存储能力为我们提供了实现的条件,这里我们采用了深度优先的方法,生成一棵解树,找出比较接近最优的解,预测的步数就是深度优先方法的深度,也就是解树的深度,这就要看具体计算机的速度内存的大小,深度越深,得到的也就越接近最优解,这里不可能递推太深,不然计算机每下一步会慢的你无法忍受,同时内存的限制了你递推的深度。
递推函数的实现如下:1.int getbenefit (int x,int y,int mover,int n)2.{3. int benefit=0;4. benefit=movetotal(x,y,mover);5. if(benefit<=0)return 0;6. if(n==1)7. {8. return benefit;9. }10. else11. {12. int tempstate[10][10];13. int good[10][10];14. int i=0,j=0;15. for(i=0;i<10;i++)16. {17. for(j=0;j<10;j++)18. {19. tempstate[i][j]=state[i][j];20. good[i][j]=0;21. }22. }23. move(x,y,mover);24. mover=mover*(-1);25. n-=1;26. for(i=0;i<10;i++)27. {28. for(j=0;j<10;j++)29. {30. if(state[i][j]!=0)continue;31. if(movetotal(j,i,mover)>0)32. {33. if(i==0&&j==0||i==9&&j==0||i==0&&j==9||i==9&&j==9)34. {35. if(mover==computermover)36. benefit+=n+5;37. if(mover!=computermover)38. benefit-=n-5;39. }40. good[i][j]=getbenefit(j,i,mover,n);41. }42. }43. }44. benefit=findmax(good,10,10)*mover+benefit;45. for(i=0;i<10;i++)46. {47. for(j=0;j<10;j++)48. {49. state[i][j]=tempstate[i][j];50. }51. }52. return benefit;53. }54.}函数说明:1:函数的参数中(x,y)表示当前要下的位置,mover为-1表示己方用黑棋,1表示己方用白棋,n为递推的深度。
4~5:计算下(x,y)能够吃掉对方棋子的数放到benefit里,并判断(x,y)能不能放子,benefit大于0表示可以,否则退出递推函数,返回0表示不能放子。
6~11:判断是否达到所要求的递推深度,当n等于1是表示完成递推,返回该位置能吃掉对方的棋子数benefit,否则继续进行递推。
12~22:数组int tempstate[10][10]对当前棋盘的状态进行备份,使递推函数退出时可以恢复原来的棋盘状态,数组int good[10][10]用来存储下该子后对方在棋盘各个位置上下棋分别能吃掉己方的棋子数,初始化为0。
23:在(x,y)位置上下棋,调用move函数实现,改变棋盘的状态,以前进行递推运算对方下一步的吃掉己方的子数,当然这种改变是暂时的,在最后还要用数组tempstate备份的棋盘状态进行恢复。
24~25:改变下棋方,同时递推深度减一26~43:对棋盘可以下棋位置进行递推调用getbenefit函数,这是本函数的主要部分,将各个位置的调用getbenefit函数的返回值保存到good数组上,以便找到对方能够吃掉己方最多子的位置。
33~39:这是对本智能函数的一个优化部分,考虑到占领四个角对整盘棋起着至关重要的作用,所以只要可以占领四个角,便对该位置增加或减少(看当前递推是处于递推己方还是对方)一个权值,在这里我将这个权值设为n+5,与递推的深度有关,越深表示最后下到那里的机会越小,所以权值就越小。
44:用findmax求出good数组中最大的值,乘以mover的作用就是要根据当前递推是处于递推黑方还是白方来判断good数组中表示的是黑方还是白方的加权值,用mover可以巧妙的分辨出当前递推是处于递推黑方还是白方,这里mover已经在24行那里改变了,所以good得到的是与前面用movetotal函数得到benefit值相反。
45~51:恢复棋盘到进入递推函数前的状态。
至此,该程序的核心部分已经完成,整合上面的函数,我们可以得到一个电脑选择位置下棋子的函数computerAI (),他的实现如下:1. int i=0,j=0,mx=0,my=0,max;2. int benefit[10][10];3. for(i=0;i<10;i++)4. {5. for(j=0;j<10;j++)6. {7. benefit[i][j]=-1000;8. }9. }10. for(i=0;i<10;i++)11. {12. for(j=0;j<10;j++)13. {14. if(state[i][j]!=0)continue;15. if(i==0&&j==0||i==0&&j==9||i==9&&j==0||i==9&&j==9)16. {17. if(movetotal(j,i,computermover)>0)18. {19. move(j,i,computermover);20. return;21. }22. }23. if(movetotal(j,i,computermover)>0)24. benefit[i][j]=getbenefit(j,i,computermover,AI);25. if(i==1||i==8||j==1||j==8)benefit[i][j]+=1;26. }27. }28. max=benefit[0][0];29. for(i=0;i<10;i++)30. {31. for(j=0;j<10;j++)32. {33. if(benefit[i][j]>max)34. {35. max=benefit[i][j];36. mx=j;37. my=i;38. }39. }40. }41. if(movetotal(mx,my,computermover)>0)42. move(mx,my,computermover);函数说明:2~9:数组benefit[10][10]用来存放各点所能得到的权值,类似于getbenefit的good数组,初始化为一个比较大的负值,这里取-1000,因为权值不会大于1000。