(C语言)三子棋(井字棋)娱乐教程

(C语言)三子棋(井字棋)娱乐教程_第1张图片

司机镇楼!!!!!!

口号:好好学习,努力养家

备注:看了正式版看不懂可以转接娱乐版

注意:这是个对于初学者来说的大型工程,分成了三部分来写:test.c,game.c,game.h

正式版:

兄台,也不知道你同不同意,我就放个链接!谢谢!

(18条消息) 三子棋代码实现思路解析与易错点纠正_xbhinsterest11的博客-CSDN博客

这位兄台的就很不错,正式版就用这位大神的吧

娱乐版:

test.c(游戏的测试逻辑)

#define _CRT_SECURE_NO_WARNINGS 1
//游戏的测试逻辑,game.h和game.c才是游戏的主题,这边你可以认为就是个“主函数”
//game为“副函数”船长离不开大副
//船长只是一个主心骨负责统领,大副才是真正干实事的大佬
//#include证明我存在过,只是后来觉得重复,你不要了,哎!像极了备胎
#include"game.h"//这是自己写的头文件
void menu()
{
	printf("**************\n");
	printf("****1.play****\n");
	printf("****0.exit****\n");
	printf("**************\n");
}
void game()
{
	//三子棋,要先有棋盘
	//要有电脑和人相互下棋的操作
	//任何下棋后下棋的位置要保存起来
	//输入的棋子是输入的字符,而棋盘输入是3*3的,我们输入字符输入时是几行几列
	//所以相当于是一个字符类型的二维数组
	//******************************************
	//以上为思考,下面是定义
	//数据存储到一个字符的二维数组中,玩家下棋是“*”电脑下棋是“#”
	//这里先构建棋盘,再下棋
	char board[ROW][COL] = { 0 };//数组的内容应该是全部空格
	InitBoard(board, ROW, COL);//初始化棋盘
	//打印棋盘确定是不是初始化正确,不过说实话,你一步步来咋可能错吗?
	DisplayBoard(board, ROW, COL);
	//注意哦,不要一看到打印就行到printf,这也打印不出来呀!
	char ret = 0;
	while (1)
	{
		player_move(board,ROW,COL);//玩家下棋一样是在几行几列下棋
		//是在这个二维数组里面下棋
		DisplayBoard(board, ROW, COL);//打印棋盘
		ret = is_win(board, ROW, COL);//马上来一次判断是平局还是继续
		if (ret != 'C')//-C是继续,-Q是平局
		{
			break;//意思就是如果返回值不等于继续-'C'就跳出循环
		//就是说只要不是继续下棋肯定就是出结果了,不要呆在这个while循环里了
		}
		computer_move(board, ROW, COL);//电脑下棋
		DisplayBoard(board, ROW, COL);//打印棋盘
		ret = is_win(board, ROW, COL);//注意一定要有,不然你会很困惑,建议尝试去点一下
		//补充
		if (ret != 'C')
		{
			break;
		}
		//到了这里,框架结束,要开始判断输赢了
	}
	if(ret == '*')
	{
		printf("玩家胜利!\n");
	}
	else if(ret == '#')
	{
		printf("电脑赢!\n");
	}
	else
	{
		printf("平局!\n");
	}
}
void test()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋\n");
			game();//真正的三子棋游戏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
		}
	} while (input);//非零为真,运行选择程序,为零则跳出结束游戏
	//这就是用do while 的原因,while是零也已经进行了一次do循环
}

int main()
{
	srand((unsigned)time(NULL));
	test();
	return 0;
}

game.h(游戏的实现函数声明)

//建议最开始来这么一句,就好像做ppt呀开题要告诉下面的老师,你要讲啥
//游戏的实现函数的声明
#define _CRT_SECURE_NO_WARNINGS 1
#include//这个东东写在这纯属因为啊printf动不动来个未定义
//反正两个c文件都要用,干脆写在都需要调用的game.h里面
#include
#include
//在头文件里宏定义行和列
//减少不必要的操作且直观清楚
//即如果是10*10的十字棋,只需要在宏定义修改即可
//说实话,你要是觉得也麻烦不想写英文也不用这样
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);//注意区分大小写
//注意:这里的row和ROW不是一个东西
//InitBoard(board,ROW,COL);//初始化棋盘操作
//这句话括号内的参数ROW和COL是int整形,用row表示,这样清楚且不冲突
//这里只是函数声明,函数实现在game.c里进行
void DisplayBoard(char board[ROW][COL], int row, int col);
//啰嗦一句,数组传参,用char a[][]用来接收a[][],或者用指针
//详细说明一下
void player_move(char board[ROW][COL],int row,int col);
//电脑下棋,在ROW*COL的棋盘的(row,col)下棋
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢的代码
//玩家赢-'*'
//电脑赢-'#'
//平局-'Q'
//继续-'C'
char is_win(char board[ROW][COL], int row, int col);

