C语言实验人机五子棋

大一上学期的时候,学校布置了C语言期末大作业,当时借鉴了许多CSDN上大佬的想法,半年多后想起来,决定将代码上传,共同学习。(当时是小白第一次进行较为复杂的代码,可能有些乱,多包涵!!!)
1.头文件及全局定义

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <Windows.h>
#include <ctime>
#include <cstdlib>
int t2[361];
void InitBoard(char a[20][20],int row,int col)
{
    memset(a,' ',row*col*sizeof(char));
}//将数组全部赋为空

2.棋盘

void qi(char a[20][20])
{
	for(int i=1;i<20;i++)
		{
			if(i==1)
			{
				printf("  ");
				for(int m=0;m<19;m++)
				{
					printf("|%02d",m+1);
				}
				printf("\n");
				for(int n=0;n<20;n++)
				{
					printf("---");
				}
			}
			printf("\n");
			printf("%02d",i);
			for(int j=1;j<20;j++)
			{
				if(j!=19)
				{
					printf("| %c",a[i][j]);
				}
				if(j==19)
				{
					printf("| %c|",a[i][j]);
				}
			}
			printf("\n");
			for(int k=0;k<20;k++)
			{
				printf("-- ");
			}
		}
		printf("\n");
}

棋盘较为简洁,主要是数组加上想象。

3.落子(人)

void ren(char a[20][20])
{
	while(1)
	{
	printf("请选择落子行列:");
	int x,y;
	scanf("%d%d",&x,&y);
	if((x<=0)||(x>=20)||(y<=0)||(y>=20))
	{
		printf("阁下莫不是老眼昏花了?\n");
		continue; 
	 }
	if(a[x][y]!=' ')
	{
		printf("这是何意?\n");
		continue;
	 }
	 a[x][y]='x';
	 break; 
	} 
	system("cls");
	qi(a);
}

人这里主要是判断落子处是否出界,或者落在已经有子的地方。

4.落子(机)

int judge(char a[20][20],int i,int j)
{
	int m=0;
	int n1=1;
	int n2=1;
	int x1,y1;
	int x2,y2;
	int X[8]={0,0,1,1,1,-1,-1,-1};
	int Y[8]={1,-1,0,1,-1,0,1,-1};
		for(int k=0;k<8;k++)
		{
			x1=i+X[k];
			y1=j+Y[k];
			while(a[x1][y1]=='o')
			{
				m=m+n1;
				x1=x1+X[k];
				y1=y1+Y[k];
				n1++;
				if((n1==4)&&(a[x1][y1]==' '))
				{
					m=m+100;
				}
				if((n1==3)&&(a[x1-4*X[k]][y1-4*Y[k]]=='o')&&(a[x1-5*X[k]][y1-5*Y[k]]==' ')&&(a[x1][y1]==' '))
				{
					m=m+100;
				}
				if((n1==3)&&(a[x1][y1]==' ')&&(a[x1-4*X[k]][y1-4*Y[k]]==' ')&&(a[x1-3*X[k]+X[k+1]][y1-3*Y[k]+Y[k+1]]=='o')&&(a[x1-3*X[k]+2*X[k+1]][y1-3*Y[k]+2*Y[k+1]]=='o')&&(a[x1-3*X[k]+3*X[k+1]][y1-3*Y[k]+3*Y[k+1]]==' '))
				{
					m=m+500;
				}
				if((n1==5)&&(a[x1][y1]=='x'))
				{
					m=m+20000;
				}
				if((n1==5)&&((x1==0)||(x1==20)||(y1==0)||(y1==20)))
				{
					m=m+20000;
				}
				if((n1==3)&&(a[x1-4*X[k]][y1-4*Y[k]]=='o')&&(a[x1-5*X[k]][y1-5*Y[k]]=='o'))
				{
					m=m+20000;
				}
				if((n1==4)&&(a[x1-5*X[k]][y1-5*Y[k]]=='o'))
				{
					m=m+20000;
				}
			}
			x2=i+X[k];
			y2=j+Y[k];
			while(a[x2][y2]=='x')
			{
				m=m+1; 
				m=m+n2;
				x2=x2+X[k];
				y2=y2+Y[k];
				n2++;
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]==' ')&&((a[x2][y2]=='o')||(a[x2-6*X[k]][y2-6*Y[k]]=='o')))
				{
					m=m+500;
				}
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]==' ')&&(a[x2][y2]==' '))
				{
					m=m+1000;
				}
				if((n2==4)&&(a[x2][y2]==' '))
				{
					m=m+1000;
				}
				if((n1==3)&&(a[x1][y1]==' ')&&(a[x1-4*X[k]][y1-4*Y[k]]==' ')&&(a[x1-3*X[k]+X[k+1]][y1-3*Y[k]+Y[k+1]]=='x')&&(a[x1-3*X[k]+2*X[k+1]][y1-3*Y[k]+2*Y[k+1]]=='x')&&(a[x1-3*X[k]+3*X[k+1]][y1-3*Y[k]+3*Y[k+1]]==' '))
				{
					m=m+3000;
				}
				if((n2==5)&&(a[x2][y2]=='o'))
				{
					m=m+6000;
				}
				if((n2==5)&&((x2==0)||(x2==20)||(y2==0)||(y2==20)))
				{
					m=m+6000;
				}
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]=='x'))
				{
					m=m+6000;
				}
				if((n2==4)&&(a[x2-5*X[k]][y2-5*Y[k]]=='x'))
				{
					m=m+6000;
				}
		    }
		    n1=1;
		    n2=1;
		}
	 return m;
}

