300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > c语言实现五子棋人人对战教程

c语言实现五子棋人人对战教程

时间:2022-11-12 18:27:10

相关推荐

c语言实现五子棋人人对战教程

利用简单的c语言基础 实现最简单的功能 界面比较丑陋主要是刚学完c的一个小实践 未使用MFC所以界面没有很好看 主要目的加强对c语言的理解与运用 同时增加自己的代码量

首先要学一些头文件可以看我的博客前面的文章

要用到到的头文件stdio.h stdlib.h windows.h time.h conio.h

思路就是

1.画个棋盘,使用数组来代替初始化出*

2.使用循环使双方轮流下棋,使用数组存放棋子的位置

3.判断是否有一方获胜

首先打印棋盘

#include<stdio.h>#include<windows.h>#include<conio.h>#include<stdlib.h>char qipan[16][16];//函数声明void initQipan();//将*存入16*16的二维数组中void printQipan();//将二维数组打印出来void initQipan(){int i,j;for(i = 0;i < 16 ;i++)for(j = 0;j <16 ;j++)qipan[i][j] = '*';}void printQipan(){int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++)printf("%c",qipan[i][j]);printf("\n");} }int main(){initQipan();printQipan(); }

打印出来效果图

这里面我发现一个算是c语言的小陷阱

void printQipan(){int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++)printf("%c",qipan[i][j]);printf("\n");} }

这段代码中内层for循环后跟着两个语句但是按正常想法应该两条语句都应随着内层循环而循环也就是打出来的应该是这样

打印出来这样的代码是

int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++){printf("%c",qipan[i][j]);printf("\n");}}

但是显然他们的效果不等价

这样其实是因为如果内层没有写出{}就会默认将第一条指令给内层,其余所有指令给外层

可以看下面的代码

int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++)printf("%c",qipan[i][j]);printf(",");printf("\n"); }}

这样很显然得出结论

在这样结构的双重for循环中

for(){for()语句1语句2语句3...}

只有第一条语句属于内存循环,写成这样更加明了一些

for(){for()语句1语句2语句3...}

下面实现双方轮流下棋

/*************************************头文件********************************************/#include<stdio.h>#include<windows.h>#include<conio.h>#include<stdlib.h>/************************************全局变量********************************************/char qipan[16][16];int x,y;/************************************函数声明********************************************/void initQipan();//将*存入16*16的二维数组中void printQipan();//将二维数组打印出来void starGame();//开始游戏/************************************自定义函数******************************************/void initQipan(){int i,j;for(i = 0;i < 16 ;i++)for(j = 0;j <16 ;j++)qipan[i][j] = '*';}void printQipan(){int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++)printf("%c",qipan[i][j]);printf("\n");}}void starGame(){initQipan(); printQipan();while(1){printf("请白方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);qipan[x][y]='W';system("cls");printQipan();printf("请黑方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);qipan[x][y]='B';system("cls");printQipan();}}/*****************************************主函数****************************************/int main(){starGame();}

现在可以实现双方轮流下棋,接下来就是要实现系统去判定是否有人获胜

/*********************************************************************头文件*************************************************************************************/#include<stdio.h>#include<windows.h>#include<conio.h>#include<stdlib.h>/********************************************************************全局变量************************************************************************************/char qipan[16][16];int x,y;/********************************************************************函数声明************************************************************************************/void initQipan();//将*存入16*16的二维数组中void printQipan();//将二维数组打印出来void starGame();//开始游戏int panduan(int x,int y);//判断是否有人获胜void win(int winner);//有人获胜后显示那方胜利/********************************************************************自定义函数**********************************************************************************/void initQipan(){int i,j;for(i = 0;i < 16 ;i++)for(j = 0;j <16 ;j++)qipan[i][j] = '*';}void printQipan(){int i,j;for(i = 0;i < 16 ;i++){for(j = 0;j <16 ;j++)printf("%c",qipan[i][j]);printf("\n");}}void starGame(){int temp;initQipan(); printQipan();while(1){printf("请白方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);qipan[x][y]='W';system("cls");printQipan();temp = panduan(x,y);if(temp==1){printf("白方获胜");system("pause");}printf("请黑方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);qipan[x][y]='B';system("cls");printQipan();temp = panduan(x,y);if(temp==2){printf("黑方获胜");system("pause");} } }int panduan(int x,int y){char temp;//保存棋子的颜色int winner;//1代表白方,2代表黑方int i;//距离落子位置水平方向的差int j;//距离落子位置竖直方向的差int count;//记下有多少个连续的棋子count = 1;i = 1;j = 1;winner = 0;temp = qipan[x][y]; //***************************************************************************水平方向**************************************************************************//水平左边while(temp = qipan[x-i][y]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;count++;if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//水平右边i = 1;//因为要重新从一格开始移动,初始化i变量while(temp = qipan[x+i][y]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;count++;//此时count是接着水平左边继续累加if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//**************************************************************************竖直方向***************************************************************************//竖直上方i = 1;//初始化变量count = 1;//初始化变量while(temp = qipan[x][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){j++;count++;if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//竖直下方i = 1;//因为要重新从一格开始移动,初始化i变量while(temp = qipan[x][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){j++;count++;//此时count是接着水平左边继续累加if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//**************************************************************************从左向右倾斜*********************************************************************** //左上方i = 1;//初始化变量count = 1;//初始化变量while(temp = qipan[x-i][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;j++;count++;if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//右下方i = 1;//因为要重新从一格开始移动,初始化i变量while(temp = qipan[x+i][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;j++;count++;//此时count是接着水平左边继续累加if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//**************************************************************************从右向左倾斜***********************************************************************//右上方i = 1;//初始化变量count = 1;//初始化变量while(temp = qipan[x-i][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;j++;count++;if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;}}//左下方i = 1;//因为要重新从一格开始移动,初始化i变量while(temp = qipan[x+i][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5){i++;j++;count++;//此时count是接着水平左边继续累加if(count==5)//如果连成五子出现胜利的一方,否则继续判断{if(temp=='W')winner = 1;else winner = 2;} }return winner;}/*******************************************************************主函数**************************************************************************************/int main(){starGame();return 0;}

