c语言实现三(多)子棋游戏

文章详细介绍了如何使用C语言设计和实现一个三子棋游戏,包括游戏逻辑、菜单设计、玩家与电脑下棋的策略,特别是通过srand()和rand()函数确保电脑下棋的随机性。此外,还提供了具体的代码实现和游戏流程控制,以及判断胜负和平局的函数实现。
摘要由CSDN通过智能技术生成

文章目录

    • 游戏介绍
    • 游戏设计思路及涉及知识点
    • 代码思路
    • 具体代码实现
    • 总结

游戏介绍

相信大家都玩过三子棋游戏。三子棋,顾名思义,就是玩家通过在“井”字格中摆上自己的棋子,当有三颗相同的棋子连成一条线时即为获胜。多子棋亦是如此。

游戏设计思路及涉及知识点

>>涉及的知识点:数组的遍历,循环,条件判断语句,分支控制语句,函数。

>>设计思路:

一、建立“菜单”,为用户(进入 / 退出)游戏提供选择。

二、创建空白棋盘即初始化棋盘,将棋盘打印到屏幕上,供玩家下棋。

三、玩家输入棋盘坐标进行下棋,同时将新棋盘打印至屏幕上。

四、判断玩家是否获胜、失败还是平局,如都不是则棋局继续进行。

五、电脑下棋,同时将新棋盘打印至屏幕上。

六、判断玩家是否获胜、失败还是平局,如都不是则棋局继续进行。

七、如若本局棋结束,返回步骤“一”,玩家选择 进入/退出 游戏。

菜单及棋盘展示

 

代码思路

  • 建立一个头文件“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;
}

运行结果

 由于篇幅有限,同学们也可以自行测试。代码肯定还有可以优化的地方,但由于博主水平有限,暂时只能为大家呈现以上内容。如果同学们有其他想法,望不吝赐教哈哈。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这题怎么做?!?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值