void ai(char a[20][20])
{
	int max=0;
	int x=0;
	int y=0;
	int k=0;
	 for(int i=1;i<20;i++)
	 {
	 	for(int j=1;j<20;j++)
	 	{
	 		if(a[i][j]==' ')
	 		{
	 			int n=judge(a,i,j);
	 			if(n>max)
	 			{
	 				max=n;
	 				x=i;
	 				y=j;
				 }
			 }
		}
	 }
	 for(int i=1;i<20;i++)
	 {
	 	for(int j=1;j<20;j++)
	 	{
	 		if(a[i][j]==' ')
	 		{
	 			int m=judge(a,i,j);
	 			if(m==max)
	 			{
	 				t1[k]=i;
	 				t2[k]=j;
	 				k++;
				 }
			 }
		}
	 }
	 srand((unsigned)time(NULL));
	 int z=rand()%k;
	a[t1[z]][t2[z]]='o';
	system("cls");
	qi(a);
	printf("上一步棋为(%d,%d),凡人你对付的了吗?\n",t1[z],t2[z]);
}

机器部分应该是最难的地方,我写这段代码的时候才大一上,CSDN上大佬写的剪枝算法等等根本看不懂,后来无意看到一篇文章(已找不到),通过设置两个一维数组来模拟一个棋子上下左右,及四个斜对角的位置,通过不断运行,来判断该方向上的棋子数目,在根据其已有数目来赋以对应的权值,最后通过穷举所有位置,计算最大值。这种方法说不得高明,只是对于当时大一的我恰到好处,因为需要自行赋分,所以代码人的棋艺决定了AI的上限,比如我的水平较差,AI连进攻都不会。

5.判断是否落满

int full(char a[20][20])
{
	int b=1;
	for(int i=1;i<20;i++)
	{
		for(int j=1;j<20;j++)
		{
			if(a[i][j]==' ')
			{
				b=0;
				break;
			}
		}
    }
    return b;
}

6.判断输赢