此时有一个问题就是程序会卡死如图

在写程序时出现这种错误可能的原因是:

①除以零

②数组越界:inta[3];a[10000000]=10;

③指针越界:int*p;p=(int*)malloc(5*sizeof(int));*(p+1000000)=10;

④使用已经释放的空间:int*p;p=(int*)malloc(5*sizeof(int));free(p);*p=10;

⑤数组开得太大,超出了栈的范围,造成栈溢出:inta[100000000]

ok发现问题是在如图位置没有初始化这几个变量现在已经将上面的代码修正了

下面来看最后优化完的代码

/***************************************头文件******************************************/#include<stdio.h>#include<windows.h>#include<conio.h>#include<stdlib.h>/****************************************宏*********************************************/#define N 16 //可以更改棋盘大小/***************************************全局变量*****************************************/char qipan[N][N];//全局变量,整个文件的都可以用int x,y;//代表的是棋盘(数组)下标为x的行 和 下标为y列的一个交点/***************************************函数声明*****************************************/void initQipan();//棋盘的初始化void printQipan();//打印棋盘void Pos(int x, int y);//设置光标位置void startGame();//游戏开始int panduan(int x,int y);//判断是否有人连成五子int showWhoWin();//输出谁赢了void whitePlay();//白方下子void blackPlay();//黑方下子void printShuzi();//打印数字模板/*****************************************自定义函数*************************************/void Pos(int x, int y)//设置光标位置,从哪里开始输出{COORD pos;//表示一个字符在控制台屏幕上的坐标,左上角(0,0)HANDLE hOutput;pos.X = x;pos.Y = y;hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄SetConsoleCursorPosition(hOutput, pos);}void printShuzi(){int i;Pos(2,0);for(i=0;i<N;i++)printf("%2d",i);for(i=0;i<16;i++){Pos(0,1+i);printf("%2d",i);}}void initQipan(){int i,j;for(i=0;i<N;i++)for(j=0;j<N;j++)qipan[i][j]='*';}void printQipan(){int i,j;printShuzi();for(i=0;i<N;i++){Pos(2,1+i);//自动换行的输出的功能,代替printf("\n");for(j=0;j<N;j++)printf(" %c",qipan[i][j]);}}int panduan(int x,int y){char temp;//保存下棋方的颜色,w bint count=1;//统计个数,针对的同一个线(水平线)int i=1;//走一格int j=1;//和i同时用来代表走斜的int whoWin=0;//1代表白方,2代表黑方temp=qipan[x][y];//水平的左边while(temp==qipan[x][y-i]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//水平的右边i=1;while(temp==qipan[x][y+i]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//解决垂直的方向//垂直上方i=1;count=1;//清理掉之前的数据while(temp==qipan[x-i][y]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//垂直下方i=1;while(temp==qipan[x+i][y]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//解决左上的斜线 上方i=1;j=1;count=1;while(temp==qipan[x-i][y-j]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;j++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//解决左上的斜线 下方i=1;j=1;while(temp==qipan[x+i][y+j]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;j++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//解决右上的斜线 上方i=1;j=1;count=1;while(temp==qipan[x-i][y+j]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;j++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}//解决右上的斜线 下方i=1;j=1;while(temp==qipan[x+i][y-j]&&x>=0&&x<N&&y>=0&&y<N&&count<5){i++;j++;count++;if(count==5)//首先count是5才能来判断谁赢了{if(temp=='W')whoWin=1;elsewhoWin=2;}}return whoWin;}int showWhoWin(){int overLeap=0;//1代表结束int leap;//用来接收谁赢了leap=panduan(x,y);if(leap==1){overLeap=1;system("cls");printQipan();printf("\n白方胜利\n");system("pause");}if(leap==2){overLeap=1;system("cls");printQipan();printf("\n黑方胜利\n");system("pause");}return overLeap;}void whitePlay(){printf("\n请白方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);//坐标的值while(1)//解决一直下错子的问题{if(qipan[x][y]=='*')//下子的地方没有其他子{qipan[x][y]='W';//解决while(1)break;}else{printf("您下子错误\n");printf("请白方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);//坐标的值}}printQipan();}void blackPlay(){printQipan();printf("\n请黑方落子,按下行与列的坐标:");scanf("%d%d",&x,&y);//坐标的值while(1)//解决一直下错子的问题{if(qipan[x][y]=='*')//下子的地方没有其他子{qipan[x][y]='B';//解决while(1)break;}else{printf("您下子错误\n");printf("请黑方落子,按下行与列的坐标:");}scanf("%d%d",&x,&y);//坐标的值}printQipan();}void startGame(){initQipan();printQipan();while(1){whitePlay();if(showWhoWin()==1)//system("pause");break;system("cls");//清理屏幕,是屏幕上的字不重复blackPlay();if(showWhoWin()==1)//system("pause");break;system("cls");printQipan();}printf("您是否重新游戏:y or n");if(getch()=='n'){system("cls");printf("游戏结束\n");exit(0);//因为程序终止}if(getch()=='y'){system("cls");startGame();}}/*********************************************主函数************************************/int main(){startGame();return 0;}

下面测试一下功能

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