目录
一、文件的创建
二、玩家游戏界面的创建
1. 菜单函数的创建
2. 玩家选择的创建
三、游戏的进程与判断输赢条件
1. 游戏规则
2. 棋盘的定义
3. 游戏棋盘的初始化
4. 打印出棋盘格式
5. 玩家进行游戏
6.判断游戏结局(
1. 测试一行能不能赢
2. 测试一列能不能赢
3. 测试两个对角线能不能赢
)
四、加强部分
五、代码部分
game.c
game.h
test.c
一、文件的创建
我们可以创建三个文件,两个源文件,一个头文件。 头文件game.c用来声明函数,源文件test.c用来测试,game.c文件用来实现游戏函数 |
二、玩家游戏界面的创建
1. 菜单函数的创建
这里我们简单编辑一个菜单函数,打印出一个方便于玩家选择的界面
void menu()
{
printf("*********************\n");
printf("********1.play*******\n");
printf("********0.exit*******\n");
printf("*********************\n");
}
测试打印的结果为
2. 菜单函数创建完之后,来创建玩家选择函数,让玩家进行选择
int n = 0;
do//采用do-while循环,因为玩家最少进行一次游戏
{
menu();//菜单函数
scanf_s("%d", &n);//让玩家输入数字,进行选择
switch (n)//判断玩家输入满足下面哪一个条件
{
case 1:
printf("三子棋游戏:\n");
game();
break;//玩家输入1就打印三子棋游戏字样,并且竟然game函数进行三子棋游戏。游戏结束后自动跳出,玩家重新选择是否继续游戏
case 0:
printf("退出游戏");
break;//玩家输入0,则退出游戏
default :
printf("输入错误,请重新输入:");//玩家如果输入1和0之外的元素,则告诉玩家输入错误,请重新输入元素
break;
}
} while (n);//;不能掉
将玩家选择界面创建好了放在主函数main里面
int main()
{
int n = 0;
do//采用do-while循环,因为玩家最少进行一次游戏
{
menu();//菜单函数
scanf_s("%d", &n);//让玩家输入数字,进行选择
switch (n)//判断玩家输入满足下面哪一个条件
{
case 1:
printf("三子棋游戏:\n");
game();
break;//玩家输入1就打印三子棋游戏字样,并且竟然game函数进行三子棋游戏。游戏结束后自动跳出,玩家重新选择是否继续游戏
case 0:
printf("退出游戏");
break;//玩家输入0,则退出游戏
default :
printf("输入错误,请重新输入:");//玩家如果输入1和0之外的元素,则告诉玩家输入错误,请重新输入元素
break;
}
} while (n);//;不能掉
}
主函数编辑完之后接下来就进入game函数,也就是游戏环节,开始编辑游戏环节代码
三、游戏的进程与判断输赢条件
1. 游戏规则
2. 棋盘的定义
三子棋棋盘是3*3的格式,但是要注意是“井”字型,周围都是开口型的
#define ROW 3 // 3是棋盘的行数,可以随意改变数字
#define COL 3 // 3是棋盘的列数,可以随意改变数字
在头文件game.h里声明,因为后面要用到很多次,我们在game.c和test.c里面引用头文件就行了,所以我们为了方便可以在头文件把所有要使用的函数的声明一下,然后直接引用就行
声明stdio库函数
#define ROW 3 // 3是棋盘的行数,可以随意改变数字
#define COL 3 // 3是棋盘的列数,可以随意改变数字
#include
引用头文件,要加" "号
#include"game.h"
现在创建一个二维数组来定义棋盘,在test.c的game函数里定义
char qp[ROW][COL] = { 0 };//定义棋盘时,ROW也就是行可以省,但是COL也就是列不能省,推荐大家都带上
3. 游戏棋盘的初始化
定义一个函数进行传参
initqp(qp, ROW, COL);//初始化棋盘,不管之前棋盘里放了什么,全部都初始化为空格
在头文件里接收
//初始化棋盘
void initqp(char qp[ROW][COL],int row,int col);//形参要小写
在game.c文件里实现,将定义的二维数组棋盘全部初始化为空格
#include"game.h"
void initqp(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
qp[i][j] = ' ';
}
}
}
初始化完棋盘后就可以打印出棋盘格式
4. 打印出棋盘格式
棋盘图像如图:
//棋盘:
// | |
//---|---|---
// | |
//---|---|---
// | |
test.c:
displayqp(qp,ROW,COL);//打印棋盘
game.h:
//打印棋盘
void displayqp(char qp[ROW][COL], int row, int col);
game.c:
void displayqp(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;//定义两个变量用来遍历数组
for (i = 0; i < row ; i++)//确定要打印多少行
{
for (j = 0; j < col; j++)//打印一行数据
{ //打印行时,可以把 | | 看成一组数据
// ---|---|---
printf(" %c ", qp[i][j]);//%c左右两个位置是空格,确保元素在中间位置
if (j < col - 1)//避免打印出棋盘最右边的一行|
{
printf("|");
}
}//此时打印出的是: | |
printf("\n");//和下面的printf("\n")共同把棋盘展开打印,否则棋盘会被打印在一行上面,就像下面那样:
//未输入printf("\n")的棋盘: | | ---|---|--- | | ---|---|--- | |
if (i < row - 1)//打印分割行
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)//避免打印出第3行的分割行
{
printf("|");
}//此时打印出的是:---|---|---
}
printf("\n");
}
}
}
测试棋盘图像
5. 玩家进行游戏
玩家下一步,就打印一次棋盘状况
test.c:
player(qp,ROW,COL);//玩家下棋
displayqp(qp, ROW, COL);//打印棋盘
game.h:
//玩家走
void player(char qp[ROW][COL], int row, int col);
game.c:
void player(char qp[ROW][COL], int row, int col)
{
int x = 0;//定义两个变量来表明玩家落子的位置
int y = 0;//x,y是横纵坐标
printf("玩家走:\n");
while (1)//坐标合法就跳出
{
printf("请输入下的坐标:");
scanf_s("%d%d", &x, &y);//玩家输入x,y坐标
//判断x,y坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家不知道下标是从0开始的,所以x,y都要从1开始
{
if (qp[x - 1][y - 1] == ' ')//x-1,y-1才对应到数组里面的元素
{
qp[x - 1][y - 1] = '*';//玩家落子,下一个*
break;
}
else
{
printf("该坐标已被占用\n");//这个位置已经有棋子了
}
}
else
{
printf("坐标非法,请重新输入:");//输入坐标超过棋盘范围
}
}
}
玩家走一步之后的图像
电脑进行自动下棋,并打印出棋盘
test.c:
computer(qp, ROW, COL);//电脑下棋
displayqp(qp, ROW, COL);//打印棋盘
game.h:
//电脑走
void computer(char qp[ROW][COL], int row, int col);
game.c:
void computer(char qp[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;//定义两个变量来表示电脑落子坐标
printf("电脑走:\n");//电脑随机走,哪里有空位就走哪里
while (1)
{
x = rand() % row;//电脑生成坐标在0到2之间,同时rand()%3余的值在0到2之间
y = rand() % col;
if (qp[x][y] == ' ')//x,y已经合法了,不用再减一
{
qp[x][y] = '#';//电脑落子,下一个#
break;
}
}
}
注意:game.c里面用到了rand,所以要引用相对应的函数
test.c:
int main()
{
int n = 0;
srand((unsigned int)time(NULL));//时间戳,用来生成随机,要引用time函数,该语句整局只用一次,所以可以放在开头处
//unsigned int 将time返回的值强制转化成无符号整形类型,用来作为srand随机数生成器
do//采用do-while循环,因为玩家最少进行一次游戏
{
menu();//菜单函数
game.h:
#define ROW 3 // 3是棋盘的行数,可以随意改变数字
#define COL 3 // 3是棋盘的列数,可以随意改变数字
#include
#include
#include
测试对弈下棋
6.判断游戏结局
情况1. 玩家或者电脑每次走一步就判断是否赢了
情况2. 棋盘满了,平局
game.h:
//可以告诉我们4种状态:
//1.玩家赢 -->'*'
//2.电脑赢 -->'#'
//3.平局 -->'P'
//4.游戏继续 -->'C'
char win(char qp[ROW][COL], int row, int col);//要返回字符,所以说要用char类型返回
test.c:
while (1)//无限循环下棋,直到出现下面的情况就跳出
{
player(qp,ROW,COL);//玩家下棋
displayqp(qp, ROW, COL);//打印棋盘
ret = win(qp, ROW, COL);//判断玩家是否赢了
if (ret != 'C')//如果返回的ret不是字符c
{
break;//跳出循环
}
computer(qp, ROW, COL);//电脑下棋
displayqp(qp, ROW, COL);//打印棋盘
ret = win(qp, ROW, COL);//判断电脑是否赢了
if (ret != 'C')//如果返回的ret不是字符c
{
break;//跳出循环
}
}
if (ret == '*')//ret返回字符*
{
printf("玩家赢\n");
}
else if (ret == '#')//ret返回字符#
{
printf("电脑赢\n");
}
else
{
printf("平局\n");//ret返回字符p
}
}
game.c:
//判断棋盘满没满,返回1表示满了,返回0表示没满
int full(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;//定义两个变量,表示棋盘格子横纵坐标
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (qp[i][j] == ' ')//棋盘上还存在空格
{
return 0;//棋盘没满
}
}
}
return 1;//棋盘满了
}
char win(char qp[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//判断3行
{
if (qp[i][0] == qp[i][1] && qp[i][1] == qp[i][2] && qp[i][1] != ' ')//判断第几行字符相同,排除游戏开始存在的空格
{
return qp[i][1];//返回*就表示同一行3个字符相同--->玩家赢,返回#,P,C同理
}
}
for (i = 0; i < col; i++)//判断3列
{
if (qp[0][i] == qp[1][i] && qp[1][i] == qp[2][i] && qp[1][i] != ' ')//判断第列行字符相同,排除游戏开始存在的空格
{
return qp[1][i];//返回*就表示同一行3个字符相同--->玩家赢,返回#,P,C同理
}
}
//判断两个对角线
if (qp[0][0] == qp[1][1] && qp[1][1] == qp[2][2] && qp[1][1] != ' ')
{
return qp[1][1];//返回* 就表示同一行3个字符相同--->玩家赢, 返回#,P,C同理
}
if (qp[2][0] == qp[1][1] && qp[1][1] == qp[2][2] && qp[1][1] != ' ')
{
return qp[1][1];//返回* 就表示同一行3个字符相同--->玩家赢, 返回#,P,C同理
}
//判断是否平局
if (1 == full(qp, ROW, COL))
{
return 'P';//返回字符P平局
}
return 'C';//返回字符C游戏继续
}
游戏试玩结果
四、加强部分
五、代码部分
game.c:
#include"game.h"
void initqp(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
qp[i][j] = ' ';
}
}
}
//棋盘:
// | |
//---|---|---
// | |
//---|---|---
// | |
void displayqp(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;//定义两个变量用来遍历数组
for (i = 0; i < row ; i++)//确定要打印多少行
{
for (j = 0; j < col; j++)//打印一行数据
{ //打印行时,可以把 | | 看成一组数据
// ---|---|---
printf(" %c ", qp[i][j]);//%c左右两个位置是空格,确保元素在中间位置
if (j < col - 1)//避免打印出棋盘最右边的一行|
{
printf("|");
}
}//此时打印出的是: | |
printf("\n");//和下面的printf("\n")共同把棋盘展开打印,否则棋盘会被打印在一行上面,就像下面那样:
//未输入printf("\n")的棋盘: | | ---|---|--- | | ---|---|--- | |
if (i < row - 1)//打印分割行
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)//避免打印出第3行的分割行
{
printf("|");
}//此时打印出的是:---|---|---
}
printf("\n");
}
}
}
void player(char qp[ROW][COL], int row, int col)
{
int x = 0;//定义两个变量来表明玩家落子的位置
int y = 0;//x,y是横纵坐标
printf("玩家走:\n");
while (1)//坐标合法就跳出
{
printf("请输入下的坐标:");
scanf_s("%d%d", &x, &y);//玩家输入x,y坐标
//判断x,y坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家不知道下标是从0开始的,所以x,y都要从1开始
{
if (qp[x - 1][y - 1] == ' ')//x-1,y-1才对应到数组里面的元素
{
qp[x - 1][y - 1] = '*';//玩家落子,下一个*
break;
}
else
{
printf("该坐标已被占用\n");//这个位置已经有棋子了
}
}
else
{
printf("坐标非法,请重新输入:");//输入坐标超过棋盘范围
}
}
}
void computer(char qp[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;//定义两个变量来表示电脑落子坐标
printf("电脑走:\n");//电脑随机走,哪里有空位就走哪里
while (1)
{
x = rand() % row;//电脑生成坐标在0到2之间,同时rand()%3余的值在0到2之间
y = rand() % col;
if (qp[x][y] == ' ')//x,y已经合法了,不用再减一
{
qp[x][y] = '#';//电脑落子,下一个#
break;
}
}
}
//判断棋盘满没满,返回1表示满了,返回0表示没满
int full(char qp[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;//定义两个变量,表示棋盘格子横纵坐标
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (qp[i][j] == ' ')//棋盘上还存在空格
{
return 0;//棋盘没满
}
}
}
return 1;//棋盘满了
}
char win(char qp[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//判断3行
{
if (qp[i][0] == qp[i][1] && qp[i][1] == qp[i][2] && qp[i][1] != ' ')//判断第几行字符相同,排除游戏开始存在的空格
{
return qp[i][1];//返回*就表示同一行3个字符相同--->玩家赢,返回#,P,C同理
}
}
for (i = 0; i < col; i++)//判断3列
{
if (qp[0][i] == qp[1][i] && qp[1][i] == qp[2][i] && qp[1][i] != ' ')//判断第列行字符相同,排除游戏开始存在的空格
{
return qp[1][i];//返回*就表示同一行3个字符相同--->玩家赢,返回#,P,C同理
}
}
//判断两个对角线
if (qp[0][0] == qp[1][1] && qp[1][1] == qp[2][2] && qp[1][1] != ' ')
{
return qp[1][1];//返回* 就表示同一行3个字符相同--->玩家赢, 返回#,P,C同理
}
if (qp[2][0] == qp[1][1] && qp[1][1] == qp[2][2] && qp[1][1] != ' ')
{
return qp[1][1];//返回* 就表示同一行3个字符相同--->玩家赢, 返回#,P,C同理
}
//判断是否平局
if (1 == full(qp, ROW, COL))
{
return 'P';//返回字符P平局
}
return 'C';//返回字符C游戏继续
}
game.h:
#define ROW 3 // 3是棋盘的行数,可以随意改变数字
#define COL 3 // 3是棋盘的列数,可以随意改变数字
#include
#include
#include
//初始化棋盘
void initqp(char qp[ROW][COL],int row,int col);//形参要小写
//打印棋盘
void displayqp(char qp[ROW][COL], int row, int col);
//玩家走
void player(char qp[ROW][COL], int row, int col);
//电脑走
void computer(char qp[ROW][COL], int row, int col);
//可以告诉我们4种状态:
//1.玩家赢 -->'*'
//2.电脑赢 -->'#'
//3.平局 -->'P'
//4.游戏继续 -->'C'
char win(char qp[ROW][COL], int row, int col);//要返回字符,所以说要用char类型返回
test.c:
#include"game.h"//引用头文件
void menu()
{
printf("*********************\n");
printf("********1.play*******\n");
printf("********0.exit*******\n");
printf("*********************\n");
}
void game()
{
char ret = 0;//接受返回字符,判断输赢
char qp[ROW][COL] = { 0 };//定义棋盘时,ROW也就是行可以省,但是COL也就是列不能省,推荐大家都带上
initqp(qp, ROW, COL);//初始化棋盘,不管之前棋盘里放了什么,全部都初始化为空格
displayqp(qp,ROW,COL);//打印棋盘
while (1)//无限循环下棋,直到出现下面的情况就跳出
{
player(qp,ROW,COL);//玩家下棋
displayqp(qp, ROW, COL);//打印棋盘
ret = win(qp, ROW, COL);//判断玩家是否赢了
if (ret != 'C')//如果返回的ret不是字符c
{
break;//跳出循环
}
computer(qp, ROW, COL);//电脑下棋
displayqp(qp, ROW, COL);//打印棋盘
ret = win(qp, ROW, COL);//判断电脑是否赢了
if (ret != 'C')//如果返回的ret不是字符c
{
break;//跳出循环
}
}
if (ret == '*')//ret返回字符*
{
printf("玩家赢\n");
}
else if (ret == '#')//ret返回字符#
{
printf("电脑赢\n");
}
else
{
printf("平局\n");//ret返回字符p
}
}
int main()
{
int n = 0;
srand((unsigned int)time(NULL));//时间戳,用来生成随机,要引用time函数,该语句整局只用一次,所以可以放在开头处
//unsigned int 将time返回的值强制转化成无符号整形类型,用来作为srand随机数生成器
do//采用do-while循环,因为玩家最少进行一次游戏
{
menu();//菜单函数
scanf_s("%d", &n);//让玩家输入数字,进行选择
switch (n)//判断玩家输入满足下面哪一个条件
{
case 1:
printf("三子棋游戏:\n");
game();
break;//玩家输入1就打印三子棋游戏字样,并且竟然game函数进行三子棋游戏。游戏结束后自动跳出,玩家重新选择是否继续游戏
case 0:
printf("退出游戏");
break;//玩家输入0,则退出游戏
default:
printf("输入错误,请重新输入:");//玩家如果输入1和0之外的元素,则告诉玩家输入错误,请重新输入元素
break;
}
} while (n);//;不能掉
return 0;
}