C语言(数组二)三子棋

​​​​​​​希望文章能对你有所帮助,有不足的地方请在评论区留言指正,一起交流学习!

目录

1.游戏介绍

2.设计思路

3.程序的实现

3.1主函数编写

3.2 test()函数编写

3.3game()函数编写

3.3.1 test()函数整体逻辑

3.3.2  ​​​​​​​init_board()初始化棋盘

3.3.3 print_board( )初始化棋盘

3.3.4 player_mover( ) 玩家下棋

3.3.5 computer_move( )电脑输入

3.3.6 is_win( )判断输赢编写


1.游戏介绍

 规则:游戏双方对战,双方依次在9宫格棋盘上摆放棋子,分为'X'和'O'两种。

1.率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了。

2.棋盘填满的情况下视为平局。

代码存放处

这个是我编写的程序,如有错误请指正【免费】C语言三子棋(密码:1234)资源-CSDN文库

2.设计思路

        我们采用C语言,由于程序较为复杂,所以我们采用模块化来写,将整个程序分为三个文件

1. test.c为测试程序,主要是测试的逻辑,就是子程序执行的顺序

2.game.c 主要编写游戏运行的所有子函数程序

3.game.h 对库函数以及game.c中的函数进行声明。

如果不懂VS软件中项目是如何运行并在组装在一起,看一看看C语言笔记(函数篇一)-CSDN博客这个中函数的声明。

        分为两个模块

 test.c为测试模块 

 game.c和game.h是游戏模块。

3.程序的实现

一、设计要求

1.有开始菜单,并且有是否进入游戏的选择,输入1就进入,0就退出。

2.对手是电脑。

3.可以判断输赢,并输出。

3.1主函数编写

        首先我们在测试程序(test.c)中完成main()函数,要求:主函数中的程序要尽量的少,因此我们会将程序的测试放在了test()的子函数中,当然这个子函数也在test.c文件中

int main()
{
	test();
	return 0;
}
3.2 test()函数编写

        test函数中式的主要作用

        调用游戏菜单函数和判断是否进入游戏函数,menu()是游戏菜单的打印

     程序的逻辑:

        1.switch语句分情况 在输入1情况下开始游戏,并执行game()函数中的程序

        2.要求在输入数字的时候是可以多次输入的,因此我们在采用的do......while的循环结构,这样就可以输入多次,将input输入的数字为判断条件,正好符合 数字 0退出游戏的设定。

下面这段代码是根据时间戳随机生成随机数字的起点,和rand()函数配合使用就可以生成一个随机数了。

srand((unsigned int)time(NULL));
void test()
{
	srand((unsigned int)time(NULL));
	menu();
	int input = 0;                          
	do
	{
		printf("请选择\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();                     //输入1的情况下进入game子函数中
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,重新输入\n");
			break;
		}
		
	}
	while (input);                      //将input作为判断条件符合程序要运行的方式
}

menu()函数,作用仅仅就是在屏幕上打印菜单而已。

void menu()
{
	printf("************************\n");
	printf("******** 1.play ********\n");
	printf("******** 2.exit ********\n");
	printf("************************\n");
}
3.3game()函数编写

 game函数的作用

        编写game.c源文件中的子程序执行的逻辑,如何实现三子棋游戏。

3.3.1 test()函数整体逻辑

所有子函数必须再头文件game.h中声明,声明的格式就是