game.c(游戏的实现逻辑)

#define _CRT_SECURE_NO_WARNINGS 1
//游戏的实现逻辑
#include"game.h"
//留一行给未来的老婆,(原谅我复习的时候也不记得这个啥意思了)
void InitBoard(char board[ROW][COL], int row, int col)
{//在board(3*3的棋盘)中下棋,row和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++)
//	{
//		printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
//		if (i < row - 1)
//		{
//      //即代表第三行不要打印下面这东东
//			printf("---|---|---\n");
//		}
//		//注意,可以试着打印一下
//		//发现第三行打印的这个———没有必要
//		//哈哈哈,你终于打完了棋盘!congratuation!!!
//		//结果你发现这种方叫做傻瓜打印法,只适用于三子棋
//		//注释掉
//	}
//
//}
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("|");
			}//打个比方,3行3列,i=0,j=0,打印第一列,0<3-1,打印|
             //j=1,打印第二列,1<3-1,打印|
             //j=2,打印第三列,2=3-1,不打印
		}
		printf("\n");//把他们分开,换行,打印完第一行打印第二行
		//下面打印---|---|---
		//分割行
		//把你放在身边怕忘记
		//井
		//   |   |    (数组第一行)
		//---|---|--- (这就是分割线)
		//   |   |   (数组第二行)
		//---|---|---  (分割线)
		//   |   |   (数组第三行)
        //所以下一步看怎么打印分割线
		if (i < row - 1)//同理第三行不要了
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}//别忘记!

}

void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋:\n");//井字棋,玩家只能下在三行三列这个范围内
	int x = 0;
	int y = 0;
	while (1)
	{
		scanf("%d %d", &x, &y);//想办法加个条件让他只能3*3
		if (x >= 1 && x <= row && y >= 1 && y <= row)
		{
			//下过棋的地方不能再下棋
			//我们看到的第一行第一列,电脑看到的是第零行零列
			//所以x-1,y-1
			if (board[x - 1][y - 1] == ' ')//注意此处是单引号
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用,请重新输入!\n");
			}
			//留心细节单双引号,单引号在字符常量时使用,表示单个字符。
			//char c = 'aA'; // 编译出错,单引号只能是一个字符
			//char c = ''; // 单引号中间没有任何字符时,编译出错
			//双引号在表示字符串常量时使用,可以表示0到多个字符组成的字符串。
			//char s1[] = "a";
			//char s2[] = "a1A";
			//char s3[] = ""; // 双引号中间可以没有任何字符,表示空字符串
		}
		else
		{
			printf("坐标非法!请重新输入!\n");
		}
	}
}


//这样电脑下棋太蠢,待优化
void computer_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:\n");
	//电脑随机下,更难的不会,初学者望谅解
	while(1)
	{
		x = rand() % ROW;//这样余数就只可能是0,1,2三种
		y = rand() % COL;
		if (board[x][y] == ' ')//这里没有减一是因为前面xy已经限制好了
		{
			board[x][y] = '#';
			break;//一定要,不然电脑就会一直下棋
		}//不需要else了,不解释
	}
}

//判断结果
int is_full(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;//位置不要放错
}

//下面也写死了,需要下多行棋时,需要进行修改
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][1] != ' ')
		{
			return board[i][1];
		}
	}
	//三列的判断
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[1][i];
		}
	}
	//对角线的情况判断
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&&board[1][1]!=' ')
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	//判断平局
	//即有空格说明没有平局
	if (1 == is_full(board, row, col))
	//注意这是在函数char is_win(char board[ROW][COL], int row, int col)里
	{
		return 'Q';
	}
	//继续
	return 'C';
}

你可能感兴趣的:(C语言,c语言,开发语言)