三子棋游戏简单版(电脑随机下)

时间:2023-02-16 22:59:40

这是一篇介绍三子棋代码实现的博客,采用C语言,主要介绍思路以及出现的一些错误修正,后跟随有自己实现的代码块,欢迎各位大佬指点,也希望可以给同为小白的同志一些帮助。 ps:主要函数实现已粘贴在文章中,游戏函数以及main函数放在文章末尾。

一、思考方向

1、游戏界面

  • 游戏选择菜单——do while 函数 以选择菜单的值确定是否进行游戏或退出游戏;

  • 棋子——采用二维数组 定义3×3的二维数组用于存储棋子,并初始化;

  • 棋盘——利用二维数组加上'---'与 '|'组合实现 为了便于观察,对棋子进行分割,达到视觉上清晰的效果;

2、下棋的实现

  • 玩家下棋——利用'*''#'代表棋子,在棋子数组中更换字符实现 每下一步,便打印一次棋盘,以'*'代表玩家,'#'代表电脑;

  • 电脑下棋——采用rand()函数与time函数结合,实现随机效果 更优的办法是电脑可以根据玩家下棋的位置进行堵截效果,使得电脑具有一定的游戏“水平”,奈何自己的代码水平暂时不够,只可暂且实现随机效果;

3、判断输赢

函数返回类型定义为char,返回赢方棋子,以便判断。

二、具体实现

1、选择菜单

自定义menu()函数,利用printf函数打印菜单,在main函数中以input收纳玩家选择,利用switch语句进行选择,

//选择菜单
void menu()
{
	printf("*********************\n");
	printf("*** 1、开始游戏 *****\n");
	printf("*** 0、退出游戏 *****\n");
	printf("*********************\n");
}
//主函数运行
int main()
{
	int input = 0;
	do
	{
		//打印选择菜单
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//开始游戏
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

2、 棋盘定义

采用二维数组保存棋子并初始化为' ',以#与*代表棋子。

初始化

void Initboard(char  (* board)[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] = ' ';
	}
}

打印棋盘

void Displayboard(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("|");//棋盘竖向分割线
		}
		if(i < row -1)
			printf("\n-----------\n");//棋盘横向分割线
	}
	printf("\n");
}

3、下棋

  • 玩家下 包含三种情况: a、棋盘空无棋,正常下; b、棋盘空已被棋子占用; c、坐标输入非法。
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
	int x = 0, y = 0;
	printf("玩家下\n");
	while (1)
	{
		printf("请输入要下的坐标:");
		scanf("%d %d", &x, &y);
		if (x > 0 && x <= row && y > 0 && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("坐标已被占用,请重新输入\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
	
}
  • 电脑随机下 只需判断在棋盘空处下棋便好。
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
	int x = 0, y = 0;
	
	printf("电脑下\n");
	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

4、判断输赢

每次下棋都需判断,根据判断的结果决定是否继续,判断会出现四种结果: a、玩家赢了 b、玩家输了 c、棋盘已满,造成平局 d、棋盘未满,游戏继续 此处利用简单的穷举法进行判断。

//判断输赢
//玩家赢返回‘*’,输返回‘#’,平局返回‘Q’,继续返回‘C’
static 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;//棋盘没满
		}
	}
	return 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][0] == board[i][2] && board[i][0] != ' ')
			return board[i][0];
	}
	//判断行
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
	}
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ' || board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
		return board[1][1];
	if (isfull(board, row, col))
		return 'Q';
	else
		return 'C';
}

三、一些小tip

  • 定义棋盘大小时可以采用#define定义标识符代表常量,便于后续修改;
  • 在函数传参时,传过去的二维数组须用二维数组接收,或采用数组指针;
//例如
int main()
{
	char a[3][3] = { 0 };
	test1(a);
	test2(a);
	return 0;
}
//方式1,同类型数组接收
void test1(char a[3][3])
{
	
}
//方式2,数组指针接收,不可用char* a[3],由于[]的优先级大于*,
//此时为指针数组, char (*a)[3]才是数组指针
void test2(char (*a)[3])
{
	
}
  • 判断输赢时,可以直接返回棋子字符,减少判断代码;
  • 定义函数时可以采用另一个.c文件用以保存函数,达到封装效果;
  • 在函数调用行列时,最好利用形参采用局部变量,而非使用全局变量; 例如,本文中利用#define将行列分别定义为ROW,COL,但在函数中依旧采用传参的方式,因为函数内部若使用了外部定义的全局变量,便导致离开此全局变量后函数便不可用,从而使得函数的可移植性降低。

四、main函数以及游戏函数

//游戏函数
void game()
{
	char ret = 0;//用以判断输赢
	//棋盘
	char board[ROW][COL] = { 0 };
	//初始化棋盘 
	Initboard(board, ROW, COL);
	//打印棋盘
	Displayboard(board, ROW, COL);
	while (1)
	{
		
		//玩家下棋
		player_move(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		computer_move(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("你赢了\n");
	else if (ret == '#')
		printf("你输了\n");
	else
		printf("平局\n");
}

//main函数
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}