Tic Tac Toe简单井字棋

前言

        井字棋是我们小时候常玩的一种简单的小游戏,今天就让我们来实践一下自己做出一个井字棋。

目录

整体思路

打印菜单

初始化棋盘

打印棋盘

玩家移动

电脑移动

判断输赢

整合

项目整体


整体思路

有一句话小黄非常赞同,”敲代码是一个项目中最简单的步骤,单纯的敲代码就和放积木一样没意思,只有决定如何去拼这个积木的时候才是最有挑战性的“。所以在完成类似的项目前,我们首先要制定一个整体的思路,然后按照框架一步步实现我们所需要的功能,才能做到快速高效的完成代码。

打印菜单

首先为了增加项目的可读性,我们可以简单加一个菜单,让玩家决定是否开始游戏,代码如下:

void meun()
{
	printf("------------------------------\n");
	printf("----------1.游戏开始----------\n");
	printf("----------0.游戏结束----------\n");
	printf("------------------------------\n");
	printf("请选择->");
}

初始化棋盘

        井字棋是一个 3  * 3 的棋盘,那么为了去表达棋子有哪些,我们采用一个字符类型的二维数组来记录当前其棋盘内的棋子。而为了可以重复开始游戏,我们每次进行完一句游戏也需要将棋盘清空,所以设置一个可以清空棋盘的函数,而之后需要打印棋盘,故初始化为空格字符,具体如下:

void IntBoard(char arr[lie][hang], int Lie, int Hang)
{
	int m, n;
	for (m = 0; m < Lie; m++)
	{
		for (n = 0; n < Hang; n++)
		{
			arr[m][n] = ' ';
		}
	}
}

打印棋盘

        为了增加可玩性,我们肯定不希望每一次下棋都需要我们自己去记住位置,因此需要设置一个可以打印当前棋盘的函数,在每次下棋之后都打印一次棋盘,具体代码如下:

void DisplayBoard(char arr[lie][hang], int Lie, int Hang)
{
	int  m, n;
	for (m = 0; m < Lie; m++)
	{
		for (n = 0; n < Hang; n++)
		{
			printf(" %c ", arr[m][n]);
			if (n < Hang - 1)
				printf("|");
		}
		printf("\n");
		if (m < Lie - 1)
			printf("---|---|--- \n");
	}
}

打印效果如图(棋盘为空的情况下):

Tic Tac Toe简单井字棋_第1张图片  

玩家移动

        当玩家开始下棋的时候我们利用 ” * “ 来代表一个棋子,但是众所周知,井字棋不一定每次都可以分出胜负,也就是说,我们还需要考虑到期盼已经被下满的情况,因此玩家下棋的时候我们总共要考虑到一下几点:

1/ 下子的地方是否有效?即是否超出界外或者已经有棋子存在。

2/ 棋盘上是否还能落子?即棋盘上的棋子数量少于等于九个。

具体代码实现如下:

void playermove(char arr[lie][hang],int *n) // n利用传址调用,实现对整个棋子数量的改变
{
	printf("轮到您下子了->");
	int x, y;
	while (1)
	{
		scanf("%d%d", &x, &y);
		if (arr[x - 1][y - 1] == ' ')
		{
			arr[x - 1][y - 1] = '*';
			++(*n);
			break;
		}
		else
			printf("你妈的看不到那里不能走吗?\n");
	}
}

电脑移动

        我们在此采用利用生成随机数的方式来模拟电脑下棋,当然这种方式下的电脑会显得特别的”蠢“。但是无妨,在此我们主要展示如何解决井字棋这样一个项目,至于如何提升电脑获胜概率可以自己思考一下。随机数我们采用srand函数来设置种子。

        在此值得注意的是,种子的设置需要放在函数之外,即游戏开始之前,这样可以避免重复设置种子导致电脑下棋时间很长,因为我们随机数也是需要判断是否可以落子的,因此随机数有可能需要多次生成,若每次生成都设置一次种子,将造成很多时间浪费,具体代码实现如下:

void computermove(char arr[lie][hang],int *a)
{
	int m, n;
	printf("轮到电脑下子了->\n");
	Sleep(2000);
	while (1)
	{
		m = rand() % 3;
		n = rand() % 3;
		if (arr[m - 1][n - 1] == ' ')
		{
			arr[m - 1][n - 1] = '#';
			++(*a);
			break;
		}
	}
}

判断输赢

        判断输赢的方式还是很简单的,判断每一行每一列以及两个斜向是否是同一种棋子即可,当我们发现是同一种棋子的时候,用一个char类型的变量记录下这个棋子,然后对其进行判断即可,同时判断是否平局也要在这一步进行,当棋子数量达到9且没有满足前面的输赢的条件时,我们就选择输出平局,并结束此局游戏,具体代码实现如下:

void iswin(char arr[lie][hang], int *n)
{
	int i;
	char k = ' ';
	for (i = 0; i < lie; i++)
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
		{
			k = arr[i][0];
			break;
		}
		else if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
		{
			k = arr[0][i];
			break;
		}
		else if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
		{
			k = arr[1][1];
			break;
		}
		else if (arr[2][0] == arr[1][1] && arr[1][1] == arr[0][2] && arr[1][1] != ' ')
		{
			k = arr[1][1];
			break;
		}
	}
	if (k == '*')
	{
		printf(" You Win! \n");
		*n = 10;
	}
	else if (k == '#')
	{
		printf(" Compuer Win! \n");
		*n = 10;
	}
	else if (k == ' ' && *n == 9)
	{
		printf(" 平局 \n");
		*n = 10;
	}
}

整合

        至此,整个游戏所需要的基本的函数我们已经全部完成,接下来,我们利用一个game函数来表示开始进行的游戏,并且把这些函数整合起来 ,同时进行一些简单的小调整,列如先前判断输赢是以函数实现的,不能直接退出game这个函数,因此单独在每次判断输赢之后加一个判断棋子数量是否未10,而棋子数量为10只有判断输赢条件成立之后对其赋值才可以实现。具体代码实现如下:

void game()
{
	char Board[lie][hang];
	int  n = 0;
	char m = 0;
	IntBoard(Board, lie, hang);
	DisplayBoard(Board, lie, hang);
	while (1)
	{
		playermove(Board, &n);
		DisplayBoard(Board, lie, hang);
		iswin(Board, &n); 
		if (n == 10)
			break;
		computermove(Board, &n);
		DisplayBoard(Board, lie, hang);
		iswin(Board, &n);
		if (n == 10)
			break;
	}
}

项目整体

        小黄在这里采用了函数分开的写法,即多文件的写法,因此将其上传到了码云,可自取,地址如下:Tic Tac Toe · 濡白/Some topics - 码云 - 开源中国 (gitee.com)

你可能感兴趣的