文章目录
-
- 游戏介绍
- 游戏设计思路及涉及知识点
- 代码思路
- 具体代码实现
- 总结
游戏介绍
相信大家都玩过三子棋游戏。三子棋,顾名思义,就是玩家通过在“井”字格中摆上自己的棋子,当有三颗相同的棋子连成一条线时即为获胜。多子棋亦是如此。
游戏设计思路及涉及知识点
>>涉及的知识点:数组的遍历,循环,条件判断语句,分支控制语句,函数。
>>设计思路:
一、建立“菜单”,为用户(进入 / 退出)游戏提供选择。
二、创建空白棋盘即初始化棋盘,将棋盘打印到屏幕上,供玩家下棋。
三、玩家输入棋盘坐标进行下棋,同时将新棋盘打印至屏幕上。
四、判断玩家是否获胜、失败还是平局,如都不是则棋局继续进行。
五、电脑下棋,同时将新棋盘打印至屏幕上。
六、判断玩家是否获胜、失败还是平局,如都不是则棋局继续进行。
七、如若本局棋结束,返回步骤“一”,玩家选择 进入/退出 游戏。
菜单及棋盘展示
代码思路
- 建立一个头文件“game.h”用来封装所需要使用的头文件以及函数的声明。
- 建立一个源文件“game.c”用来对头文件中需要使用的函数进行定义。
- 建立另一个源文件“PlayGame.c”实现三子棋游戏。
- 玩家与电脑下棋确保坐标在棋盘范围内,且电脑下棋确保其随机性。
如何确保电脑下棋的随机性呢?
思路:使用srand()、rand()函数为电脑提供随机值。
函数介绍:
srand()
和 rand()
是C语言中用于生成随机数的标准库函数,它们声明在 stdlib.h
头文件中。
1、srand()
srand()
函数用于设置随机数生成器的种子。使用 srand()
函数可以改变随机数生成器的起始点,从而影响后续调用 rand()
生成的随机数序列。
函数原型如下:
void srand(unsigned int seed);
参数 seed
是一个无符号整数值,用作随机数生成器的种子。常用的种子值有 time(NULL)
,它使用当前时间作为种子,因此每次程序运行都会得到不同的随机数序列。
2、time()
time()
是C语言中的一个标准库函数,声明在 time.h
头文件中。它用于获取当前的系统时间并返回一个 time_t
类型的值。
函数原型如下:
time_t time(time_t* timer);
参数 timer
是一个可选的指向 time_t
对象的指针,用于接收时间值。如果传入 NULL
,则 time()
函数会仅返回时间值,而不会将其存储到指定的位置。
返回值是一个表示当前时间的 time_t
类型的值,通常是一个整数,表示自某个特定时间(通常是系统特定的起始时间点)到调用 time()
时经过的秒数。
使用 time()
函数可以实现获取当前时间的功能。
3、rand()
rand()
函数用于生成一个随机数。
函数原型如下:
int rand(void);
rand()
函数返回一个在范围 [0, RAND_MAX]
内的伪随机整数。RAND_MAX
是一个常量,表示随机数的最大可能值,通常是一个较大的整数。
若要生成一个指定范围内的随机数,可以使用取余运算符 %
对 rand()
的返回值进行处理,例如:rand() % n
表示生成一个范围在 [0, n-1]
的随机整数。
由于rand()函数生成的随机值具有局限性,且只能生成一次随机数,所以我们在主函数中调用srand()函数,以及使用time(NULL)时刻改变其参数,使其程序调用rand()函数都可以生成不同的伪随机数,极大的确保了电脑下棋的随机性。
我们列举一个简单的生成随机数的例子:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int i;
srand((unsighed int)time(NULL)); // 设置种子为当前时间
for (i = 0; i < 5; i++) {
printf("%d\n", rand()); // 生成随机数并打印
}
return 0;
}
**** 由于time(NULL)的返回值为time_t类型,通常是一个整数。由于游戏中所需的随机数类型为正整数,所以我们将time(NULL)的返回值用(unsigned int)强制转换为“无符号整型”,以确保电脑下棋的可行性。
具体代码实现
根据上面的代码思路我们先实现头文件“game.h"。
#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS 1
#define row 3//改变数据则可进行多子棋玩法
#define col 3//同上
void meau();//游戏菜单界面
void PlayerPlay(char board[row][col]);//玩家下棋
char WinOrLose(char board[row][col]);//判断输赢
void ComputerPlay(char board[row][col]);//电脑下棋
void DisplayBoard(char board[row][col]);//打印棋盘
int Is_Full(char board[row][col]);//判断是否平局
由于我们将需要使用的头文件及函数都包含在了自己建立的头文件game.h中,所以在后续写源文件代码时,只需引用game.h这个头文件即可。创立的头文件的引用方法为:#include"game.h”。
接下来我们在源文件game.c中实现对函数的定义
#include"game.h"
void meau()//打印菜单
{
printf("************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("************************\n");
}
//打印棋盘。
void DisplayBoard(char board[row][col])
{
int i, j, k;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (k = 0; k < col; k++)
{
printf("---");
if (k < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
printf("\n");
}
void PlayerPlay(char board[row][col])
{
int a, b,num1,num2;
printf("玩家下棋\n请输入下棋坐标,eg: num1 num2 >: ");
while (1)
{
scanf("%d %d", &a, &b);
num1 = a - 1;
num2 = b - 1;
if (num1 >= 0 && num2 >= 0 && num1 < row && num2 < col)
{
if (board[num1][num2] == ' ')
{
board[num1][num2] = 'O';
break;
}
else
{
printf("坐标已被占用,请输入其他坐标>:");
continue;
}
}
else
{
printf("输入坐标错误,请重新输入>:");
continue;
}
}
}
void ComputerPlay(char board[row][col])
{
printf("电脑下棋\n");
while (1)
{
int c = rand() % row;//经对row取模后,c的范围在0~row-1之间
int d = rand() % col;//同理,d的范围在0~col-1之间
if (board[c][d] == ' ')
{
board[c][d] = 'X';//如果此元素为' ',将其赋值为X,打印至屏幕上
break;
}
else
{
continue;//如果不为' ',进行下次循环。
}
}
}
//判断棋盘是否被填满且未产生赢家
int Is_Full(char board[row][col])
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')//如果数组元素中无' ',则说明棋盘已被填满。
{
return 0;
}
}
}
return 1;
}
//判断玩家输或赢或平局
{
char WinOrLose(char board[row][col])
{
int i=0, j=0, k, flag = 1;
char t;
for (i = 0; i < row; i++)//判断一行是否为连续相同的棋子
{
j = 1;
t = board[i][0];//将每行第一个棋子与后面的棋子比较
while (j < col)
{
if (t != board[i][j] || t == ' ')
break;
else
j++;
}
if (j == col)
return t;
}
//判断每一列是否为连续相同的棋子
for (j = 0; j < col; j++)
{
i = 1;
t = board[0][j];
while (i < row)
{
if (t != board[i][j] || t == ' ')
break;
else
i++;
}
if (i == row)
return t;
}
//判断对角线是否为连续相同的棋子
for (i = 1; i < row; i++)
{
t = board[0][0];
if (t != board[i][i] || t == ' ')
{
flag = 0;
break;
}
}
if (flag)
return t;
//判断另一条对角线是否为连续相同的棋子
int num3 = 0, num4 = col - 1;
t = board[num3][num4];
while (num3 < row)
{
if (t != board[num3][num4]||t==' ')
break;
num3++;
num4--;
}
if (num3 == row)
return t;
//判断是否平局,如否则继续下棋
if (Is_Full(board))
return 'P';//返回P则为平局
else
return 'C';//返回C。则为继续下棋
}
源文件PlayGame.c中实现三子棋游戏。
#include"game.h"
void game()
{
char board[row][col] ;
int i, j;
char k;
//初始化元素为空
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
DisplayBoard(board);
while (1)
{
PlayerPlay(board);
DisplayBoard(board);
k = WinOrLose(board);
if (k != 'C')
break;
ComputerPlay(board);
DisplayBoard(board);
k = WinOrLose(board);
if (k != 'C')
break;
}
if (k == 'O')
{
printf("玩家获胜!!!\n");
}
else if (k == 'X')
{
printf("电脑获胜!!!\n");
}
else
{
printf("平局。。。\n");
}
}
int main()
{
int input;
srand((unsigned int)time(NULL));
do
{
meau();
printf("请输入>(1/0):");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏。\n");
break;
default :
printf("输入错误,请重新输入!!!>:\n");
break;
}
} while (input);
return 0;
}
运行结果
由于篇幅有限,同学们也可以自行测试。代码肯定还有可以优化的地方,但由于博主水平有限,暂时只能为大家呈现以上内容。如果同学们有其他想法,望不吝赐教哈哈。