C语言实现五子棋小游戏
开始界面的实现
引言
每次当我们进入游戏时总会有一个开始导航界面,可以通过选择相应的功能来进行帮助、选择游戏模式、设置声音开关以及颜色等。尽管我们是做一个基础版的五子棋小游戏工程,但是麻雀虽小五脏得全。
特殊头文件简单介绍
conio.h不是C标准库中的头文件,在C standard library,ISO C 和POSIX标准中均没有定义。conio是Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等。
2、windows.h是计算机中的一个头文件。当你要使用与窗口相关的函数的时候, 如messagebox( ), FindWindow( ), SendMessage( ) 等等, windows.h是一个很重要的头文件。
特殊函数的介绍
1、坐标函数
void gotoxy(int x,int y)
{
COORD c;
c.X=x;
c.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
这段函数中比较特别为第一句和最后一句,COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标。SetConsoleCursorPosition是一个计算机函数,如果用户定义了 COORD pos,那么pos其实是一个结构体变量,其中X和Y是它的成员,通过修改pos.X和pos.Y的值就可以实现光标的位置控制。
2、颜色函数
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
通过调用函数可以改变控制台输出字体的颜色。
3、游戏开始界面函数
void welcometogame()
{
int n;
int i,j=1;
gotoxy(23,2);
color(13);
printf("五 子 棋 游 戏");
color(15);//白色边框
for(i=6;i<=12;i++)//输出上下边框
{
for(j=7;j<=54;j++)//输出左右边框
{
gotoxy(j,i);
if(i==6||i==12)
{
printf("-");
}
else if(j==7||j==54)
{
printf("|");
}
}
}
color(14);
gotoxy(15,8);
printf("1.开始游戏");
gotoxy(35,8);
printf("2.游戏说明");
gotoxy(15,10);
printf("3.退出游戏");
gotoxy(19,13);
color(12);
printf("请选择[1 2 3]:[ ]\b\b");
color(14);
scanf("%d",&n);
switch (n)
{
case 1:
system("cls");
display();
break;
case 2:
system("cls");
explation();
break;
case 3:
exit(0);
break;
}
}
通过调用定义的坐标函数和改变字体函数来实现让界面更加的美观,在main函数里调用该函数运行结果如下图:
创建棋盘及实现下棋
1、基本思路
首先定义棋盘大小的数组(这里博主定义的20X20的),棋盘就可以看成是一个20X20的坐标,每一个坐标都有3种状态(0:黑棋 1:白棋 2:没有棋子)我们就可以根据坐标的标志数字来判断该坐标的状态,同时来创建棋盘。首先创建一个没有棋子的棋盘则需要给每一个坐标赋值为2。然后提示下棋(根据提示从键盘输入相对应的坐标)下棋以后坐标状态改变,如果有棋子则不输入方格,若没有棋子则输入方格。这就说明这个棋盘是一个动态的不断地变换不断的,根据坐标的状态来改变棋盘的形状。一行一行的处理,边缘需要特殊处理。每次输入一次后要判断输赢,定义3个变量分别表示横向、纵向、斜向相关棋子的数量。分别判断横向是否赢、纵向是否赢、斜向是否赢如果有一个满足赢的条件则输出谁赢。
2、重要步骤代码
void display()
{
int i,j;//表示棋盘横纵坐标
int qipan[20][20];
int color=0;//0表示黑棋(圆圈),1表示白棋
int iTemp = 0,jTemp = 0,countTemp = 0;
int colorFlag = 0;
char op;
again:
for(i=0;i<20;i++)
for(j=0;j<20;j++)
qipan[i][j]=2;
while(1)
{
printf("请输入棋子位置(棋盘大小为20*20),如2,2: ");
scanf("%d,%d", &i,&j);
if(i<1 || i >20 || j<1 || j>20)
{
printf("输入的位置超出了棋盘的范围,请重新输入!\n");
continue;
}
if((2 != qipan[i-1][j-1]))
{
printf("提示:该位置已经有棋子了!\n");
fflush(stdin);
continue;
}
color=(color+1)%2;//获取棋盘棋子属性
qipan[i-1][j-1]=color;
system("cls");
for(i=1;i<=20;i++)
{
if(i==1)
{
if(qipan[i-1][0]==1)
printf("●");
if(qipan[i-1][0]==0)
printf("○");
if(qipan[i-1][0]==2)
printf("┌ ");
for(j=2;j<=19;j++)
{
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┬ ");
}
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┐ ");
printf("\n");
}
if(i<=19 && i>=2)
{
if(qipan[i-1][0]==1)
printf("●");
if(qipan[i-1][0]==0)
printf("○");
if(qipan[i-1][0]==2)
printf("├ ");
for(j=2;j<=19;j++)
{
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┼ ");
}
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┤ ");
printf("\n");
}
if(i==20)
{
if(qipan[i-1][0]==1)
printf("●");
if(qipan[i-1][0]==0)
printf("○");
if(qipan[i-1][0]==2)
printf("└ ");
for(j=2;j<=19;j++)
{
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┴ ");
}
if(qipan[i-1][j-1]==1)
printf("●");
if(qipan[i-1][j-1]==0)
printf("○");
if(qipan[i-1][j-1]==2)
printf("┘ ");
printf("\n");
}
}
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
if(2 != qipan[i][j] )
{
colorFlag = qipan[i][j];
countTemp = 1;
iTemp = i;
jTemp = j;
while((++jTemp<20 )&&( 5 != countTemp ))
{
if(colorFlag == qipan[i][jTemp])
{
countTemp++;
if(5 == countTemp)
{
if(0 == colorFlag)
{
printf("黑棋赢了!\n");
}
else if(1 == colorFlag)
{
printf("白棋赢了!\n");
}
goto whileEnd;
}
}
else
{
countTemp = 0;
break;
}
}
iTemp = i;
jTemp = j;
countTemp = 1;
while((++iTemp<20 )&&(5 !=countTemp))
{
if(colorFlag == qipan[iTemp][j])
{
countTemp++;
if(5 == countTemp)
{
if(0 == colorFlag)
{
printf("黑棋赢了!\n");
}
else if(1 == colorFlag)
{
printf("白棋赢了!\n");
}
goto whileEnd;
}
}
else
{
countTemp= 0;
break;
}
}
iTemp = i;
jTemp = j;
countTemp = 1;
while((++iTemp<20 )&&(++jTemp<20 )&&(5 !=countTemp))
{
if(colorFlag == qipan[iTemp][jTemp])
{
countTemp++;
if(5 == countTemp)
{
if(0 == colorFlag)
{
printf("黑棋赢了!\n");
}
else if(1 == colorFlag)
{
printf("白棋赢了!\n");
}
goto whileEnd;
}
}
else
{
countTemp = 0;
break;
}
}
iTemp = i;
jTemp = j;
countTemp = 1;
while((++iTemp>=0)&&(--jTemp>=0)&&(5 !=countTemp))
{
if(colorFlag ==qipan[iTemp][jTemp])
{
countTemp++;
if(5 == countTemp)
{
if(0 ==colorFlag)
{
printf("黑棋赢了!\n");
}
else if(1 == colorFlag)
{
printf("白棋赢了!\n");
}
goto whileEnd;
}
}
else
{
countTemp = 0;
break;
}
}
}
}
}
}
whileEnd:
printf("重新开始,还是退出?重新开始请按y/Y,退出请按任意键:");
fflush(stdin);
op = getchar();
if(('y' == op) ||( 'Y' == op))
{
system("cls");
printf("已经重新开始了,请输入第一颗棋子的坐标:\n\n\n");
goto again;
}
else
{
system("cls");
welcometogame();
}
}
3、界面一览
总结
因为是为了在STM32上实现五子棋,但是不知道五子棋的算法还有很多问题。通过C语言实现五子棋,知道了如何实现五子棋同时学到了更多的C语言知识,知道了之前不知道的头文件、函数等。同时也发现了很多问题,如何判断斜向连成5个棋子、如何实现下棋。通过网上搜索相关的程序借鉴、了解了相关的思想和方法。
但是还是有很多的不足,还有很多的功能待开发,如:悔棋、用键盘控制下棋位置、智能提示等功能。但是总体来说还是实现了基础的功能还是很开心的。实践是检验真理的唯一标准,通过实践才能发现问题、解决问题、在错误中成长。希望在移植到STM32上能够顺利。