参考了“崩坏3”,我用C语言写出了一个游戏(TDD测试驱动开发思想与艺术)

  • TDD测试驱动开发
    测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码,并加速开发过程。
    ————转自搜狗百科

所以我们可以利用这种思路,一步一步地实现一个个的小功能,进而逐渐实现一款游戏的开发。

首先我们建立两个源文件,一个名为test.c 主要就是游戏的一个框架,里面是游戏实现的大概逻辑,另外一个名为game.c 主要用来存放封装好的函数,实现一个个小的功能。

再一个是创建一个头文件 game.h, 用来存放各种头文件和函数声明,其它源文件就可以不用再重复写各种头文件的引用了,而是直接在最前面写上include"game.h"就可以使用这个头文件中的东西了。

准备工作完成后,我们来构思一下一个游戏最开始应该是咋样的。一开始应该会出现一个选择菜单,如下图
在这里插入图片描述
会让你选择是开始游戏,还是退出游戏。
所以就需要写一个函数menu(),里面打印图形界面,如下图:
在这里插入图片描述
然后你输入你的选项。
注意:这里的选项设置得非常巧妙,读者需要后期慢慢体会,为什么不能输入其它的数字呢?

进入游戏后,你肯定会看到初始化的界面,如下图:
在这里插入图片描述
依照这样的思路,我们设计出来的游戏也应该一样,如下图:
在这里插入图片描述
所以接下来我们就要按照这种图形设计一个初始化函数InitBoard()和打印函数DispalyBoard(),函数的参数分别为数组首元素地址、横格数以及纵格数,三子棋有九个格子,我们可以用3x3的二维数组来储存棋子,那么分割线便用竖线和横线实现,也就是在初始化数组中某个元素后(将数组元素全部初始化为空格,数组类型为char型),在其后面打印出来的 ‘|’, 但是注意一排中最后一个元素后不打印。横线分隔就是在第一行数组元素打印完了后,直接打印一行由横线和竖线组合成的图形,具体代码实现请读者参考后文提供的源码,此处只是讲解了代码大概思路。

接下来我们就要开始下棋了,输入想要下棋的坐标,然后再棋盘上标记出玩家的棋子‘ * ’,接下是电脑下棋,标记‘ # ’。
当然,玩家不是程序员,输入坐标肯定没有带0的,而数组角标是从0开始的。
程序还需要判断,下棋位置是否已经有棋子了。
电脑下棋的坐标肯定需要借用随机数生成函数,先再main函数中设置一个随机种子数srand((unsighed)time(NULL)),然后再电脑下棋的函数ComputerMove()中获取随机数 rand()%3,这样就可以得到0~3的随机数了。

每一次下棋我们都需要判断一下游戏是否结束,谁赢了?平局?
首先是检验横三行,再是纵三列,最后是两条对角线上的字符是否一致。
再判断棋盘是不是满了(没有空格了),来判断是否平局。

综上所述,总结如下:我们需要写如下五个函数:初始化棋盘函数,打印棋盘函数,玩家下棋函数,电脑下棋函数,最后是判断输赢函数。

源码如下:

//game.h file
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3 //三行
#define COL 3 //三列 column

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘
void DisplayBoard(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);

//test.c file
#include"game.h"
void menu()
{
	printf("*******************************\n");
	printf("*******     1. PLAY     *******\n");
	printf("*******     0. EXIT     *******\n");
	printf("*******************************\n");
}

void game()
{
	char board[ROW][COL];
	//棋盘初始化
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		PlayerMove(board, ROW, COL);//玩家下棋
		DisplayBoard(board, ROW, COL);//下完棋后立刻打印棋盘
		//玩家下完棋后判断玩家是否胜利
		if ('*' == IsWin(board, ROW, COL))//IsWin函数返回值为'#'、'*'、'C'-游戏未完成,继续游戏、'T'-平局
		{
			printf("玩家赢了!\n");
			break;
		}
		else if ('T' == IsWin(board, ROW, COL))
		{
			printf("平局~\n");
			break;
		}
		ComputerMove(board, ROW, COL);//电脑下棋
		DisplayBoard(board, ROW, COL);//下完棋后立刻打印棋盘
		//电脑下完棋后判断电脑是否胜利
		if ('#' == IsWin(board, ROW, COL))
		{
			printf("您输了\n");
			break;
		}
		else if ('T' == IsWin(board, ROW, COL))
		{
			printf("平局~\n");
			break;
		}
	}
	DisplayBoard(board, ROW, COL);//展示最终的棋盘
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择>>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始三子棋游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

//game.c file
#include"game.h"

//初始化棋盘
void InitBoard(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 DisplayBoard(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("---");//三个
				if (j < col - 1)
				{
					printf("|");//两个
				}
			}
		}
		printf("\n");
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入您想要下棋位置的坐标:");
		scanf("%d %d", &x, &y);
		if (x > 0 && x <= col && y > 0 && y <= row)
		{
			if (' ' == board[y - 1][x - 1])
			{
				board[y - 1][x - 1] = '*';
				break;
			}
			else
			{
				printf("该位置已经有棋子了!\n");
			}
		}
		else
		{
			printf("您输入的坐标不正确!\n");
		}
	}	
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % col;
		int y = rand() % row;
		if (' ' == board[y][x])
		{
			board[y][x] = '#';
			break;
		}
	}	
}

//判断输赢
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])
		{
			return board[i][1];//返回连成三个的字符
		}
	}

	//判断列
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
		{
			return board[1][i];//返回连成三个的字符
		}
	}

	//判断斜线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
	{
		return board[1][1];//返回连成三个的字符
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
	{
		return board[1][1];//返回连成三个的字符
	}

	//判断平局-以上情况都没发生,而且每个格子都不是空的
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 'C';//游戏继续
			}
		}
	}
	return 'T';
}

代码中有有一些注释解释代码的实现。

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值