char win(char a[20][20])
{
	for(int i=5;i<20;i++)
	{
		for(int j=1;j<16;j++)
		{
			if((a[i][j]==a[i-1][j+1])&&(a[i][j]==a[i-2][j+2])&&(a[i][j]==a[i-3][j+3])&&(a[i][j]==a[i-4][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
		}
    }
	for(int i=1;i<16;i++)
	{
		for(int j=1;j<16;j++)
		{
			if((a[i][j]==a[i+1][j])&&(a[i][j]==a[i+2][j])&&(a[i][j]==a[i+3][j])&&(a[i][j]==a[i+4][j])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if((a[i][j]==a[i][j+1])&&(a[i][j]==a[i][j+2])&&(a[i][j]==a[i][j+3])&&(a[i][j]==a[i][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if((a[i][j]==a[i+1][j+1])&&(a[i][j]==a[i+2][j+2])&&(a[i][j]==a[i+3][j+3])&&(a[i][j]==a[i+4][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if(full(a))
			{
				return '0';
			}
		}
	}
	return NULL;
}

判断输赢只是简单的穷举加规则,当有五个相同时,输出即可。

7.输出结果

void jieguo(char a[20][20])
{
	char d=win(a);
	if(d=='x')
	{
		printf("佩服佩服!"); 
	}
	if(d=='o')
	{
		printf("就这点手段?"); 
	}
	if(d=='0')
	{
		printf("竟然与我一成功力打成平手!!!"); 
	} 
}

8.包装组合

void game(char a[20][20])
{
	InitBoard(a,20,20);//初始化
	qi(a);//打印棋盘
	while(1)
	{
	    ren(a);
	    Sleep(1000);//防止下的太快,反应不过来
	    char c=win(a);//判断输赢
	    if(c!=NULL)
	    {
	    	jieguo(a);
	    	break;
		}
	    ai(a);
	    Sleep(1000);
	    c=win(a);//AI下完同样判断
	    if(c!=NULL)
	    {
	    	jieguo(a);
	    	break;
		}
	}
}

9.主函数

int main()
{
	printf("来一盘血脉贲张的五子棋大战吧!!!\n");
	printf("我来会会你:1\n");
	printf("告辞:0\n");
	char a[20][20];
	char c;
	c=_getch();
	while(c=='1')
	{
		game(a);
		printf("小儿可敢再战?\n");
		printf("今日便与你这厮大战三百回合:1\n");
		printf("我妈喊我回家吃饭:0\n");
		c=_getch(); 
	}
	return 0; 
}

下面将完整代码全部写出,方便复制(有没有前面一点一点复制的?这算水字数吗?)

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <Windows.h>
#include <ctime>
#include <cstdlib>
int t1[361];
int t2[361];
void InitBoard(char a[20][20],int row,int col)
{
    memset(a,' ',row*col*sizeof(char));
}
void qi(char a[20][20])
{
	for(int i=1;i<20;i++)
		{
			if(i==1)
			{
				printf("  ");
				for(int m=0;m<19;m++)
				{
					printf("|%02d",m+1);
				}
				printf("\n");
				for(int n=0;n<20;n++)
				{
					printf("---");
				}
			}
			printf("\n");
			printf("%02d",i);
			for(int j=1;j<20;j++)
			{
				if(j!=19)
				{
					printf("| %c",a[i][j]);
				}
				if(j==19)
				{
					printf("| %c|",a[i][j]);
				}
			}
			printf("\n");
			for(int k=0;k<20;k++)
			{
				printf("-- ");
			}
		}
		printf("\n");
}
void ren(char a[20][20])
{
	while(1)
	{
	printf("请选择落子行列:");
	int x,y;
	scanf("%d%d",&x,&y);
	if((x<=0)||(x>=20)||(y<=0)||(y>=20))
	{
		printf("阁下莫不是老眼昏花了?\n");
		continue; 
	 }
	if(a[x][y]!=' ')
	{
		printf("这是何意?\n");
		continue;
	 }
	 a[x][y]='x';
	 /*locateCursor(3*y+1,2*x+3);
	 printf("x");
	 locateCursor(0,44+p);*/
	 break; 
	} 
	system("cls");
	qi(a);
}
int judge(char a[20][20],int i,int j)
{
	int m=0;
	int n1=1;
	int n2=1;
	int x1,y1;
	int x2,y2;
	int X[8]={0,0,1,1,1,-1,-1,-1};
	int Y[8]={1,-1,0,1,-1,0,1,-1};
		for(int k=0;k<8;k++)
		{
			x1=i+X[k];
			y1=j+Y[k];
			while(a[x1][y1]=='o')
			{
				m=m+n1;
				x1=x1+X[k];
				y1=y1+Y[k];
				n1++;
				if((n1==4)&&(a[x1][y1]==' '))
				{
					m=m+100;
				}
				if((n1==3)&&(a[x1-4*X[k]][y1-4*Y[k]]=='o')&&(a[x1-5*X[k]][y1-5*Y[k]]==' ')&&(a[x1][y1]==' '))
				{
					m=m+100;
				}
				if((n1==3)&&(a[x1][y1]==' ')&&(a[x1-4*X[k]][y1-4*Y[k]]==' ')&&(a[x1-3*X[k]+X[k+1]][y1-3*Y[k]+Y[k+1]]=='o')&&(a[x1-3*X[k]+2*X[k+1]][y1-3*Y[k]+2*Y[k+1]]=='o')&&(a[x1-3*X[k]+3*X[k+1]][y1-3*Y[k]+3*Y[k+1]]==' '))
				{
					m=m+500;
				}
				if((n1==5)&&(a[x1][y1]=='x'))
				{
					m=m+20000;
				}
				if((n1==5)&&((x1==0)||(x1==20)||(y1==0)||(y1==20)))
				{
					m=m+20000;
				}
				if((n1==3)&&(a[x1-4*X[k]][y1-4*Y[k]]=='o')&&(a[x1-5*X[k]][y1-5*Y[k]]=='o'))
				{
					m=m+20000;
				}
				if((n1==4)&&(a[x1-5*X[k]][y1-5*Y[k]]=='o'))
				{
					m=m+20000;
				}
			}
			x2=i+X[k];
			y2=j+Y[k];
			while(a[x2][y2]=='x')
			{
				m=m+1; 
				m=m+n2;
				x2=x2+X[k];
				y2=y2+Y[k];
				n2++;
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]==' ')&&((a[x2][y2]=='o')||(a[x2-6*X[k]][y2-6*Y[k]]=='o')))
				{
					m=m+500;
				}
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]==' ')&&(a[x2][y2]==' '))
				{
					m=m+1000;
				}
				if((n2==4)&&(a[x2][y2]==' '))
				{
					m=m+1000;
				}
				if((n1==3)&&(a[x1][y1]==' ')&&(a[x1-4*X[k]][y1-4*Y[k]]==' ')&&(a[x1-3*X[k]+X[k+1]][y1-3*Y[k]+Y[k+1]]=='x')&&(a[x1-3*X[k]+2*X[k+1]][y1-3*Y[k]+2*Y[k+1]]=='x')&&(a[x1-3*X[k]+3*X[k+1]][y1-3*Y[k]+3*Y[k+1]]==' '))
				{
					m=m+3000;
				}
				if((n2==5)&&(a[x2][y2]=='o'))
				{
					m=m+6000;
				}
				if((n2==5)&&((x2==0)||(x2==20)||(y2==0)||(y2==20)))
				{
					m=m+6000;
				}
				if((n2==3)&&(a[x2-4*X[k]][y2-4*Y[k]]=='x')&&(a[x2-5*X[k]][y2-5*Y[k]]=='x'))
				{
					m=m+6000;
				}
				if((n2==4)&&(a[x2-5*X[k]][y2-5*Y[k]]=='x'))
				{
					m=m+6000;
				}
		    }
		    n1=1;
		    n2=1;
		}
	 return m;
}
void ai(char a[20][20])
{
	int max=0;
	int x=0;
	int y=0;
	int k=0;
	 for(int i=1;i<20;i++)
	 {
	 	for(int j=1;j<20;j++)
	 	{
	 		if(a[i][j]==' ')
	 		{
	 			int n=judge(a,i,j);
	 			if(n>max)
	 			{
	 				max=n;
	 				x=i;
	 				y=j;
				 }
			 }
		}
	 }
	 for(int i=1;i<20;i++)
	 {
	 	for(int j=1;j<20;j++)
	 	{
	 		if(a[i][j]==' ')
	 		{
	 			int m=judge(a,i,j);
	 			if(m==max)
	 			{
	 				t1[k]=i;
	 				t2[k]=j;
	 				k++;
				 }
			 }
		}
	 }
	 srand((unsigned)time(NULL));
	 int z=rand()%k;
	a[t1[z]][t2[z]]='o';
	system("cls");
	qi(a);
	printf("上一步棋为(%d,%d),凡人你对付的了吗?\n",t1[z],t2[z]);
}
int full(char a[20][20])
{
	int b=1;
	for(int i=1;i<20;i++)
	{
		for(int j=1;j<20;j++)
		{
			if(a[i][j]==' ')
			{
				b=0;
				break;
			}
		}
    }
    return b;
}
char win(char a[20][20])
{
	for(int i=5;i<20;i++)
	{
		for(int j=1;j<16;j++)
		{
			if((a[i][j]==a[i-1][j+1])&&(a[i][j]==a[i-2][j+2])&&(a[i][j]==a[i-3][j+3])&&(a[i][j]==a[i-4][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
		}
    }
	for(int i=1;i<16;i++)
	{
		for(int j=1;j<16;j++)
		{
			if((a[i][j]==a[i+1][j])&&(a[i][j]==a[i+2][j])&&(a[i][j]==a[i+3][j])&&(a[i][j]==a[i+4][j])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if((a[i][j]==a[i][j+1])&&(a[i][j]==a[i][j+2])&&(a[i][j]==a[i][j+3])&&(a[i][j]==a[i][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if((a[i][j]==a[i+1][j+1])&&(a[i][j]==a[i+2][j+2])&&(a[i][j]==a[i+3][j+3])&&(a[i][j]==a[i+4][j+4])&&(a[i][j]!=' '))
			{
				return a[i][j];
			}
			else if(full(a))
			{
				return '0';
			}
		}
	}
	return NULL;
}
void jieguo(char a[20][20])
{
	char d=win(a);
	if(d=='x')
	{
		printf("佩服佩服!"); 
	}
	if(d=='o')
	{
		printf("就这点手段?"); 
	}
	if(d=='0')
	{
		printf("竟然与我一成功力打成平手!!!"); 
	} 
}
void game(char a[20][20])
{
	InitBoard(a,20,20);
	qi(a);
	while(1)
	{
	    ren(a);
	    Sleep(1000);
	    char c=win(a);
	    if(c!=NULL)
	    {
	    	jieguo(a);
	    	break;
		}
	    ai(a);
	    Sleep(1000);
	    c=win(a);
	    if(c!=NULL)
	    {
	    	jieguo(a);
	    	break;
		}
	}
}
int main()
{
	printf("来一盘血脉贲张的五子棋大战吧!!!\n");
	printf("我来会会你:1\n");
	printf("告辞:0\n");
	char a[20][20];
	char c;
	c=_getch();
	while(c=='1')
	{
		game(a);
		printf("小儿可敢再战?\n");
		printf("今日便与你这厮大战三百回合:1\n");
		printf("我妈喊我回家吃饭:0\n");
		c=_getch(); 
	}
	return 0; 
}

感谢观看!

  • 14
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值