700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > c语言五子棋人机对弈算法_从零开始编写C语言五子棋程序1

c语言五子棋人机对弈算法_从零开始编写C语言五子棋程序1

时间:2021-08-01 16:23:28

相关推荐

c语言五子棋人机对弈算法_从零开始编写C语言五子棋程序1

从零开始编写C语言五子棋程序

C语言程序是国科大计算机系本科生必修课程,我选修的是武成岗老师的C语言课程。除了课上回答问题,实验课competitive programming的成绩之外,最终的大作业五子棋程序也占据了相当重的分值。除了写出基本的显示棋盘、人人对战、人机对战的功能之外,武老师对人机对战的策略提出了更高的要求。期末时每个人所写的AI会进行1对1的比赛,五子棋作业的分数与比赛排名直接挂钩(卷,就嗯卷)。开这个坑的原因有两点,一是记录自己写这个程序的过程(可能是我目前写过的代码最长的程序),理清思路同大家分享,另一方面想熟悉一下刚学的Markdown排版。(试图摆脱折磨人的公众号内部编辑)今天要解决的是第一部分,五子棋棋盘的实现。

五子棋棋盘的实现

解决这个问题可以有两种思路:

利用双重循环首先构建出一个空棋盘,接着用户根据棋盘上显示的坐标实现下棋的操作,只需要把输入坐标所对应的字符替换成黑/白棋子即可。

构建三个棋盘:第一个棋盘用于存放空棋盘的模板,第二个棋盘是用于在终端显示的棋盘(交互棋盘),第三个棋盘是所谓“内部棋盘”,用户输入的坐标改变的是内部棋盘上的数值,这一数值的改变反映到交互棋盘上就是黑/白棋子。

两种思路其实都可以实现棋盘的功能,在这里,我为了减轻后期调试工作的工作量,选择采取第二种方式来构建棋盘。

构建棋盘的过程中,最关键的就是二维数组的运用。二维数组和内部棋盘上的点建立起了一一映射的关系,通过改变二维数组中元素的值,即可改变棋盘上的落子情况。二维数组的相关知识,详见多维数组。

有了这个基本思想,下面我们就可以开始书写代码了。

宏定义与全局变量的声明

#include #include #include #define SIZE 15#define CHARSIZE 2void initRecordBorard(void);void innerLayoutToDisplayArray(void);void displayBoard(void);//棋盘使用的是GBK编码,每一个中文字符占用2个字节。//空棋盘模板 char arrayForEmptyBoard[SIZE][SIZE*CHARSIZE+1] = {"┏┯┯┯┯┯┯┯┯┯┯┯┯┯┓", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨", "┗┷┷┷┷┷┷┷┷┷┷┷┷┷┛"};//此数组存储用于显示的棋盘 char arrayForDisplayBoard[SIZE][SIZE*CHARSIZE+1];//此数组用于记录当前的棋盘的格局,即所谓“内部棋盘”int arrayForInnerBoardLayout[SIZE][SIZE];char play1Pic[]="●";//黑棋子;char play2Pic[]="◎";//白棋子;

主函数编写

int main(){initRecordBorard(); //初始化一个空棋盘 arrayForInnerBoardLayout[0][0]=1; //在棋盘的左上角落一个黑色棋子 innerLayoutToDisplayArray(); //将心中的棋盘转成用于显示的棋盘 displayBoard();//显示棋盘 getchar(); arrayForInnerBoardLayout[5][9]=2; innerLayoutToDisplayArray(); displayBoard(); getchar(); arrayForInnerBoardLayout[3][4]=2; innerLayoutToDisplayArray(); displayBoard(); getchar(); arrayForInnerBoardLayout[6][1]=1; innerLayoutToDisplayArray(); displayBoard(); getchar(); arrayForInnerBoardLayout[9][4]=2; innerLayoutToDisplayArray(); displayBoard(); getchar(); return 0;}//内部棋盘里的数组元素若为0,表示该位置为空,若为1,表示该位置落的是黑子,若为0,表示该位置落的是白子。//这是一个测试性的主函数(由于只是单纯想构建出棋盘来),整体操作分三步:落子——内部棋盘和交互棋盘的映射——显示出当前的交互棋盘棋盘的初始化

棋盘的初始化

//初始化一个空棋盘格局 void initRecordBorard(void){//通过双重循环,将arrayForInnerBoardLayout清0 int i,j; for(i = 0;i<= SIZE-1 ;i++){for(j = 0;j<= SIZE-1;j++)arrayForInnerBoardLayout[i][j] = 0; }}

内部棋盘和交互棋盘一一映射的构建

//将arrayForInnerBoardLayout中记录的棋子位置,转化到arrayForDisplayBoard中void innerLayoutToDisplayArray(void){//第一步:将arrayForEmptyBoard中记录的空棋盘,复制到arrayForDisplayBoard中 int i,j; for(i = 0;i <= SIZE - 1;i++){for(j = 0;j <=SIZE*CHARSIZE+1;j++)arrayForDisplayBoard[i][j] = arrayForEmptyBoard[i][j];} //第二步:扫描arrayForInnerBoardLayout,当遇到非0的元素,将●或者◎复制到arrayForDisplayBoard的相应位置上 //注意:arrayForDisplayBoard所记录的字符是中文字符,每个字符占2个字节。●和◎也是中文字符,每个也占2个字节。 for( i = 0;i <= SIZE-1;i++){for( j = 0; j <= SIZE-1;j++){if(arrayForInnerBoardLayout[i][j]!=0){if(arrayForInnerBoardLayout[i][j]==1){arrayForDisplayBoard[i][2*j] = play1Pic[0]; arrayForDisplayBoard[i][2*j+1] = play1Pic[1]; }else if(arrayForInnerBoardLayout[i][j]==2){arrayForDisplayBoard[i][2*j] = play2Pic[0]; arrayForDisplayBoard[i][2*j+1] = play2Pic[1]; } } }} }//这里涉及一个我之前没有接触过的知识点,将双字节字符赋值到字符数组里,要用连续的两个元素来进行赋值。

显示当前棋盘

//显示棋盘格局 void displayBoard(void){int i; //第一步:清屏 system("clear"); //清屏//第二步:将arrayForDisplayBoard输出到屏幕上 for(i=0;i<=SIZE-1;i++) printf("%3d %s\n",SIZE-i,arrayForDisplayBoard[i]); //第三步:输出最下面的一行字母A B ....printf(" "); for(i = 0;i<=SIZE-1;i++) printf("%2c",'A'+i); printf("\n");}

至此,我们已经完成了棋盘构建的全部工作,下面是程序的运行结果。

接下来的目标(周五前完成):

胜负的判定

先后手

记录上一次棋子的位置

输入quit退出游戏

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。