//初始化数组,将数组所有元素改为 空格
void init_board(char board[ROW][COL], int row,int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家输入
void player_mover(char board[ROW][COL], int row, int col);
//电脑输入
void computer_move(char board[ROW][COL], int row, int col);

//判断输赢
char is_win(char board[ROW][COL], int row, int col);

程序的逻辑

  (1)定义的ROW ,COL

        我们在game.h的文件中定义的ROW ,COL,因为要在两个源文件中使用;

(2)创建一个三行三列的数组

  (3)   初始化棋盘,就是打出棋盘的最初模样,将数组的所有元素改成符号空格 

  (4)  打印整个棋盘 ,将整个棋盘打印出来,包括数组的元素

(5)  玩家输入函数,在玩家输入坐标后,再次打印整个棋盘

(6) 打印整个棋盘

(7)输赢的判断函数的调用

(8)电脑输入 ,电脑是随机输入的,这个时候我们就用到那个随机生成的数。

(9)打印整个棋盘

(10)   判断输赢函数的调用

(11)   由于我们要多次的输入和打印棋盘,因此我们采用while(1)的循环,当符合某一条件的情况下跳出棋盘。

(12)   最后就是输出玩家胜利和电脑胜利的if语句。

#define ROW 3
#define COL 3

上面game.h的文件中定义的ROW ,COL,这种是常量,要是修改的话,直接将3 改为10 等等

void game()
{
	char board[ROW][COL];
	//初始化数组
	init_board(board, ROW, COL);
	//打印棋盘
	print_board(board, ROW, COL);
	char ret ;
	while (1)
	{
		//玩家下棋
		player_mover(board, ROW, COL);
		//打印整个棋盘
		print_board(board, ROW, COL);
		//判断输赢
	    ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		//电脑下棋
		computer_move(board, ROW, COL);
		//打印整个棋盘
		print_board(board, ROW, COL);
		//判断输赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
			if (ret == '*')
			{
				printf("玩家胜利\n");
			}
			if (ret == '#')
			{
				printf("电脑胜利\n");
			}
			if (ret == 'Q')
			{
				printf("平局\n");
			}
}
//接下里的程序是要有返回值的,
//定位玩家赢返回'*'
//电脑赢  返回'#'
//平局 返回'Q'棋盘已经满
//继续游戏  返回'C'
3.3.2  ​​​​​​​init_board()初始化棋盘

使用两次for循环直接将board[ ][ ]中的所有元素改为 符号空格

void init_board(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] = ' ';  //空格是字符 
		}
	}
}
3.3.3 print_board( )初始化棋盘

下面的代码使用了一个for循环,打印三次,一次的同时打印数组元素,在打印---分割线(可以优化的)

void print_board(char board[ROW][COL], int row, int col)
{

	int i = 0;
	for (i = 0; i < col; i++)
	{
		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		if (i < row - 1)
		{
			printf("---|---|---\n");
		}
	}
	printf("\n");
}

打印出来的结果是

3.3.4 player_mover( ) 玩家下棋

逻辑:

我在这里实现采用了 while和break组合的循环,goto语句,站在玩家的立场上

1.首先玩家输入变量,确定输入那个位置

2.使用while(1)语句,

3.在语句中使用if else语句判断输入的条件,要进行什么修改,行和列减一是必然的

4. goto语句,在这里输入错误或者输入位置已经使用过会重新进入循环

void player_mover(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	//站在玩家的立场上是第一行第一列
	flag:
		while (1)
		{
			printf("请输入坐标\n");
			scanf("%d %d", &x, &y);
			if (x >= 1 && y >= 1 && x <= row && y <= col)
			{
				if (board[x-1][y-1] == ' ')
				{
					board[x-1][y-1] = '*';
					break;
				}
				else
				{
					printf("坐标已经被占用,请重新输入\n");
					goto flag;
				}
			}
			else
			{
				printf("无效坐标,重新输入\n");
				goto flag;
			}
		}
}
3.3.5 computer_move( )电脑输入

逻辑

     1.  和3.3.4一样的,rand()和srand函数配合生成随机数组,对于3取模以后,只能产生小于3的数字

     2. 使用while(1)和break实现错误输入再输入的情况,要配合goto语句

void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	
	flag1:
		while (1)
		{
			int x = rand() % row;
			int y = rand() % col;
			printf("%d %d\n", x,y);

			if (board[x][y] == ' ')
			{
				board[x][y] = '#';
			break;
			}
			else
			{
				goto flag1;
			}
		}
}
3.3.6 is_win( )判断输赢编写

  首先是有两个函数构成的is_full仅仅对于is_win有作用,因此就将他放在了game.c文件中。

逻辑

1.判断行是否相等且不等于空格

2.判断列是否相等且不等于空格

3.判断对角线是否相等且不等于空格

4.判断棋盘是否填满,并且有返回值

int is_full(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 is_win(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][2]!=' ')
		   return board[i][0];
	}
	//判断三列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i]!= ' ')
			return board[0][0];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&& board[2][2]!= ' ')
	{
		return board[0][0];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0]&& board[2][0]!= ' ')
	{
	  return board[1][1];
	}
	int ret = is_full(board, row, col);
	if (ret == 0)
	{
		return 'C';
	}
	else
		return 'Q';
	
}	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值