• 趣味益智小游戏 三子棋+五子棋 优化版(可任意选择棋盘大小)


    前言

    今天牛牛给大家分享的是c语言实现三子棋和五子棋游戏,初学者可能有些不理解的地方,记得私信提问哦,牛牛会一 一回答的。

    一、游戏介绍

    三子棋》是一款益智小游戏,通常是在九宫格里面玩,所以也被称为”九宫棋“或”井字棋“。
    游戏规则也极其简单,只要三子相连即可获胜。
    例如:

    c语言实现效果图:

    三子棋:


    五子棋

    二、游戏设计思路

    分为三个模块化实现:

    1.主函数测试区(test.c):用于打印菜单、实现调用游戏要使用的各种函数、退出游戏等功能。
    重点在于其中的game函数()。

    2.函数声明区(game.h):用于各种库函数、自定义函数的声明。

    3.函数实现区(game.c):用于各种函数功能的具体的实现。

    
     1. 菜单界面选择开始或者退出游戏。
     2. 玩家选择游戏类型:1.三子棋 2.五子棋  
     3. 玩家选择棋盘大小。
     4. 创建棋盘并初始化.打印棋盘。(打印初始化后的棋盘)。
     5. 玩家落子(玩家输入行列坐标的方式来落子),'*’表示玩家落子。(注意坐标合法性)
     6. 打印棋盘(玩家落子后的棋盘)。
     7. 判定胜负关系(输,赢,和棋),'p’表示平局。.
     8.电脑落子(随机位置落子) ,'#’表示电脑落子。
     9. 打印棋盘(电脑落子后的棋盘)
     10.判定输赢情况。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.1 主函数测试区(test.c)基本构成

    2.11 创建游戏菜单

    可用printf打印一个简易菜单,让玩家选择。

    //在主函数测试区(test.c)
    void menu()
    {
    	printf("*******************************************************************\n");
    	printf("************                     *                    *************\n");
    	printf("******************               *                *****************\n");
    	printf("************************         *          ***********************\n");
    	printf("*******************************  *   ******************************\n");
    	printf("********    1.玩游戏         *        2.退出游戏          *********\n");
    	printf("*******************************  *   ******************************\n");
    	printf("************************         *          ***********************\n");
    	printf("******************               *                *****************\n");
    	printf("************                     *                     ************\n");
    	printf("*******************************************************************\n");
    	printf("请选择:\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.12 主测试区基本框架

    通过switch语句来实现根据玩家选择结果来调用game函数

    int main()
    {
    	int n = 0;//记录玩家在菜单中的选择
    	srand((unsigned int)time(NULL));//与前面介绍的猜数字游戏一样,改变种子值来使得rand函数每次生成不同的随机数列。用于后面的电脑下棋
    	do
    	{
    		menu();
    		scanf("%d", &n);//让玩家在菜单中选择
    		switch (n)
    		{
    		case 1://代表玩游戏
    			game();//这个是重点函数
    			printf("再来一局吗?\n");//游戏结束后
    			printf("1.再来一局   2. 没意思不玩了\n");
    			int again = 0;//存放玩家是否再玩的结果。
    			scanf("%d", &again);
    			if (again == 1)
    			{
    				break;
    			}
    			else
    				n = 2;//令n=2循环结束
    			break;
    		case 2:
    			printf("退出游戏");
    			break;
    		default:
    			printf("没有这个选项哦。\n");//玩家不小心输错了
    			break;
    		}
    	} while (n - 2);//当玩家选择2时,代表不玩了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2.2 game函数的实现(在主函数测试区(test.c))

     1. 玩家选择游戏类型:1.三子棋 2.五子棋  
     2. 玩家选择棋盘大小。
     3. 创建棋盘并初始化.打印棋盘。(打印初始化后的棋盘)。
     4. 玩家落子(玩家输入行列坐标的方式来落子),'*’表示玩家落子。(注意坐标合法性)
     5. 打印棋盘(玩家落子后的棋盘)。
     6. 判定胜负关系(输,赢,和棋),'p’表示平局。.
     7.电脑落子(随机位置落子) ,'#’表示电脑落子。
     8. 打印棋盘(电脑落子后的棋盘)
     9.判定输赢情况。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.21 棋盘的创建:

    创建一个大小为15行15列的二维数组(可修改,不建议太大)用于存放棋子。
    这里使用宏定义是为了方便改变棋盘的最大大小,下次需要修改的时候只需要修改这里就行,不需要每个函数都一 一去改。

    //函数声明区(game.h)
    #define ROW 15//为了方便改变棋盘大小
    #define COL 15
    
    • 1
    • 2
    • 3
    //game函数的实现(在主函数测试区(test.c))
    void game()
    {
    	printf("欢迎玩家进入游戏:\n");
    	
    	int gametype = 0;//游戏类型
    	int boardtype = 0;//棋盘大小的确定
        again://玩家选择错误后返回到此处
    	printf("请选择游戏类型: 1.三子棋游戏(建议3*3的棋盘)  2.五子棋游戏\n");
    	scanf("%d", &gametype);//让玩家选择游戏类型
    	if (gametype != 1 && gametype != 2)//玩家选择错误给出提示,并重新选择
    	{
    		printf("选择错误,牛牛还未开发此类型游戏。\n");
    		printf("请重新选择:\n");
    		goto again;//跳转到again语句处
    	}
    	printf("请选择棋盘类型:n*n,你希望n的值为多少?(1);
    	scanf("%d", &boardtype);//得到玩家想要的棋盘大小
    	if (gametype == 2 && boardtype < 5 || gametype == 1 && boardtype < 3)//避免选五子棋的棋盘小于5*5,和三子棋小于3*3的棋盘
    	{
    		printf("棋盘不符合要求:请重新选择:\n");
    		goto again;//跳转到again语句处
    	}
    	else if (boardtype > ROW)//选择的棋盘最大不得超过15*15
    	{
    		printf("超出棋盘最大设置范围(15*15):\n请重新选择:\n");
    		goto again;//跳转到again语句处
    	}
    	char board[ROW][COL] = { 0 };//定义一个2维数组,最大为15*15,用于存放棋子
    	char ret = 0;//设置判断输赢的返回值。
    	//打印数组的元素
    	init_board(board, ROW, COL);//初始化棋盘,使其值全为空格
    	print_board(board, boardtype, boardtype);//打印棋盘的外观和内容
    	
    	while (1)//游戏开始
    	{
    		palyer(board, boardtype, boardtype);//玩家下棋
    		print_board(board, boardtype, boardtype);//打印棋盘
    		if (gametype == 1)//根据类型现在判断输赢的类型
    		{
    			ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    		}
    		else
    		ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    		if (ret != 'c')
    		{
    			break;
    		}
    		computer(board, boardtype, boardtype);//电脑下棋
    		print_board(board, boardtype, boardtype);//打印棋盘
    		if (gametype == 1)//根据类型现在判断输赢的类型
    		{
    			ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    		}
    		else
    			ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    		if (ret != 'c')
    		{
    			break;
    		}
    	}
    	if (ret == '*')
    	{
    		printf("玩家胜利\n");
    	}
    	else if (ret == '#')
    	{
    		printf("电脑胜利\n");
    	}
    	else
    	{
    		printf("平局\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    补充知识:goto语句:用于跳转到自己设定的语句处。

    提示:虽然棋盘大小是用户选择,但其实并不是用户选择多大的棋盘就创建多大的棋盘,棋盘最大值已经限定,只是在打印棋盘的时候,根据传递过去的参数要求打印棋盘的部分内容。
    例如:
    玩家输入:5,那么程序就只打印5×5的棋盘,但是棋盘的真实大小还是15×15,程序只是打印了其中的5行5列罢了(部分内容)。

    2.3函数实现区(game.c)

    2.31 棋盘的初始化函数(init_board)

    void init_board(char board[ROW][COL], int row, int col)//初始化棋盘
    {
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)
    	{
    		for (j = 0; j < col; j++)
    		{
    			board[i][j] = ' ';//初始化棋盘的内容为全空格
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.32 棋盘的打印函数(print_board)

    牛牛为了美观,这里设计起来显得有些繁琐,但是牛牛会尽量解释清楚的。
    先看效果图:

    棋盘打印实现的分步讲解:
    分割行打印讲解:(由于空格不能显示,这里用口表示,棋子未输入前用%c表示)

    特殊:由于分割行总共有row+1行,所以我们可以先打印第一行,再循环打印后面的row行。

    数据行打印讲解:

    行号和列标的打印讲解:
    为了让玩家更好的找到棋盘的对应位置,我们可以打印行号和列标来辅助。
    只是苦了我们程序猿了,要加代码来实现。
    行号:可以在打印棋盘之前用for循环打印得到1到col之间的数字。
    列标:则是每打印一行数据行,在前面加上行号。

    打印棋盘函数代码实现:

    //函数代码实现区(game.c)
    void print_board(char board[ROW][COL], int row, int col)//打印棋盘//建议参照棋盘的外观查看代码
    {
    	int i = 0, j = 0;
    	printf(" ");//打印空格是为了对齐(因为下面的行号占用位置)
    	for (i = 1; i <= row; i++)//打印显示在第一行的列标
    	{
    		printf("%3d ",i);//因为一个数据行的格子占3个位置,所以我们这里用%3d占用三个位置的空间
    	}
    	printf("\n");//打印列标后换行。
    	printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格,因为分割行前面没有行号占用位置,只能补空格。
    	for (i = 0; i < row; i++)//打印第一行的分割线
    	{
    		printf("---+");//上图讲解了拆分过程。
    	}
    	printf("\n");//每次打印一行就要换行
    	for (i = 0; i < row; i++)
    	{
    		printf("%2d", i+1);//打印数据行前面的行号,%2d是因为当行数>9的时候,两位数会占用两个位置,影响对齐。(细节)
    		printf("|");//和上面一样,先打印一个 | ,可以观察棋盘外观,将数据行拆分打印。
    		for (j = 0; j < col; j++)//打印一行中间的棋子和其它分割线
    		{
    			printf(" %c |", board[i][j]);//这里打印的是“空格”“棋子”“空格”“|”
    		}
    		printf("\n");//每次打印一行就要换行
    		//打印剩余的分割行
    		printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
    		for (j = 0; j < col; j++)//打印一行外观的分割线
    		{
    			printf("---+");//每次打印一行就要换行
    		}
    		printf("\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2.33 玩家下棋函数(palyer)

    注意:此处的ROW(大写)与row(小写)大小不一定相同,ROW(大写)是宏定义的15,而row(小写)是由玩家选择的。

    void palyer(char board[ROW][COL], int row, int col)
    {
    	int x = 0, y = 0;//定义x 和 y变量存储棋子的坐标
    	printf("请玩家下棋:\n");
    	while (1)
    	{
    		printf("请输入行号和列标:(用空格隔开)\n");
    		scanf("%d%d", &x, &y);
    		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法,由于玩家并不是程序员,所以坐标要正常从1开始
    		{
    			if (board[x - 1][y - 1] == ' ')//落子处为空格,表示此处还未被占用。x-1,y-1是因为2维数组的坐标是从0开始的。
    			{
    				board[x - 1][y - 1] = '*';//玩家下棋为‘*’,将输入的坐标位置占据。
    				break;//表示落子成功,结束循环,判断输赢后,轮到电脑下了
    			}
    			else//如果此处不是空格,则表示此处已经有棋子了。
    			{
    				printf("该处已经被占用了,请重新选择\n");
    			}
    		}
    		else//如果坐标不在1到row之间,则棋子超出合法范围,
    		{
    			printf("该坐标非法,已经超过棋盘,无法识别\n");
    			printf("请重新选择:\n");
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.33 电脑下棋函数(computer)

    电脑下棋是随机下棋,我们需要得到两个随机数作为电脑棋子的下标。

    void computer(char board[ROW][COL], int row, int col)//电脑下棋中
    {
    	printf("电脑下棋中:\n");
    	while (1)
    	{
    		int x = rand() % row;//生成0到2的随机数作为棋子下标
    		int y = rand() % col;
    		if (board[x][y] == ' ')//找到棋盘中的空余位置进行下棋
    		{
    			board[x][y] = '#';
    			break;
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.34 判断是否平局函数(draw)

    平局的判断很简单,当棋盘上没有空余棋子的时候,表示棋盘已经满了,并且没有一方获胜,则显示平局。

    int draw(char board[ROW][COL], int row, int col)//判断平局
    {
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)
    	{
    		for (j = 0; j < col; j++)
    		{
    			if (board[i][j] == ' ')
    			{
    				return 0;//如果还要一个空格,即表示棋盘还没有满
    			}
    		}
    	}
    	return 1;//棋盘满了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.35 三子棋的判断输赢函数(who_win3)

    char who_win3(char board[ROW][COL], int row, int col)//三子棋判断输赢
    {
    
    
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)//判断每行,所以i要取0到row(不包含row)
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
    				//判断每行是否有相连的3个元素,并且不是空格
    			{
    				return board[i][j];
    			}
    		}
    	}
    	for (j = 0; j < col; j++)//判断每列
    	{
    		for (i = 0; i + 2 < row; i++)
    		{
    			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
    				//判断每列是否有相连的3个元素,并且不是空格
    			{
    				return board[i][j];
    			}
    		}
    	}
    	for (i = 0; i + 2 < row; i++)//判断主对角线和主对角线平行的线
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i][j] != ' ')//判断主对角线和主对角线平行的线是否有三个相连,且不是空格
    				return board[i][j];
    		}
    	}
    	for (i = 2; i < row; i++)//判断反对角线和与反对角线平行的线
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2]  && board[i][j] != ' ')//判断反对角线和反对角线平行的线是否有三个相连,且不是空格
    				return board[i][j];
    		}
    	}
    	if (1 == draw(board, ROW, COL))
    	{
    		return 'p';
    	}
    	else
    		return 'c';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    2.36 五子棋的判断输赢函数(who_win5)

    char who_win5(char board[ROW][COL], int row, int col)//五子棋判断输赢
    {
    	int i = 0;
    	int j = 0;
    	for (i = 0; i < row; i++)//判断每行
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j + 2] == board[i][j + 3] && board[i][j + 3] == board[i][j + 4] && board[i][j] != ' ')/判断每一行的是否有五个相连的元素,并且不是空格
    				return board[i][j];
    		}
    	}
    	for (j = 0; j < row; j++)//判断每列
    	{
    		for (i = 0; i + 4 < row; i++)
    		{
    			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')//判断每一列的是否有五个相连的元素,并且不是空格
    				return board[i][j];
    		}
    	}
    	for (i = 0; i + 4 < row; i++)//判断主对角线和主对角线平行的线
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4] && board[i][j] != ' ')//判断主对角线和反对角线平行的线是否有五个相连,且不是空格
    				return board[i][j];
    		}
    	}
    	for (i = 4; i < row; i++)//判断反对角线和与反对角线平行的线
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4] && board[i][j] != ' ')//判断反对角线和反对角线平行的线是否有五个相连,且不是空格
    				return board[i][j];
    		}
    	}
    	if (1 == draw(board, ROW, COL))
    	{
    		return 'p';
    	}
    	else
    		return 'c';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    三、游戏总代码

    3.1.主函数测试区(test.c):

    
    #define _CRT_SECURE_NO_WARNINGS 1
    #include "game.h"
    void menu()
    {
    	printf("*******************************************************************\n");
    	printf("************                     *                    *************\n");
    	printf("******************               *                *****************\n");
    	printf("************************         *          ***********************\n");
    	printf("*******************************  *   ******************************\n");
    	printf("********    1.玩游戏         *        2.退出游戏          *********\n");
    	printf("*******************************  *   ******************************\n");
    	printf("************************         *          ***********************\n");
    	printf("******************               *                *****************\n");
    	printf("************                     *                     ************\n");
    	printf("*******************************************************************\n");
    	printf("请选择:\n");
    }
    void game()
    {
    	printf("欢迎玩家进入游戏:\n");
    	
    	int gametype = 0;//游戏类型
    	int boardtype = 0;//棋盘大小的确定
        again:
    	printf("请选择游戏类型: 1.三子棋游戏(建议3*3的棋盘)  2.五子棋游戏\n");
    	scanf("%d", &gametype);//让玩家选择游戏类型
    	if (gametype != 1 && gametype != 2)
    	{
    		printf("选择错误,牛牛还未开发此类型游戏。\n");
    		printf("请重新选择:\n");
    		goto again;
    	}
    	printf("请选择棋盘类型:n*n,你希望n的值为多少?(1);
    	scanf("%d", &boardtype);
    	if (gametype == 2 && boardtype < 5 || gametype == 1 && boardtype < 3)//避免选五子棋的棋盘小于5*5,和三子棋小于3*3的棋盘
    	{
    		printf("棋盘不符合要求:请重新选择:\n");
    		goto again;
    	}
    	else if (boardtype > ROW)//选择的棋盘最大不得超过15*15
    	{
    		printf("超出棋盘最大设置范围(15*15):\n请重新选择:\n");
    		goto again;
    	}
    	char board[ROW][COL] = { 0 };//定义一个2维数组,最大为15*15,用于存放棋子
    	char ret = 0;//设置判断输赢的返回值。
    	//打印数组的元素
    	init_board(board, ROW, COL);//初始化棋盘,使其值全为空格
    	print_board(board, boardtype, boardtype);//打印棋盘的外观和内容
    	
    	while (1)//游戏开始
    	{
    		palyer(board, boardtype, boardtype);//玩家下棋
    		print_board(board, boardtype, boardtype);//打印棋盘
    		if (gametype == 1)//根据类型现在判断输赢的类型
    		{
    			ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    		}
    		else
    		ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    		if (ret != 'c')
    		{
    			break;
    		}
    		computer(board, boardtype, boardtype);//电脑下棋
    		print_board(board, boardtype, boardtype);//打印棋盘
    		if (gametype == 1)//根据类型现在判断输赢的类型
    		{
    			ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    		}
    		else
    			ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    		if (ret != 'c')
    		{
    			break;
    		}
    	}
    	if (ret == '*')
    	{
    		printf("玩家胜利\n");
    	}
    	else if (ret == '#')
    	{
    		printf("电脑胜利\n");
    	}
    	else
    	{
    		printf("平局\n");
    	}
    }
    int main()
    {
    	int n = 0;//记录玩家在菜单中的选择
    	srand((unsigned int)time(NULL));//与前面介绍的猜数字游戏一样,改变种子值来使得rand函数每次生成不同的随机数列。
    	do
    	{
    		menu();
    		scanf("%d", &n);//让玩家在菜单中选择
    		switch (n)
    		{
    		case 1://代表玩游戏
    			game();
    			printf("再来一局吗?\n");
    			printf("1.再来一局   2. 没意思不玩了\n");
    			int again = 0;//存放玩家是否再玩的结果。
    			scanf("%d", &again);
    			if (again == 1)
    			{
    				break;
    			}
    			else
    				n = 2;//令n=2循环结束
    			break;
    		case 2:
    			printf("退出游戏");
    			break;
    		default:
    			printf("没有这个选项哦。\n");//玩家不小心输错了
    			break;
    		}
    	} while (n - 2);//当玩家选择2时,代表不玩了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    3.2.函数声明区(game.h):

    #define _CRT_SECURE_NO_WARNINGS 1
    #pragma once
    #include 
    #include 
    #include 
    #define ROW 15//为了方便改变棋盘大小
    #define COL 15
    void init_board(char board[ROW][COL], int row, int col);//初始化棋盘
    void print_board(char board[ROW][COL], int row, int col);//打印棋盘
    void palyer(char board[ROW][COL], int row, int col);//玩家下棋
    void computer(char board[ROW][COL], int row, int col);//电脑下棋
    char who_win3(char board[ROW][COL], int row, int col);//判断三子棋输赢
    char who_win5(char board[ROW][COL], int row, int col);//判断五子棋输赢
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.3.函数实现区(game.c):

    #define _CRT_SECURE_NO_WARNINGS 1
    #include "game.h"
    void init_board(char board[ROW][COL], int row, int col)//初始化棋盘
    {
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)
    	{
    		for (j = 0; j < col; j++)
    		{
    			board[i][j] = ' ';//初始化棋盘的内容为全空格
    		}
    	}
    }
    void print_board(char board[ROW][COL], int row, int col)//打印棋盘//建议参照棋盘的外观
    {
    
    	int i = 0, j = 0;
    	printf(" ");//为了对齐
    	for (i = 1; i <= row; i++)//打印显示在第一行的列标
    	{
    		printf("%3d ",i);//因为一个格子3个位置
    	}
    	printf("\n");
    	printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
    	for (i = 0; i < row; i++)//打印一行外观的分割线
    	{
    		printf("---+");
    	}
    	printf("\n");//每次打印一行就要换行
    	for (i = 0; i < row; i++)
    	{
    		printf("%2d", i+1);
    		printf("|");//和上面一样,先打印一个 | ,可以观察棋盘外观,将棋盘外观拆分打印。
    		for (j = 0; j < col; j++)//打印一行中间的棋子和其它分割线
    		{
    			printf(" %c |", board[i][j]);//这里打印的是“空格”“棋子”“空格”“|”
    		}
    		printf("\n");//每次打印一行就要换行
    		printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
    		for (j = 0; j < col; j++)//打印一行外观的分割线
    		{
    			printf("---+");//每次打印一行就要换行
    		}
    		printf("\n");
    	}
    }
    void palyer(char board[ROW][COL], int row, int col)
    {
    	int x = 0, y = 0;//定义x 和 y变量存储棋子的坐标
    	printf("请玩家下棋:\n");
    	while (1)
    	{
    		printf("请输入行号和列标:(用空格隔开)\n");
    		scanf("%d%d", &x, &y);
    		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法,由于玩家并不是程序员,所以坐标要正常从1开始
    		{
    			if (board[x - 1][y - 1] == ' ')//落子处为空格,表示此处还未被占用。
    			{
    				board[x - 1][y - 1] = '*';//玩家下棋为‘*’,将输入的坐标位置占据。
    				break;//表示落子成功,结束循环,轮到电脑下了
    			}
    			else//如果此处不是空格,则表示此处已经有棋子了。
    			{
    				printf("该处已经被占用了,请重新选择\n");
    			}
    		}
    		else//如果坐标不在1到3之间,则棋子超出合法范围,
    		{
    			printf("该坐标非法,已经超过棋盘,无法识别\n");
    			printf("请重新选择:\n");
    		}
    	}
    }
    void computer(char board[ROW][COL], int row, int col)//电脑下棋中
    {
    	printf("电脑下棋中:\n");
    	while (1)
    	{
    		int x = rand() % row;//生成0到2的随机数作为棋子下标
    		int y = rand() % col;
    		if (board[x][y] == ' ')//找到棋盘中的空余位置进行下棋
    		{
    			board[x][y] = '#';
    			break;
    		}
    	}
    
    }
    int draw(char board[ROW][COL], int row, int col)//判断平局
    {
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)
    	{
    		for (j = 0; j < col; j++)
    		{
    			if (board[i][j] == ' ')
    			{
    				return 0;
    			}
    		}
    	}
    	return 1;
    }
    char who_win3(char board[ROW][COL], int row, int col)//三子棋判断输赢
    {
    
    
    	int i = 0, j = 0;
    	for (i = 0; i < row; i++)//判断每行,所以i要取0到row(不包含row)
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
    				//判断每行是否有相连的3个元素,并且不是空格
    			{
    				return board[i][j];
    			}
    		}
    	}
    	for (j = 0; j < col; j++)//判断每列
    	{
    		for (i = 0; i + 2 < row; i++)
    		{
    			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
    				//判断每列是否有相连的3个元素,并且不是空格
    			{
    				return board[i][j];
    			}
    		}
    	}
    	for (i = 0; i + 2 < row; i++)//判断主对角线和主对角线平行的线
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	for (i = 2; i < row; i++)//判断反对角线和与反对角线平行的线
    	{
    		for (j = 0; j + 2 < col; j++)
    		{
    			if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2]  && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	if (1 == draw(board, ROW, COL))
    	{
    		return 'p';
    	}
    	else
    		return 'c';
    }
    char who_win5(char board[ROW][COL], int row, int col)//五子棋判断输赢
    {
    	int i = 0;
    	int j = 0;
    	for (i = 0; i < row; i++)//判断每行
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j + 2] == board[i][j + 3] && board[i][j + 3] == board[i][j + 4] && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	for (j = 0; j < row; j++)//判断每列
    	{
    		for (i = 0; i + 4 < row; i++)
    		{
    			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	for (i = 0; i + 4 < row; i++)//判断主对角线和主对角线平行的线
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4] && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	for (i = 4; i < row; i++)//判断反对角线和与反对角线平行的线
    	{
    		for (j = 0; j + 4 < col; j++)
    		{
    			if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4] && board[i][j] != ' ')
    				return board[i][j];
    		}
    	}
    	if (1 == draw(board, ROW, COL))
    	{
    		return 'p';
    	}
    	else
    		return 'c';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196

    结语

    怎样可以让电脑变得更加聪明呢?怎样实现n子棋的玩法而不是限制了三子棋和五子棋的玩法呢?判断输赢能否有更简单的方法?这些都需要更加聪明的牛牛才能实现,现在牛牛的能力有限,还在成长当中。希望看了这篇文章对大家有帮助。欢迎小伙伴们私信提意见和提问哦!今天牛牛的小游戏就分享到这里了。
    最后,小伙伴们的点赞就是给牛牛最大的支持,能不能给牛牛来一个一键三连呢?谢谢支持。

  • 相关阅读:
    k8s实践记录
    面向对象【static关键字】
    2022年最新宁夏建筑安全员模拟题库及答案
    C#生成anb文件
    分布形态的度量-偏度系数与峰度系数的探讨
    谷歌Chrome庆祝15周年,推出全新设计!了解最新信息!
    Mac M芯片上安装统信UOS 1070arm64虚拟机
    【动手学深度学习】学习笔记
    linux下安装ffmpeg的教程
    【Shiro】基本使用
  • 原文地址:https://blog.csdn.net/qq_67276605/article/details/127811147