【C语言】数组的应用——三子棋、扫雷

目录

1. 三子棋

1.1 创建文件

1.2 设计游戏大致流程

1.3 设计菜单

1.4 设计游戏

1.4.1 创建棋盘

1.4.2 初始化棋盘

1.4.3 打印棋盘

1.4.4 下棋

1.4.5 打印结果并打印棋盘

1.5 完整代码

2. 扫雷

2.1 创建文件

2.2 设计游戏大致流程

2.3 设计菜单

2.4 设计游戏

2.4.1 创建棋盘

2.4.2 初始化棋盘

2.4.3 布置雷

2.4.4 打印棋盘

2.4.5 排查雷

2.5 完整代码


1. 三子棋

1.1 创建文件

创建一个头文件game.h:游戏代码的声明(函数声明、符号定义)

创建两个源文件game.c:游戏代码的实现

                            test.c:测试游戏的逻辑

1.2 设计游戏大致流程

游戏流程至少执行1次,所以用do while循环。

  1. 打印菜单:1. play 0. exit
  2. 玩家输入1/0选择是否进入游戏
  3. 输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
//test.c
int main()
{
	int input = 0;
	do
	{
		//打印菜单
        menu();
        //玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
        //输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}
//game.h
//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>

1.3 设计菜单

//test.c
//菜单
void menu()
{
	printf("*****************************\n");
	printf("*****  1. play  0. exit *****\n");
	printf("*****************************\n");
}

1.4 设计游戏

1.4.1 创建棋盘

创建3×3的二维数组当作棋盘,在game.h中定义ROW和COL的值均为3,这样如果要修改ROW和COL的值,只需要在game.h中修改即可。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
}
//game.h
//如果要修改ROW和COL的值,只需要修改#define这两行代码即可
#define ROW 3
#define COL 3

1.4.2 初始化棋盘

遍历二维数组, 令二维数组每个元素都是空格。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
}
//game.c
//初始化棋盘
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] = ' ';
		}
	}
}
//game.h
//初始化棋盘函数声明
void InitBoard(char board[ROW][COL], int row, int col);

1.4.3 打印棋盘

打印棋子和网格。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
}

打印棋盘函数版本1——容易看懂版:

//game.c
//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据
		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		//打印分割信息
		if(i<row-1)
			printf("---|---|---\n");
	}
}

打印棋盘函数版本2——高大上版:

//game.c
//打印棋盘
void DispalyBoard(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]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		if (i < row - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}
//game.h
//打印棋盘函数声明
void DispalyBoard(char board[ROW][COL], int row, int col);

棋盘展示:

1.4.4 下棋

双方下棋过程是无限循环的,直到有一方赢了或平局,跳出循环,结束下棋,所以下棋过程放在while(1)循环内。

玩家的棋子为*,电脑的棋子为#。

1.4.4.1 玩家下棋

数组的下标是从0开始的,而玩家认为行和列的坐标都是从1开始的,如图所示:

123
1棋盘格棋盘格棋盘格
2棋盘格棋盘格棋盘格
3棋盘格棋盘格棋盘格

玩家可能会输入被占用的或棋盘外的坐标,此时需要重新下棋,如果一直输入错误,则玩家下棋无限循环,直到输入合法的坐标,跳出循环,结束玩家下棋,所以玩家下棋放在while(1)循环内。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
	}
}
//game.c
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋:>\n");
	while (1)
	{
        int x = 0;
	    int y = 0;
        //输入下棋坐标
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		//坐标范围合法的判断
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,不能下棋,请选择其他位置\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}
//game.h
//玩家下棋函数声明
void PlayerMove(char board[ROW][COL], int row, int col);

1.4.4.2 判断输赢

设计判断输赢函数,返回类型为char型,所以要先创建一个char型变量ret,用于接收返回值。如果行或列或对角线三个棋子相同,则返回棋子(即玩家赢返回*,电脑赢返回#)。平局返回D,继续返回C。如果玩家赢或电脑赢或平局,则跳出循环,结束下棋。

平局即棋盘被占满的情况,设计判断棋盘是否被占满函数,返回类型为int型,被占满返回1,没被占满返回0。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
}
//game.c
//判断输赢
char IsWin(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][1] != ' ')
			return board[i][1];
	}
	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
			return board[1][j];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];
	//平局
	if (IsFull(board, row, col))
		return 'D';
	//继续
	return 'C';
}
//game.h
//判断输赢函数声明
char IsWin(char board[ROW][COL], int row, int col);
//game.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;//没被占满返回0
		}
	}
	return 1;//被占满返回1
}

