0
点赞
收藏
分享

微信扫一扫

Redis入门到实战(实战篇)缓存更新、穿透、雪崩、击穿!

small_Sun 2023-05-11 阅读 141

代码思路:

1.多文件的使用(test.c  game.c  game.h)

2.宏定义的使用

3.打印菜单

4.创建二维数组

5.初始化数组

6.打印棋盘

7.玩家下棋

8.电脑下棋

9.判断输赢

10.代码全析总结

(1)多文件的使用:

 在路径下面创建一个头文件和两个源文件

test.c        里面是 主函数 调用的函数 菜单的打印

game.c        这里面是 游戏主体 的实现

game.h        除了 主函数 之外的 所有函数 以及 宏 所存放的地方

(2)宏定义的使用:

 在我的头文件里面使用宏定义:将每一行,每一列都定义为3

        如果想要修改棋盘的行和列,只需要在头文件的ROW COL后面修改数字即可,这样很方便,提高了效率。

(3)打印菜单:

        为了保证游戏能够多次进行,或者说我们玩玩一把不过瘾,需要再玩一把。我们可以直接把菜单的打印和游戏函数的实现放到一个循环里面。

        因为上来直接可以让你选择是否玩游戏,所以说不管三七二十一直接用do while循环,代码的实现如下:

	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋游戏开始\n");
			game();//整个游戏的实现主体在这个game函数里面。
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}
	} while (input);

        

void menu()
{
	printf("*********************************\n");
	printf("********	1.play	 *********\n");
	printf("********	0.exit	 *********\n");
	printf("*********************************\n");
}

        这个循环的控制条件放的是input,为什么要放input呢?初始化input为0,当你选择非零的时候,就会进入case1或者default,循环的结果为真,所以进入循环让你继续游戏或者重新选择。input是零的话就为假,直接跳出循环。

(4)创建二维数组:

char board[ROW][COL] = { 0 };//咱们暂且将二维数组初始化为0。

(5)初始化数组:

        我们现在要充分利用函数的思想,所以要创建一个初始化数组的函数

函数的调用:

InitBoard(board, ROW, COL);//初始化数组

函数的声明:

//初始化数组
void InitBoard(char board[ROW][COL],int row,int col);

函数的实现:

初始化二维数组为空格的话,需要用两个for循环来遍历

//初始化棋盘为空格
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

(6)打印棋盘:(重难点!)

函数的调用:

PrintBoard(board, ROW, COL);//打印数组

函数的声明:

//打印数组
void PrintBoard(char board[ROW][COL], int row, int col);

函数的实现:

        棋盘的打印需要用分割线来分隔开 

1.打印数据(包括:“空格+%c+空格” +“|”)

2.打印分割线(包括 :“---”+“|”)

见下图:

        红 蓝总共为一组,每一行需要打印这么多,只不过在最后那一列不用打印,到时候加一个限制条件即可。 

//版本2---打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{
	//1.打印数据
	int i = 0;//这个i相当于作用域内的全局变量
	//所以下面的第2个条件照样使用。
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)//限制最后一个,不用打印。
				printf("|");
		}
		printf("\n");//打印完一行后要换行

		//2.打印分割线
		if (i < row - 1)//如果是三子棋的话,只需要打印两行分割线即可,这里的row是3,所以说这需要i=0,1
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//限制最后一个不用打印。
					printf("|");
			}
			printf("\n");
		}
	}
}

值得注意的是:这个 打印棋盘 是重难点,需要多次反复思考

(7)玩家下棋:(重难点!)

函数的调用:

PlayerMove(board, ROW, COL);//玩家下棋

函数的声明:

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

函数的实现:

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)//这一步仔细想想!!!!
{
	int x = 0;
	int y = 0;
	printf("玩家下棋:>");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')//因为数组的下边从0开始,所以输的数要-1
			{
				board[x-1][y-1] = '*';//符合坐标范围而且是空,才能落子
				break;//当你成功落完子之后,需要赶紧跳出循环,等待电脑下棋。
			}
			else//这个else的对立面,就是空格处有*或#,不能再落子了
				printf("坐标被占用,请重新输入:");
		}
		else//超出范围无法落子
		{
			printf("坐标非法,请重新输入:");
		}
	}
}

代码的每一步解析,在注释中需要读者仔细阅读反复理解

(8)电脑下棋:(重难点!)

函数的调用:

ComputerMove(board, ROW, COL);//电脑下棋

函数的声明:

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

函数的实现:

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	
	printf("电脑下棋\n");
	while (1)//这里我们为什么要用一个死循环?如果电脑所下的地方被占用,那么就让它一直循环产生一个随机数,直到产生一个没有被占用的地方。
	{
		// X和Y要放循环内部,让他每一次循环都会产生随机数,不然就会电脑不下棋,形成死循环。
		x = rand() % row;//产生0~row-1的数字
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;//这里的break意思是指电脑下棋成功后直接跳出循环。
		}
	}
}

这里电脑下棋需要运用,我们之前在猜数字游戏学过的随机数的产生。

rand---srand---time函数

同样,每一步的解析和疑问都在代码的注释中,需要读者反复阅读理解。

(9)判断输赢:(重难点!)

游戏所进行的状态无非就这几种:

玩家赢---'*'
电脑赢---'#'
平局---'Q'

继续游戏---'C'

后面的字母代表,如果某种情况成立,那么就返回后面所对应的字符:

那么我们就需要创建一个判断输赢的函数(另外在判断平局的时候比较特殊,需要创建一个判断平局的函数:IsFull):

函数的调用:

ret = IsWin(board, ROW, COL);//ret是创建的变量用来接收它的返回值,数据类型:char
IsFull(board, ROW, COL);

