舌尖上的C——三子棋的慢烹细作

传统艺能?

小编是大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】点我!点我!请搜索博主 【知晓天空之蓝】或扫码进入!
乔乔的gitee代码库(打灰人欢迎访问,点我!
在这里插入图片描述

(https://blog.51cto.com)感谢支持!

过渡区?

现在是北京时间3:12,1:12开始写,本来打算在12点前赶一篇博客出来,想想还是算了,事情确实太多了,今天就先熬夜把博客写了,昨天没写手就够痒了,反正明天早上一二节没课就寻思来续命咯。

在这里插入图片描述

正片开始?

准备?

今晚是个大工程,但是咱不急,工欲善其事,必先利其器,先来看看需要哪些“器”:
1.一大饼函数(随机值rand函数,srand函数,自义定函数……);
2.一小撮头文件:<stdlib.h>,<time.h>,<stdio.h>;
3.格局打开:封装函数,提高可读性与逻辑感;test.c存放main函数,用来当作程序的入口,引用game.h头文件(引用自己写的头文件记得是双引号“game.h”),game.c中存放实现工程的主体函数,game.h中则存放各种函数的声明以及VS提供的头文件的包含;
4.一大堆二维数组的运用;
5.错综的分支与循环语句的嵌套使用;
6.善于分析的脑瓜子和勤快的小手手;
如果以上东西你都没有问题,那我们就不用废话,直接进入正题。

洋葱战略?

对待问题就要像洋葱一样一层一层一层的剥开,接下来就带大家来剥洋葱
**

1.万金油开头少不了?

int main()
{
	test();
	return 0;
}

2.上菜得先上菜单?

先用一个test函数将菜单唤出来,之所以不写在main函数里面是方便食用。

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));//随机数发生器的初始化函数,利用时间戳生成伪随机数
    do//至少进行一次该过程
	{
		menu();
		printf("请选择菜单:>");
		scanf("%d", &input);//将值存入input以实现菜单选择功能
		switch (input)
		{
		case 1:
		{
			printf("三子棋n");
		    game();//进入游戏主体
			break;
		}
		case 0:
		{
			printf("即将退出……");
			break;
		}
		default:
		{
			printf("玩儿呢?n");//防特殊情况防皮
			break;
		}		
		}
	} while (input);//实现游戏的重复游玩
}

3.游戏的入口——菜单?

简简单单搞了一个菜单出来,诸君可肆意发挥,我懒惰的天性造就了它平庸的外表。

void menu()
{
printf("------------------------------------n");
printf("------------------------------------n");
printf("-------1.P    L    A    Y-----------n");
printf("-------0.E    X    I    T-----------n");
printf("------------------------------------n");
printf("------------------------------------n");
}

当你输入“ 1 ”时就正式开始了。

4.游戏主体?

这里就需要动一下脑筋了,因为需要安排的东西突然就暴涨,制定规则就重在效率与目的并持。
首先在规则之下,需要实现的是三子棋的物质表达,即棋盘的设计,高大上一点就是在搭建游戏环境。棋盘是方的,那我们就用二维数组行列式的相似性来模拟棋盘,这里我设置一个名为 board 的数组。
**

1.棋盘初始化?

**
为了能搞出一个棋盘,我得用数据告诉编译器一个棋盘的轮廓:既然是三子棋,我们就先从最简单的3*3开始,分别用ROW(行),COL(列)来指定数组元素。
为了方便写也为了方便读,我们将ROW和COL在game.h头文件中宏定义使用:

# define ROW 3
# define COL 3

这样写也有一个好处,想要改变棋盘大小就会很简单,只需改变数字的大小,无需大费周章的到处去改这改那。

void Printboard(char board[ROW][COL], int row, int col)
{
	int i = 0;//数组下标从0开始
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)//嵌套循环来完成整个数组
		{
			board[i][j] = ' ';//将i行j列的数组初始化为空,用来布局和放入棋子
		}
	}
}

**

2.打印棋盘?

**
万事俱备只欠东风,代码直接上:

void Display(char board[ROW][COL], int row, int col)
{
	int i, j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);//放入%c以作为棋子位存放棋子
			if (j < col - 1);//棋盘美观去掉最外面的分隔线
			printf("|");
		}
		printf("n");//换行打印横线
		if(i<row-1)
		{	
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1);
				printf("|");//同理打印分隔线
			}
		}
		printf("n");
	}
}

这里自定义的Display函数,效果如下:
在这里插入图片描述
**

棋手操作?

**
棋盘搞好了就可以下了嘛,这里要实现下的话,就需要我们玩家的下棋函数和一个24小时在线陪玩的憨憨人机,我们就用 player 函数和 X_MAN函数实现(取名是一种艺术):

void player(char board[ROW][COL], int row, int col)//玩家
{
	int x = 0;//模拟行数
	int y = 0;//模拟列数
	printf("玩家请输入棋子坐标:>");坐标模拟棋格
	scanf("%d%d", &x, &y);
	while (1)
	{
		if (row >= x && x >= 1 && y >= 1 && y <= col)//界定有效范围
		{
			if (board[x - 1][y - 1] == ' ')//人性化,按玩家眼中的棋盘设计
			{
				board[x - 1][y - 1] = '*';//如果本格为空,则将棋子*放入
				Display(board, row, col);//显示当前布局
				break;
			}
			else
			{
		     	printf("无效棋格,请重新输入n");//防止占用
				break;
			}
	    }
	       else
		{
			printf("你下到棋盘外了!n");//越界警告
		}
	}
}