1.4.4.3 打印棋盘

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
        //打印棋盘
		DispalyBoard(board, ROW, COL);
	}
}

1.4.4.4 电脑下棋

电脑在空格子随机下棋,需要在循环内使用rand()函数,循环外使用srand((unsigned int)time(NULL))使每次生成的随机数序列都是不同的。

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
        //打印棋盘
		DispalyBoard(board, ROW, COL);
        //电脑下棋
		ComputerMove(board, ROW, COL);
	}
}

int main()
{
    //设置随机数种子
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		//打印菜单
        menu();
        //玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
        //输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}
//game.c
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	while (1)
	{
		int x = rand() % row;//0~2
		int y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}
//game.h
//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//电脑下棋函数声明
void ComputerMove(char board[ROW][COL], int row, int col);

1.4.4.5 判断输赢

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
        //打印棋盘
		DispalyBoard(board, ROW, COL);
        //电脑下棋
		ComputerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
}

1.4.4.6 打印棋盘

//test.c
//游戏
void game()
{
    //创建棋盘
	char board[ROW][COL] = { 0 };
    //初始化棋盘
	InitBoard(board, ROW, COL);
    //打印棋盘
	DispalyBoard(board, ROW, COL);
    //下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
        PlayerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
        //打印棋盘
		DispalyBoard(board, ROW, COL);
        //电脑下棋
		ComputerMove(board, ROW, COL);
        //判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
        //打印棋盘
		DispalyBoard(board, ROW, COL);
	}
}

1.4.5 打印结果并打印棋盘

//test.c
//游戏
void game()
{
	//创建棋盘
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DispalyBoard(board, ROW, COL);
	//下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//打印棋盘
		DispalyBoard(board, ROW, COL);
	}
	//打印结果
	if (ret == '*')
		printf("玩家赢\n");
	else if (ret == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");
	//打印棋盘
	DispalyBoard(board, ROW, COL);
}

1.5 完整代码

game.h:

#pragma once//预处理指令,保证头文件只能被编译一次

//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//如果要修改ROW和COL的值,只需要修改#define这两行代码即可
#define ROW 3
#define COL 3

//初始化棋盘函数声明
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘函数声明
void DispalyBoard(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);

game.c:

#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 DispalyBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
		//打印数据
//		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		//打印分割信息
//		if(i<row-1)
//			printf("---|---|---\n");
//	}
//}

//打印棋盘2
void DispalyBoard(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]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		if (i < row - 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)
{
	printf("玩家下棋:>\n");
	while (1)
	{
		int x = 0;
		int y = 0;
		//输入下棋坐标
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		//坐标范围合法的判断
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,不能下棋,请选择其他位置\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	while (1)
	{
		int x = rand() % row;//0~2
		int y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//判断棋盘是否被占满
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;//没被占满返回0
		}
	}
	return 1;//被占满返回1
}

//判断输赢
char IsWin(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][1] != ' ')
			return board[i][1];
	}
	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
			return board[1][j];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];
	//平局
	if (IsFull(board, row, col))
		return 'D';
	//继续
	return 'C';
}

test.c:

#include "game.h"

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

//游戏
void game()
{
	//创建棋盘
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DispalyBoard(board, ROW, COL);
	//下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//打印棋盘
		DispalyBoard(board, ROW, COL);
	}
	//打印结果
	if (ret == '*')
		printf("玩家赢\n");
	else if (ret == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");
	//打印棋盘
	DispalyBoard(board, ROW, COL);
}