函数的声明:

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//判断平局
int IsFull(char board[ROW][COL], int row, int col);

函数的实现:

char IsWin(char board[ROW][COL], int row, int col)//因为返回的是字符,所以要用char
{
	//赢
	//行
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//这种判断方法也是很有局限的,也是确定了只能用三子棋,不能用5×5 6×6 10×10的棋盘。
		if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][0] != ' ')//记得这里两个条件判断的时候一定要两两分开!!!
			return board[i][0];
	}
	//列
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&&board[1][i] != ' ')
			return board[0][i];
	}
	//对角线
	if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&& board[1][1] != ' ')
		return board[0][0];
	if (board[2][0] == board[1][1]&& board[1][1] == board[0][2]&& board[1][1] != ' ')
		return board[0][2];
	//判断平局
	if (IsFull(board, ROW, COL) == 1)
		return 'Q';
	else
		return 'C';
}

int IsFull(char board[ROW][COL], int row, int col)//判断是否平局的函数。
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;//如果存在空格,游戏继续。
		}
	}
	return 1;//如果返回1那么是平局,平局对应上方的第130行,正好返回Q
}

以上内容是所有三子棋的一步一步的分析,不理解的地方,需要反复阅读认真理解

(10)代码全析总结:

1.test.c:

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include "game.h"
void menu()
{
	printf("*********************************\n");
	printf("********	1.play	 *********\n");
	printf("********	0.exit	 *********\n");
	printf("*********************************\n");
}
void game()
{
	//设置一个变量来接收是否平局
	char ret = 0;//这里因为返回一个字符,所以要用char类型
	char board[ROW][COL] = { 0 };
	InitBoard(board, ROW, COL);//初始化数组
	PrintBoard(board, ROW, COL);//打印数组
	while (1)
	{
		PlayerMove(board, ROW, COL);//玩家下棋
		PrintBoard(board, ROW, COL);//打印数组

		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;

		ComputerMove(board, ROW, COL);//电脑下棋
		PrintBoard(board, ROW, COL);//打印数组

		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("玩家赢\n");
	if (ret == '#')
		printf("电脑赢\n");
	if (ret == 'Q')
		printf("平局\n");
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋游戏开始\n");
			game();//整个游戏的实现主体在这个game函数里面。
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

2.game.c :

#define _CRT_SECURE_NO_WARNINGS 1 
#include "game.h"
//初始化棋盘为空格
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}
//版本1
//void PrintBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		int j = 0;
//		for (j = 0; j < col; j++)
//		{
//			printf("%c", board[i][j]);
//		}
//		printf("\n");
//	}
//}


//版本2---打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{
	//1.打印数据
	int i = 0;//这个i相当于作用域内的全局变量
	//所以下面的第2个条件照样使用。
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)//限制最后一个,不用打印。
				printf("|");
		}
		printf("\n");//打印完一行后要换行

		//2.打印分割线
		if (i < row - 1)//如果是三子棋的话,只需要打印两行分割线即可,这里的row是3,所以说这需要i=0,1
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//限制最后一个不用打印。
					printf("|");
			}
			printf("\n");
		}
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)//这一步仔细想想!!!!
{
	int x = 0;
	int y = 0;
	printf("玩家下棋:>");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')//因为数组的下边从0开始,所以输的数要-1
			{
				board[x-1][y-1] = '*';//符合坐标范围而且是空,才能落子
				break;//当你成功落完子之后,需要赶紧跳出循环,等待电脑下棋。
			}
			else//这个else的对立面,就是空格处有*或#,不能再落子了
				printf("坐标被占用,请重新输入:");
		}
		else//超出范围无法落子
		{
			printf("坐标非法,请重新输入:");
		}
	}
}
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	
	printf("电脑下棋\n");
	while (1)//这里我们为什么要用一个死循环?如果电脑所下的地方被占用,那么就让它一直循环产生一个随机数,直到产生一个没有被占用的地方。
	{
		// X和Y要放循环内部,让他每一次循环都会产生随机数,不然就会电脑不下棋,形成死循环。
		x = rand() % row;//产生0~row-1的数字
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;//这里的break意思是指电脑下棋成功后直接跳出循环。
		}
	}
}

char IsWin(char board[ROW][COL], int row, int col)//因为返回的是字符,所以要用char
{
	//赢
	//行
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//这种判断方法也是很有局限的,也是确定了只能用三子棋,不能用5×5 6×6 10×10的棋盘。
		if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][0] != ' ')//记得这里两个条件判断的时候一定要两两分开!!!
			return board[i][0];
	}
	//列
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&&board[1][i] != ' ')
			return board[0][i];
	}
	//对角线
	if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&& board[1][1] != ' ')
		return board[0][0];
	if (board[2][0] == board[1][1]&& board[1][1] == board[0][2]&& board[1][1] != ' ')
		return board[0][2];
	//判断平局
	if (IsFull(board, ROW, COL) == 1)
		return 'Q';
	else
		return 'C';
}

int IsFull(char board[ROW][COL], int row, int col)//判断是否平局的函数。
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;//如果存在空格,游戏继续。
		}
	}
	return 1;//如果返回1那么是平局,平局对应上方的第130行,正好返回Q
}

3.game.h :

#pragma once

#define ROW 3
#define COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//初始化数组
void InitBoard(char board[ROW][COL],int row,int col);
//打印数组
void PrintBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//玩家赢--'*'
//电脑赢--'#'
//平局---'Q'
//int IsFull(char board[ROW][COL], int row, int col);
//继续游戏---'C'

以上就是三子棋的全分析

如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!

请添加图片描述

举报

相关推荐

0 条评论