相比之下,人机就好写一些了;
这里注意两个重点:1.伪随机数初始化函数记得放在上一级函数或者主函数里面;
2.电脑不需要像对玩家一样“ -1”操作,电脑自己是可以识别的;

void x_man(char board[ROW][COL], int row, int col)//人机
{
	int x = 0;
	int y = 0;
	printf("人机下:n");
	while(1)
	{
		x = rand() % ROW;//ROW,COL范围0~2,得到0~2随机值
		y = rand() % COL;//同理
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			Display(board, row, col);
			break;
		}	
	}	
}

**

判断?

**
下棋要判断才有输赢对吧,不然咱就是在和电脑搞打字联谊。
我们就搞一个 winor函数来实现,基本思路是要实现三种情况:
1.玩家赢:
分为横三列赢,竖三列赢,对角线赢。实现条件判断我的思路简单粗暴,就是传递性连着三个元素俩俩相等,最后保证都不为空格就行(其中一个不为空就行);
2.五五开;我们又需要一个Full函数来满足平局的判断,即棋盘下满时并未满足输赢条件我们就给出平局的结果
3.电脑赢;
具体如下:

char winor(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')//横赢
		{
			return board[i][1];
		}
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')//竖赢
		{
			return board[1][i];
		}
	}
		 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')//对角线赢
		{
			return board[0][0];
		}
		 if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')//对角线赢
		{
			return board[0][2];
		}
		if (1==Full(board, row, col))//Full函数判断平局
		{
			return  'p';
		}
		return 'c';
}

Full函数定义如下:

int Full(char board[ROW][COL], int row, int col)
{
	int i,j = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (board[i][j] == ' ')//有空格则不满足平局继续循环
			{
				return 0;
			}
		}
	}
	return 1;循环完未发现空格则返回1表示平局
}

当以上步骤完成时,我们代入主体的game函数中进行逻辑组装,如下:

void game()
{
	char board[ROW][COL] = { 0 };
	Printboard(board, ROW, COL); //初始化棋盘
	Display(board, ROW, COL);//打印棋盘
	char ret = 0;
	while (1)//循环以持续游戏进行
	{
		player(board, ROW, COL);//玩家先走
		ret = winor(board, ROW, COL);//进入结果判断
		if (ret != 'c')//非“继续”结果跳出
		{
			break;
		}
		x_man(board, ROW, COL);//人机后走
		ret = winor(board, ROW, COL);//再次判断
		if (ret != 'c')
		{
			break;
		}
	}
		if (ret == 'p')
			printf("平局!n");
		else if (ret == '*')
			printf("你赢了!n");
		else
			printf("你输了n");//返回值对应判断三种游戏结果
	
}

战略总览?

整个游戏到这里就完成了,给整理出来完整的工程如下:

test.c?

# include"game.h"
void menu()
{
printf("------------------------------------n");
printf("------------------------------------n");
printf("-------1.P    L    A    Y-----------n");
printf("-------0.E    X    I    T-----------n");
printf("------------------------------------n");
printf("------------------------------------n");
}
void game()
{
	char board[ROW][COL] = { 0 };
	Printboard(board, ROW, COL); 
	Display(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		player(board, ROW, COL);
		ret = winor(board, ROW, COL);
		if (ret != 'c')
		{
			break;
		}
		x_man(board, ROW, COL);
		ret = winor(board, ROW, COL);
		if (ret != 'c')
		{
			break;
		}
	}
		if (ret == 'p')
			printf("平局!n");
		else if (ret == '*')
			printf("你赢了!n");
		else
			printf("你输了n");
	
}

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择菜单:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		{
			printf("三子棋n");
		    game();
			break;
		}
		case 0:
		{
			printf("即将退出……");
			break;
		}
		default:
		{
			printf("玩儿呢?n");
			break;
		}		
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

game.c?

# define _CRT_SECURE_NO_WARNINGS 

# include"game.h"

void Printboard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}
void Display(char board[ROW][COL], int row, int col)
{
	int i, j = 0;
	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 (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1);
				printf("|");
			}
		}
		printf("n");
	}
}
void player(char board[ROW][COL], int row, int col)//玩家
{
	int x = 0;
	int y = 0;
	printf("玩家请输入棋子坐标:>");
	scanf("%d%d", &x, &y);
	while (1)
	{
		if (row >= x && x >= 1 && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				Display(board, row, col);
				break;
			}
			else
			{
				printf("无效棋格,请重新输入n");
				break;
			}
	    }

	       else
		{
			printf("你下到棋盘外了!n");
		}
	}
}
void x_man(char board[ROW][COL], int row, int col)//人机
{
	int x = 0;
	int y = 0;
	printf("电脑走:n");
	while(1)
	{
		x = rand() % ROW;
		y = rand() % COL;  //0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			Display(board, row, col);
			break;
		}	
	}	
}
int Full(char board[ROW][COL], int row, int col)
{
	int i,j = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}
char winor(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
			return board[i][1];
		}
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[1][i];
		}
	}
		 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
		{
			return board[0][0];
		}
		 if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
		{
			return board[0][2];
		}
		if (1==Full(board, row, col))
		{
			return  'p';
		}
		return 'c';
}

game.h?

#pragma once
# define ROW 3
# define COL 3

# include<stdio.h>
# include<stdlib.h>
# include<time.h>

void game();
void Printboard(char board[ROW][COL], int row, int col);
void menu();
void Display(char board[ROW][COL], int row, int col);
void player(char board[ROW][COL], int row, int col);
void x_man(char board[ROW][COL], int row, int col);
char winor(char board[ROW][COL], int row, int col);

运行结果如下:

在这里插入图片描述
今天就到这里吧,躺平咯家人们,不然明天上课就得躺平了

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>