完成一个三子棋项目首先我们要知道要学会对头文件和不同源文件功能的划分首先创建一个头文件
两个源文件如图
其中我们将所有要引用函数的头文件放入头文件.h中主逻辑里面放的就是一个程序的主要实行逻辑而在实行这个逻辑的时候我们肯定要自定义一些函数那么定义函数的任务也放入那个头文件中而实现那个代码的任务就放入到那个另外的源文件中了。
首先我们要先完成我们的主函数
int main()
{
int input = 0;
do
{
menu();
printf("请选择\n");
scanf("%d",&input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏");
break;
default:
printf("输入无法识别,请重新输入");
}while(input)//这样我们就将我们的主函数完成了其中的game函数就是我们要完成的三子棋函数而menu函数就是一个简单的菜单函数
return 0;
}
然后我们来完成我们的menu函数因为我们只是需要这个函数打印出一个菜单不需要它返回给我们什么具体的值所以我们要在自定义函数的前面加void.同时我们也不需要传给它什么值所以后面的括号是空的
void menu()
{
printf("*********************\n");
printf("*******1.play********\n");
printf("*******0.rxit********\n");
printf("*********************\n");
}//这里使用1和0也是有用的,因为在主函数那块有一个do while语句当input为0时判断do while循环失败退出游戏而当输入的不是1也不是0时while内判断条件满足非0所以循环
接下来便是我们的大头详细的如何实现三子棋的game()函数首先我们观察一个棋盘如下图
假设把那些横线和竖线删除的话很明显这是一个二维数组那么我们便先创建一个二维数组接下来的难题就是如何打印这个棋盘呢?若使用下面的这种书写方法那么当我们日后想要改变这个棋盘的大笑的时候你就会发现很麻烦你要把每一个数组里的3给改了那么我们便可以在.h文件中定义一个标识符来代表常量当我们日后想要改变棋盘的大小的时候只需要改变.h文件一处即可如图
那么我们下面的这个代码便可以改写了
void game()
{
char ki[3][3];
}
void game()
{
char ki[ROW][COL];
}
这个代码代表的意思与上一个代码代表的意思是一样的都是创建了一个3行3列的字符数组
接下来我们便要先将我们的数组给初始化若不初始化数组那么局部变量在栈上,各数组元素的值将是随机数。对于我们打印棋盘十分的不方便。接下来我们便要创建一个自定义函数这个自定义具体的实现我们便放入三子棋.c的原文件中同时在.h的头文件中声明这个函数同时为了能够让代码正常的运行我们要让两个源文件都要包含.h的头文件如图
然后我们在.c文件中实现这个zero函数。
void zero(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
ki[i][k] = ' ';
}
}
}
使用遍历数组的方式我们便成功的完成了数组的初始化,接下来便是打印棋盘与上面一样我们一样创建一个打印函数同时实现它
void printfg(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
printf(" %c ", ki[i][k]);
if (k < col - 1)//让|在最后一次打印第一排的时候不打印
{
printf("|");//先将空格字符空格打印出来然后第一行每一次打印完前面后加一个|但最后一个不用加|下面的同理
}
}
printf("\n");换行开始打印下面的横线
if (i < row - 1)//与上面的一样是为了不打印最后一行的横线
{
for (k = 0; k < col; k++)
{
printf("---");
if (k < col - 1)
{
printf("|");
}
}
}
printf("\n");//在彻底完成第一行后换行开始下一行的打印
}
}
这样我们便能将一个棋盘答应出来运行如下图
那么加下来就该是我们玩家的移动了与上面的函数一样之后我们在三子棋.c中详细的实现它
void playermove(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
while (1)
{
printf("请输入要下的坐标:<\n");
scanf("%d %d", &i, &k);
if (i<=row&&i>=1 && k<=col&&k>=1)//这里的目的就是判断玩家下的棋是否在棋盘的范围内
{
if (ki[i - 1][k - 1] == ' ')//判断这个位置是否是空格有没有被占用。
{
ki[i - 1][k - 1] = '*';
break;
}
else
{
printf("此坐标已被占用。");
}
}
else
printf("坐标非法请重新输入");
}
}
然后我们便要让电脑下棋但因为我只是一个还在学习c的萌新所以我这里就是用随机数的方式实现让电脑下棋的
void computermove(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
printf("电脑下棋:\n");
while (1)
{
i = rand() % row;//在使用这个函数的时候我们不仅要加入头文件stdlib.h同时要在主函数中使用srand time来配置随机数
k = rand() % col;//模的目的是为了让得出的随机数在1到3之间
if (ki[i - 1][k - 1] == ' ')
{
ki[i - 1][k - 1] = '#';
break;
}
}
}
现在我们的主函数便变成了这样
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择-<:");
scanf("%d", &input);
switch (ak)
{
case 1:
game();
break;
case 0:
printf("退出游戏");
break;
default:
printf("选择错误请重新选择");
}
} while (input);
return 0;
在完成了这些之后我们便要完成最后一步那就是判断输赢和是否为平局或是继续往下下棋同时我们在这里规定的是电脑赢返回#玩家赢返回*平局返Q继续返回C这样做的好处就是在返回给game函数判断的时候就不用再考虑是哪个赢了若是玩家赢了那么返回的是代表玩家的符号电脑赢了返回的是电脑的符号
char Iswin(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
if (ki[i][0] == ki[i][1] && ki[i][0] == ki[i][2] && ki[i][0] != ' ')
{
return ki[i][0];
}
}
for (k = 0; k < col; k++)
{
if (ki[0][k] == ki[1][k] && ki[2][k] == ki[0][k] && ki[0][k] != ' ')
{
return ki[0][k];
}
}
if (ki[0][0] == ki[1][1] && ki[2][2] == ki[0][0] && ki[0][0] != ' ')
{
return ki[0][0];
}
if (ki[0][2] == ki[1][1] && ki[0][2] == ki[2][0] && ki[2][0] != ' ')
{
return ki[0][2];
}
if (Isfull(ki, row, col))//这里我又创建了一个函数目的就是在上面的情况都不存在得时候判断这个棋盘是否满了
{
return 'Q';
}
else
return 'C';
}
int Isfull(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
if (ki[i][k] == ' ')
{
return 0;//如果
}
}
}
return 1;
}
最后再game函数那里创建一个变量储存这个返回值最后一个完整的game函数如下
void game()
{
char qipan[ROW][COL] = {0};
zero(qipan, ROW, COL);//目的为使每个棋盘的位置被空格占据即初始化棋盘
printfg(qipan, ROW, COL);//打印棋盘
char ret = 0;
while (1)
{
playermove(qipan, ROW, COL);//玩家下棋
printfg(qipan, ROW, COL);//打印棋盘
ret =Iswin(qipan, ROW, COL);//判断是否出现输赢还是继续还是平局
if (ret != 'C')
{
break;
}
computermove(qipan, ROW, COL);//电脑下棋
printfg(qipan, ROW, COL);//打印棋盘
ret = Iswin(qipan, ROW, COL);//判断是否出现输赢还是继续还是平局
if (ret != 'C')
{
break;
}
}
if (ret == '#')
printf("很遗憾,你输了\n");
else if (ret == '*')
printf("恭喜你,你赢了\n");
else if (ret == 'Q')
printf("平局\n");
}
这样一个简单的三子棋游戏就完成了
下面的是三子棋主逻辑.c中的代码
#include"三子棋.h"
void menu()
{
printf("************************\n");
printf("*********1.play*********\n");
printf("*********0.exit*********\n");
printf("************************\n");
printf("************************\n");
}
void game()
{
char qipan[ROW][COL] = {0};
zero(qipan, ROW, COL);//目的为使每个棋盘的位置被空格占据即初始化棋盘
printfg(qipan, ROW, COL);//打印棋盘
char ret = 0;
while (1)
{
playermove(qipan, ROW, COL);//玩家下棋
printfg(qipan, ROW, COL);//打印棋盘
ret =Iswin(qipan, ROW, COL);//判断是否出现输赢还是继续还是平局
if (ret != 'C')
{
break;
}
computermove(qipan, ROW, COL);//电脑下棋
printfg(qipan, ROW, COL);//打印棋盘
ret = Iswin(qipan, ROW, COL);//判断是否出现输赢还是继续还是平局
if (ret != 'C')
{
break;
}
}
if (ret == '#')
printf("很遗憾,你输了\n");
else if (ret == '*')
printf("恭喜你,你赢了\n");
else if (ret == 'Q')
printf("平局\n");
}
int main()
{
int ak = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择-<:");
scanf("%d", &ak);
switch (ak)
{
case 1:
game();
break;
case 0:
printf("退出游戏");
break;
default:
printf("选择错误请重新选择");
}
} while (ak);
return 0;
}
下面是三子棋.c中的代码
#include"三子棋.h"
void zero(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
ki[i][k] = ' ';
}
}
}
void printfg(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
printf(" %c ", ki[i][k]);
if (k < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (k = 0; k < col; k++)
{
printf("---");
if (k < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
void playermove(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
while (1)
{
printf("请输入要下的坐标:<\n");
scanf("%d %d", &i, &k);
if (i<=row&&i>=1 && k<=col&&k>=1)
{
if (ki[i - 1][k - 1] == ' ')
{
ki[i - 1][k - 1] = '*';
break;
}
else
{
printf("此坐标已被占用。");
}
}
else
printf("坐标非法请重新输入");
}
}
void computermove(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
printf("电脑下棋:\n");
while (1)
{
i = rand() % row;
k = rand() % col;
if (ki[i - 1][k - 1] == ' ')
{
ki[i - 1][k - 1] = '#';
break;
}
}
}
int Isfull(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (k = 0; k < col; k++)
{
if (ki[i][k] == ' ')
{
return 0;
}
}
}
return 1;
}
char Iswin(char ki[ROW][COL], int row, int col)
{
int i = 0;
int k = 0;
for (i = 0; i < row; i++)
{
if (ki[i][0] == ki[i][1] && ki[i][0] == ki[i][2] && ki[i][0] != ' ')
{
return ki[i][0];
}
}
for (k = 0; k < col; k++)
{
if (ki[0][k] == ki[1][k] && ki[2][k] == ki[0][k] && ki[0][k] != ' ')
{
return ki[0][k];
}
}
if (ki[0][0] == ki[1][1] && ki[2][2] == ki[0][0] && ki[0][0] != ' ')
{
return ki[0][0];
}
if (ki[0][2] == ki[1][1] && ki[0][2] == ki[2][0] && ki[2][0] != ' ')
{
return ki[0][2];
}
if (Isfull(ki, row, col))
{
return 'Q';
}
else
return 'C';
}
下面的是三子棋.h中的代码
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void zero(char ki[ROW][COL], int row, int col);
void printfg(char ki[ROW][COL], int row, int col);
void playermove(char ki[ROW][COL], int row, int col);
void computermove(char ki[ROW][COL], int row, int col);
char Iswin(char ki[ROW][COL], int row, int col);