【C语言】简易三子棋设计

三子棋想必大家都不陌生,甚至和小伙伴玩了不知道多少遍,我也不例外。
特别是以前电子产品不普及的时候,那个时候那张纸,画个井字,就可以和小伙伴玩了。【C语言】简易三子棋设计_第1张图片

那么今天我将来介绍一下如何用C语言设计简易的三子棋游戏。(我们规定玩家的棋子为’*’,电脑的棋子为’#’)
首先进入游戏,我们需要设计一个菜单内容,大概是下面这个样子:
【C语言】简易三子棋设计_第2张图片
用四个printf函数即可实现

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

然后对于选项我们需要做出相应的响应,即玩家选1时开始游戏,玩家选0时结束游戏,玩家输入其他数字则提示玩家重新输入,以保证代码的健壮性,故我们可以用一个switch语句实现,设置一个input变量以接收玩家的输入,而且为了让玩家可以多次游玩,我们使用一个do while语句来保证游戏的重复,代码实现如下:

int main()
{
	int input = 0;
	do 
	{
		menu();//打印菜单
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束,程序退出\n");
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

接下来就需要实现这里的game()函数了,首先我们要设计一个棋盘来进行游戏,如何构建一个棋盘呢,首先我们要知道棋盘的大致样子:
【C语言】简易三子棋设计_第3张图片
【C语言】简易三子棋设计_第4张图片
从图中我们可以看出三子棋的棋盘有五行组成,那么我们可以用循环来打印出棋盘,这里我们用char型的二维数组存放棋盘中的棋子,代码如下:

    //符号的定义,之后更改棋盘大小更加方便
    #define ROW 3
    #define COL 3
	//设置棋盘--二维数组
	char board[ROW][COL];
	//初始化棋盘
	InitBroad(board, ROW, COL);
	//打印棋盘
	DisplayBroad(board, ROW, COL);

函数实现:

void InitBroad(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 DisplayBroad(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++)//棋盘列数
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)//保证棋盘的美观性,最后一列的‘|’不打印
				printf("|");
		}
		printf("\n");//换行
		if (i < row - 1)//同意棋盘最后一行的‘--- ’也不打印
			for (j = 0; j < col; j++)
				printf("--- ");
		printf("\n");
	}
}

注意这里的数组初始化是必要的,否则数组的打印可能是随机的(如图):

【C语言】简易三子棋设计_第5张图片
打印出棋盘后就需要实现玩家和电脑的交互了,首先来实现玩家走的部分:

		//玩家走
		PlayerMove(board, ROW, COL);
		DisplayBroad(board, ROW, COL);//每次走完更新一次棋盘

由于数组的下标是从0开始的,而玩家一般认为坐标是总1开始的,故在处理玩家输入的坐标时要-1确保落子的正确性,同时要判断玩家输入的坐标的合法性,是否落在棋盘内且该处无棋子,那么代码的实现就很明显了:

void PlayerMove(char board[ROW][COL], int row, int col)
{
	printf("玩家走:\n");
	while (1)
	{
		printf("请输入坐标:\n");
		int x = 0;//接收坐标
		int y = 0;
		scanf("%d %d", &x, &y);
		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '*';
			break;
		}
		else
		{
			printf("坐标非法,请重新输入:\n");
		}
	}

}

对于电脑,我们使用随机数来确定电脑的落子,则需要使用到rand()函数产生随机数,而电脑的落子是有我们设计的,故不需要判断合法性,代码实现与玩家略有不同:

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	srand((unsigned int)time(NULL));
	printf("电脑走:\n");
	while (1)
	{
		x = rand() % 3;//产生0-2的随机数字作为数组下标
		y = rand() % 3;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

最后也是最为关键的步骤就是判断游戏进程,游戏每落下一次子就会产生四种状态,即玩家赢,电脑赢,平局以及游戏继续,不妨令这些状态分别对应四个不同的字符,即玩家赢:返回’*’,电脑赢,返回’#’,平局,返回’Q’,游戏继续,返回’C’,这里我们设计一个返回类型为char型的Judgegame()函数来接收对应的游戏状态,并将返回值赋给ret变量,在每次的落子后判断一下。

        PlayerMove(board, ROW, COL);
		DisplayBroad(board, ROW, COL);//每次走完更新一次棋盘
		//判断游戏状态
		ret = Judgegame(board, ROW, COL);
		if (ret == '*')
		{
			printf("玩家赢\n");
			break;
		}
		else if (ret == 'Q')
		{
			printf("平局\n");
			break;
		}
		//电脑走
		ComputerMove(board, ROW, COL);
		DisplayBroad(board, ROW, COL);
		ret = Judgegame(board, ROW, COL);
		if (ret == '#')
		{
			printf("电脑赢\n");
			break;
		}
		else if (ret == 'Q')
		{
			printf("平局\n");
			break;
		}

那么我们来实现一下Judgegame函数,直接上代码:

char Judgegame(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 - 2; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//列相等
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 2; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
				return board[i][j];
		}
	}
	//主对角线相等
	for (i = 0; i < row - 2; i++)
	{
		for (j = 0; j < col - 2; 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 = 0; i < row - 2; i++)
	{
		for (j = col - 1; j > 1; 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 (IsFull(board, row, col))//判断棋盘是否满,满则平局,不满则游戏继续
		return 'Q';
	else
	return 'C';
}
int IsFull(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++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

由于三子棋的规则是有三个子连成一条线则判断胜利,故我们穷举出所有的胜利条件,而返回的*和#刚好是我们的棋子,故这里的设计是十分巧妙的,并且为了不把代码写死,我们将判断变为遍历整个棋盘去找出是否有三子连成直线,以便棋盘扩大后的实现。

至此,我们的三子棋游戏已经大致设计完毕了,我们先来一把看看效果:
【C语言】简易三子棋设计_第6张图片
由于电脑的落子是由随机数产生的,故电脑想要赢是比较难的,只能通过放水来让电脑赢:
【C语言】简易三子棋设计_第7张图片
最后再来看一下平局:
【C语言】简易三子棋设计_第8张图片
由于是简易版的三子棋设计,因此就游戏性而言肯定是设计的不够好的,在之后更深入的学习之后,还可以实现电脑的走法更加的完善,而非随机走。
那么这就是这次简易三子棋的C语言程序设计了,
完整的代码
希望大家能够点个赞~

你可能感兴趣的:(C语言,c语言,数组)