实现思路:将整个实现编写到一个函数中,比将实现中部分代码直接写在main中的可移植性更好。开始创建一个名为初始主体的函数,此函数可用于多数游戏的实现。在此函数中,运用游戏菜单函数与选择,循环语句达到让用户选择是否游戏的功能。而三子棋游戏真正的实现,需要编写游戏函数,并将其置于初始主体中,这样方便随时更换游戏,而不动初始主体。
在游戏函数中首先创建“n*n”的二维字符数组,方便在三子棋盘中填入内容,考虑到更换游戏内容的原因,创建二维字符数组时使用全局变量ROW与COL。创建后首要任务是将此字符数组(棋盘)“清空”(字符数组清空函数),之后需要打印棋盘(打印当前棋盘函数)(在此函数中使用嵌套循环和条件控制达到打印棋行与分割行的效果),然后编写玩家下棋函数,下完棋后,需要打印当前棋盘,并及时判断当前情况(判断当前情况函数)(此函数可返回四种情况:平局,玩家胜,电脑胜和继续)(平局的情况还需要编写当前棋盘是否充满函数来判断)(此函数可返回内容并在判断当前情况函数中运用选择语句控制返回值来控制是否继续游戏),如果继续,则电脑下棋(电脑下棋函数)(在此函数中通过rand随机生成坐标并下棋,此处还需搭配srand与time函数使rand生成数真正随机),同理,下棋后也需打印棋盘并判断当前局势。注意:玩家下棋与电脑下棋都在一个循环中,当判断当前情况函数返回值为非继续时,跳出该循环并根据函数返回值用选择语句控制打印最后内容。
#include<stdio.h>
#include<stdlib.h>//与srand库函数配套
#include<time.h>//与time库函数配套
#define ROW 3
#define COL 3//为了实现多子棋的变换,使用全局变量实现多处改变
void menu()
{
printf("**********************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("**********************\n");
}
void qkong(char sz[ROW][COL],int row,int col)//形参为二维数组时,必须将行列规格标准出来,并且使用时只需要数组的名字。
{
int i,j;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
sz[i][j]=' ';
}
}
}//将目标数组的全部元素变为空格,在棋盘上体现为清零
void dying(char sz[ROW][COL],int row,int col)
{
int i,j;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
printf(" %c ",sz[i][j]);//棋盘视觉实现
if(j<col-1)//控制结尾不多余打印
printf("|");
}
printf("\n");
if(i<row-1)//打印分割行,控制多余打印
{
for(j=0;j<col;j++)
{
printf("---");
if(j<col-1)//控制结尾不多余打印
printf("|");
}
}
printf("\n");//打印棋行
}
}
void wanjia(char sz[ROW][COL],int row,int col)
{
int x,y;
while(1)//将玩家输入信息规范
{
printf("玩家请下棋:");
scanf("%d %d",&x,&y);
if(x>=1&&x<=row&&y>=1&&y<=col)//将玩家输入信息规范
{
if(sz[x-1][y-1]==' ')
{
sz[x-1][y-1]='*';
break; //跳出死循环
}
}
else printf("该棋格无法下棋,请重新输入:");
}
}
void computer(char sz[ROW][COL],int row,int col)
{
int x,y;
printf("电脑下棋\n");
while(1)//规范信息
{
x=rand()%row;//产生数在闭区间0到row-1里面
y=rand()%col;
if(sz[x][y]==' ')
{
sz[x][y]='#';
break;
}
}
}
int iffull(char sz[ROW][COL],int row,int col)
{
int i,j;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
if(sz[i][j]==' ')
return 1;//预示棋盘未填满
}
}
return 0;
}
char panduan(char sz[ROW][COL],int row,int col)
{
int i,j,num;
for(i=0;i<row;i++)
{
if(sz[i][0]==sz[i][1]&&sz[i][1]==sz[i][2]&&sz[i][1]!=' ')
return sz[i][1];
}//检查每列
for(i=0;i<col;i++)
{
if(sz[0][i]==sz[1][i]&&sz[1][i]==sz[2][i]&&sz[1][i]!=' ')
return sz[1][i];
}//检查每行
if(sz[0][0]==sz[1][1]&&sz[1][1]==sz[2][2]&&sz[1][1]!=' ')
return sz[1][1];
if(sz[0][2]==sz[1][1]&&sz[1][1]==sz[2][0]&&sz[1][1]!=' ')
return sz[1][1];//检查两个对角线
num=iffull(sz,ROW,COL);
if(num==0)
return 'p';//填满,判断平局
return 'j';//继续游戏
}
void game()
{
printf("进入游戏\n");
char sz[ROW][COL],linshi;
qkong(sz,ROW,COL);//清空棋盘
dying(sz,ROW,COL);//打印棋盘,视觉实现
while(1)
{
wanjia(sz,ROW,COL);//玩家下棋
dying(sz,ROW,COL);//打印视觉实现
linshi=panduan(sz,ROW,COL);
if(linshi!='j') //判断是否继续
break;
computer(sz,ROW,COL);//电脑下棋
dying(sz,ROW,COL);//打印视觉实现
linshi=panduan(sz,ROW,COL);
if(linshi!='j') //判断是否继续
break;
}
if(linshi=='*')
printf("玩家胜\n");
if(linshi=='#')
printf("电脑胜\n");
if(linshi=='p')
printf("平局\n"); //判断情况
}
void test()
{
int input;
srand((unsigned int)time(NULL));
//time函数返回值是从初始时间到现在的时间数,简称时间戳,其中的参数(空指针NULL)使time在执行时不需要对内存申请空间
//srand函数是随机数发生器的初始化函数,参数一直变化可以使本题中rand函数随机出不同的值
do{
menu();
printf("请选择:");
scanf("%d",&input);
switch(input)//实现玩家选择
{
case 1:game();break;
case 0:printf("游戏结束\n");break;
default :printf("选择错误请重新输入\n");break;
}
}while(input);//因为循环至少需要执行一次,可以用dowhile语句,巧妙运用input实现循环开始与结束。
}
int main()
{
test();//编写一个函数将整个三子棋实现包括起来
return 0;
}