int main()
{
	//设置随机数种子
	srand((unsigned int)time(NULL));	
    int input = 0;
	do
	{
		//打印菜单
		menu();
		//玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
		//输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}

运行结果:

2. 扫雷

2.1 创建文件

创建一个头文件game.h:游戏代码的声明(函数声明、符号定义)

创建两个源文件game.c:游戏代码的实现

                            test.c:测试游戏的逻辑

2.2 设计游戏大致流程

游戏流程至少执行1次,所以用do while循环。

  1. 打印菜单:1. play 0. exit
  2. 玩家输入1/0选择是否进入游戏
  3. 输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
//test.c
int main()
{
	int input = 0;
	do
	{
		//打印菜单
        menu();
        //玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
        //输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}
//game.h
//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>

2.3 设计菜单

//test.c
//菜单
void menu()
{
	printf("*****************************\n");
	printf("*****  1. play  0. exit *****\n");
	printf("*****************************\n");
}

2.4 设计游戏

2.4.1 创建棋盘

要想展示9×9的棋盘,就要创建11×11的二维数组。因为计算一个坐标周围的雷的个数时,会计算周围八个坐标中雷的个数之和,当坐标为边界时,计算周围的雷的个数会发生数组越界,所以应在9×9的基础上增加两行两列,创建11×11的二维数组。

创建2个11×11的二维数组,一个用来存放布置好的雷的信息,一个用来存放排查出的雷的信息。

//test.c
//游戏
void game()
{
    //创建棋盘
    //存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
    //存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
}
//game.h
//如果要修改ROW和COL的值,只需要修改#define这几行代码即可
#define ROW 3
#define COL 3
#define ROWS ROW+2
#define COLS COL+2

2.4.2 初始化棋盘

遍历二维数组, 令二维数组每个元素都是指定内容。mine数组全部初始化为'0',show数组全部初始化为'*'。

//test.c
//游戏
void game()
{
    //创建棋盘
    //存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
    //存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
    //全部初始化为'0'
	InitBoard(mine, ROWS, COLS, '0');
    //全部初始化为'*'
	InitBoard(show, ROWS, COLS, '*');
}
//game.c
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}
//game.h
//初始化棋盘函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)

2.4.3 布置雷

电脑在mine数组的下标1~9的81个元素中随机布置雷,下标0和10为拓展的两行两列,不能布置雷,用1表示雷,定义简单模式下有10个雷。随机布置雷需要在循环内使用rand()函数,循环外使用srand((unsigned int)time(NULL))使每次生成的随机数序列都是不同的。

//test.c
//游戏
void game()
{
    //创建棋盘
    //存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
    //存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
    //全部初始化为'0'
	InitBoard(mine, ROWS, COLS, '0');
    //全部初始化为'*'
	InitBoard(show, ROWS, COLS, '*');
	//布置雷
	SetMine(mine, ROW, COL);
}

int main()
{
	//设置随机数种子
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		//打印菜单
		menu();
		//玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
		//输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}
//game.c
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//1~9
		int y = rand() % col + 1;//1~9
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
//game.h
//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义雷的个数
#define EASY_COUNT 10
//布置雷函数声明
void SetMine(char board[ROWS][COLS], int row, int col);

2.4.4 打印棋盘

打印数组元素和棋盘坐标系。

游戏过程中打印show数组的元素,没被排查的坐标为'*',被排查的坐标为周围的雷的个数(数字字符)。

游戏结束时打印mine数组的元素,即布置好的雷的信息。

//test.c
//游戏
void game()
{
    //创建棋盘
    //存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
    //存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
    //全部初始化为'0'
	InitBoard(mine, ROWS, COLS, '0');
    //全部初始化为'*'
	InitBoard(show, ROWS, COLS, '*');
	//布置雷
	SetMine(mine, ROW, COL);
    //打印show棋盘
	DisplayBoard(show, ROW, COL);
}
//game.c
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
    //打印分割线
	printf("------扫雷游戏------\n");
    //打印0 1 2 3 4 5 6 7 8 9(横轴)
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
    //打印纵轴和数组元素
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
    //打印分割线
	printf("------扫雷游戏------\n");
}
//game.h
//打印棋盘函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);

show棋盘展示:

 

mine棋盘展示:

2.4.5 排查雷

计算坐标周围的雷的个数,即计算mine数组中该坐标周围八个坐标的数字之和。

(x-1,y-1)(x,y-1)(x+1,y-1)
(x-1,y)(x,y)(x+1,y)
(x-1,y+1)(x,y+1)(x+1,y+1)
//test.c
//游戏
void game()
{
    //创建棋盘
    //存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
    //存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
    //全部初始化为'0'
	InitBoard(mine, ROWS, COLS, '0');
    //全部初始化为'*'
	InitBoard(show, ROWS, COLS, '*');
	//布置雷
	SetMine(mine, ROW, COL);
    //打印show棋盘
	DisplayBoard(show, ROW, COL);
	//排查雷
	FindMine(mine, show, ROW, COL);
}
//game.c
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win = 0;//找到的非雷的个数
	//循环排雷
	while (win < row * col - EASY_COUNT)
	{
		int x = 0;
		int y = 0;
		//输入排雷坐标
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		//坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//没排查过
			if (show[x][y] = '*')
			{
				//是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					//打印mine棋盘
					DisplayBoard(mine, ROW, COL);
					break;
				}
				//不是雷
				else
				{
					win++;
					//计算坐标周围的雷的个数
					int count = get_mine_count(mine, x, y);
					//将整型的雷的个数转化为字符型,存入数组
					show[x][y] = count + '0';//+'0'的ASCII码值,转化为字符型
					//打印show棋盘
					DisplayBoard(show, ROW, COL);
				}
			}
			//排查过
			else
				printf("该坐标被排查过了,不能重复排查\n");
		}
	    //坐标非法
	    else
			printf("输入的坐标非法,请重新输入\n");
	}
    //排雷成功
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		//打印mine棋盘
		DisplayBoard(mine, ROW, COL);
	}
}
//game.h
//排查雷函数声明
void SetMine(char board[ROWS][COLS], int row, int col);
//game.c
//计算坐标周围的雷的个数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y] +
		board[x - 1][y - 1] +
		board[x][y - 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] +
		board[x][y + 1] +
		board[x - 1][y + 1] - 8 * '0');//8个字符型数字相加-8个'0'的ASCII码值,转化为整型
}

2.5 完整代码

game.h:

#pragma once//预处理指令,保证头文件只能被编译一次

//源文件需要的头文件可以写在game.h中,这样源文件只要包含了game.h就包含了这些头文件
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//如果要修改ROW和COL的值,只需要修改#define这几行代码即可
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10

//初始化棋盘函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//布置雷函数声明
void SetMine(char board[ROWS][COLS], int row, int col);
//打印棋盘函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//排查雷函数声明
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c:

#include "game.h"

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//1~9
		int y = rand() % col + 1;//1~9
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	//打印分割线
	printf("------扫雷游戏------\n");
	//打印0 1 2 3 4 5 6 7 8 9(横轴)
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	//打印纵轴和数组元素
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	//打印分割线
	printf("------扫雷游戏------\n");
}

//计算坐标周围的雷的个数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y] +
		board[x - 1][y - 1] +
		board[x][y - 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] +
		board[x][y + 1] +
		board[x - 1][y + 1] - 8 * '0');//8个字符型数字相加-8个'0'的ASCII码值,转化为整型
}

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int win = 0;//找到的非雷的个数
	//循环排雷
	while (win < row * col - EASY_COUNT)
	{
		int x = 0;
		int y = 0;
		//输入排雷坐标
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		//坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//没排查过
			if (show[x][y] = '*')
			{
				//是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					//打印mine棋盘
					DisplayBoard(mine, ROW, COL);
					break;
				}
				//不是雷
				else
				{
					win++;
					//计算坐标四周的雷的个数
					int count = get_mine_count(mine, x, y);
					//将整型的雷的个数转化为字符型,存入数组
					show[x][y] = count + '0';//+'0'的ASCII码值,转化为字符型
					//打印show棋盘
					DisplayBoard(show, ROW, COL);
				}
			}
			//排查过
			else
				printf("该坐标被排查过了,不能重复排查\n");
		}
	    //坐标非法
	    else
			printf("输入的坐标非法,请重新输入\n");
	}
    //排雷成功
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		//打印mine棋盘
		DisplayBoard(mine, ROW, COL);
	}
}

 test.c:

#include "game.h"

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

//游戏
void game()
{
	//创建棋盘
	//存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };
	//存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
	//全部初始化为'0'
	InitBoard(mine, ROWS, COLS, '0');
	//全部初始化为'*'
	InitBoard(show, ROWS, COLS, '*');
	//布置雷
	SetMine(mine, ROW, COL);
	//打印show棋盘
	DisplayBoard(show, ROW, COL);
	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	//设置随机数种子
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		//打印菜单
		menu();
		//玩家输入1/0选择是否进入游戏
		printf("请选择:>");
		scanf("%d", &input);
		//输入1,进入游戏;输入0,退出游戏;输入其他,提示选择错误后再次进入循环
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值