智能三子棋——保姆级教学。

目录

序言:

一.整体思路

 二.加载逻辑

 三.棋盘布置

 四.下棋

 五.智能化

最后:


序言:

想必三子棋大家都玩过吧,回想起小时候在地上用石头画上线,有的用石子儿,有的用树枝,下三子棋,都能玩一天。现在回想起来都是满满的回忆呀。今天带着大家来用C语言,来实现模拟实现一下三子棋游戏,来帮大家找一找童年的记忆。下面进入正题:

一.整体思路

我们三子棋主要实现的原理是,利用字符打印出一个棋盘,用二维数组存储我们下的棋子。先给大家看看什么样的。

 

大致就是这个样子。

 然后一步一步下棋,每下一步,我们就把棋盘打印一边。

 二.加载逻辑

首先每次游戏开始我们都需要一个菜单:

 菜单代码:

void menu()
{
	printf("*****************************************\n");
	printf("************1.play    0.exit*************\n");
	printf("*****************************************\n");
}

游戏的加载逻辑,我们希望可以选择游戏开始或者退出,也不是玩完一局就没有了,而是玩完一局以后还可以继续选择玩或者不玩,只有我们选组退出时,程序才会结束。

代码:

void game()
{
    printf("三子棋\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入选项:>\n");
		scanf("%d", &input);
		printf("\n");
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入:>\n");
			break;
		}
	} while (input);

	return 0;
}

运行效果:

设置好游戏的加载逻辑以后,后面的游戏内容就全部在game()函数里面完成。并且我们为了是程序模块化,我们将主函数放到main.c文件里面,函数声明,头文件,宏等,我们就放在game.h文件里面,函数的具体实现我们统统放在,game.c文件里面。这样我们的整体程序就会非常有序,可读性提高。

 三.棋盘布置

我们使用宏常量来,规定棋盘的大小 :

#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define LIN 3
#include<stdio.h>

void menu();

void game();
void game()
{
	//创建二维数组
	char chess[ROW][LIN] = { 0 };
	//初始化用来装棋子的二维数组
	init_board(chess,ROW,LIN);
	//打印棋盘
	print_board(chess,ROW,LIN);
}
void init_board(char chess[ROW][LIN], int row, int lin)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < lin; j++)
		{
			//二维数组全部初始化位空格
			chess[i][j] = ' ';
		}
	}
}
void print_board(char chess[ROW][LIN],int row,int lin)
{
	for (int i = 0; i <  row; i++)
	{
		for (int j = 0; j < lin; j++)
		{
			//空格 + 棋子 + 空格 + | ,为一组,一共
			//需要 lin 组,但是最后一组不需要 |
			printf(" %c ",chess[i][j]);
			//控制最后一个 | 不打印
			if (j < row - 1)
			{
				printf("|");
			}
		}
		//换行
		printf("\n");

		//   |   |   
		//---|---|---
		//为一组,一共需要 row 组,但是最后一组,不需要 ---|---|---
		if (i < lin - 1)
		{
			for (int j = 0; j < row; j++)
			{
				// ---| 为一组,一共 row 组,最后一组不需要打印 |
				printf("---");
				if (j < row - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

运行效果:

 四.下棋

下棋的主要逻辑实现就是,封装两个函数player_chess()用来表示玩家下棋和电脑下棋computer_board(),玩家输入坐标,并将玩家代表的棋子存入棋盘的二维数组里面,电脑下棋先给他设置成随机下棋,然后每次下完一颗棋子我们就打印一下整个棋盘。我们需要一直下棋,每下一颗棋子都有可能出现胜利的一方,封装一个函数is_win()用来判断是否又人赢了,所以需要每下一颗棋子就需要判断一下是否又赢得玩家,如果又赢得玩家就直接is_win直接返回胜利者的棋子,如果没有人赢就返回‘C’代表继续,如果棋盘已经满了,就返回‘Q’代表平局。

void game()
{
	char set;
    //随机数生成器
	srand((unsigned int)time(NULL));
	//创建二维数组
	char chess[ROW][LIN] = { 0 };
	//初始化用来装棋子的二维数组
	init_board(chess,ROW,LIN);
	//打印棋盘
	print_board(chess,ROW,LIN);
	while (1)//一直循环,直到结果出现输赢,或者平局
	{
        //玩家下棋
		player_chess(chess, ROW, LIN );
        //打印棋盘
		print_board(chess, ROW, LIN);
        //判断结果
		set=is_win(chess,ROW,LIN);
		if ('C' != set)
		{
			break;
		}
        //电脑下棋
		computer_board(chess, ROW, LIN);
        //打印棋盘
		print_board(chess, ROW, LIN);
        //判断结果
		set = is_win(chess, ROW, LIN);
		if ('C' != set)
		{
			break;
		}
	}
    //如果返回的是玩家代表的棋子,
	if (set == '*')
	{
		printf("恭喜你,你赢了!!\n");
	}
    //如果返回的是电脑代表的棋子
	else if ('#' == set)
	{
		printf("电脑赢了!!\n");
	}
    //如果是平局
	else if ('Q' == set)
	{
		printf("平局\n");
	}
}

void player_chess(char chess[ROW][LIN], int row, int lin)
{
    //计数玩家棋子数量
	count_board++;
    //坐标
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入棋子坐标:>");
		scanf("%d %d", &x, &y);
        //判断坐标合理性,是否在棋盘内
		if (x >= 1 && x <= row && y >= 1 && y <= lin)
		{
            //坐标位置是否为空
			if (chess[x-1][y-1] == ' ')
			{
				chess[x-1][y-1] = '*';
				break;
			}
			else
			{
				printf("该位置已有棋子\n");
			}
		}
		else
		{
			printf("棋子坐标错误,请重新输入\n");
		}
	}
}
void computer_board(char chess[ROW][LIN], int row, int lin)
{
	while (1)//直到找好位置循环结束。
	{
        //随机数生成,0~2
		int x = rand()%row;
		int y = rand()%lin;
        //判断是否该位置为空,
		if (chess[x][y] == ' ')
		{
			chess[x][y] = '#';
			break;
		}
		
	}
}

判断是否有玩家赢is_win()

//判断棋盘是否满了
int is_full(char chess[ROW][LIN], int row, int lin)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < lin; j++)
		{
			if (chess[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

char is_win(char chess[ROW][LIN], int row, int lin)
{
    //横着判断是否有三个一样的
	for (int i = 0; i < row; i++)
	{
		if (chess[i][0] == chess[i][1] && 
            chess[i][1] == chess[i][2] &&
            chess[i][0]!=' ')
		{
			return chess[i][0];
		}
	}
    //竖着判断是否有三个一样的
	for (int i = 0; i < lin; i++)
	{
		if (chess[0][i] == chess[1][i] && 
            chess[1][i] == chess[2][i] && 
            chess[0][i] != ' ')
		{
			return chess[0][i];
		}
	}
    //斜着判断是否有三个一样的
	if (chess[0][0] == chess[1][1] && 
        chess[1][1] == chess[2][2] && 
        chess[0][0] != ' ')
	{
		return chess[0][0];
	}
    //斜着判断是否有三个一样的
	if (chess[0][2] == chess[1][1] && 
        chess[1][1] == chess[2][0] && 
        chess[0][2] != ' ')
	{
		return chess[0][2];
	}
    //判断棋盘是否满了
	int tmp = is_full(chess, ROW, LIN);
	if (tmp == 1)
	{
		return 'Q';
	}
	return 'C';
}

这样我们三子棋的主要逻辑就实现了

 五.智能化

 但是大家发现这电脑傻了吧唧的,现在我们就给他智能化,但是智能化的程度取决于设计者。分析那些情况优先的,就像当你电脑还差一颗棋子就可以赢了,这就是最先考虑的情况,其次是当对手还差一颗棋子赢了,还有电脑下一颗可以达成两颗棋子的领先情况,等等还有一些情况小编不好分析,就不多介绍了。

void computer_board(char chess[ROW][LIN], int row, int lin)
{
	
	//差一棋子,优先下(1)
	for (int i = 0; i < row; i++)
	{
		if (chess[i][0] == chess[i][1] && chess[i][0] == '#'&& chess[i][2] == ' ')
		{
			chess[i][2] = '#';
			return;
		}
		if (chess[i][0] == chess[i][2] && chess[i][0] == '#'&& chess[i][1] == ' ')
		{
			chess[i][1] = '#';
			return;
		}
		if (chess[i][1] == chess[i][2] && chess[i][1] == '#'&& chess[i][0] == ' ')
		{
			chess[i][0] = '#';
			return;
		}
	}
	//差一棋子,优先下(2)
	for (int i = 0; i < lin; i++)
	{
		if (chess[0][i] == chess[1][i] && chess[0][i] == '#'&& chess[2][i]==' ')
		{
			chess[2][i] = '#';
			return;
		}
		if (chess[0][i] == chess[2][i] && chess[0][i] == '#'&&chess[1][i] == ' ')
		{
			chess[1][i] = '#';
			return;
		}
		if (chess[1][i] == chess[2][i] && chess[1][i] == '#'&& chess[0][i] == ' ')
		{
			chess[0][i] = '#';
			return;
		}
	}
	//差一棋子,优先下(3)
	if (chess[0][0] == chess[1][1] && chess[0][0] == '#' && chess[2][2] == ' ')
	{
		chess[2][2] = '#';
		return;
	}
	if (chess[0][0] == chess[2][2] && chess[0][0] == '#' && chess[1][1] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[2][2] == chess[1][1] && chess[1][1] == '#' && chess[0][0] == ' ')
	{
		chess[0][0] = '#';
		return;
	}

	//差一棋子,优先下(4)
	if (chess[0][2] == chess[1][1] && chess[0][2] == '#' && chess[2][0] == ' ')
	{
		chess[2][0] = '#';
		return;
	}
	if (chess[0][2] == chess[2][0] && chess[0][2] == '#' && chess[1][1] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[2][0] == chess[1][1] && chess[1][1] == '#' && chess[0][2] == ' ')
	{
		chess[0][2] = '#';
		return;
	}
	//对方差一棋子胜利,优先下(5)
	for (int i = 0; i < row; i++)
	{
		if (chess[i][0] == chess[i][1] && chess[i][0] == '*' && chess[i][2] == ' ')
		{
			chess[i][2] = '#';
			return;
		}
		if (chess[i][0] == chess[i][2] && chess[i][0] == '*' && chess[i][1] == ' ')
		{
			chess[i][1] = '#';
			return;
		}
		if (chess[i][1] == chess[i][2] && chess[i][1] == '*' && chess[i][0] == ' ')
		{
			chess[i][0] = '#';
			return;
		}
	}
	//对方差一棋子胜利,优先下(6)
	for (int i = 0; i < lin; i++)
	{
		if (chess[0][i] == chess[1][i] && chess[0][i] == '*' && chess[2][i] == ' ')
		{
			chess[2][i] = '#';
			return;
		}
		if (chess[0][i] == chess[2][i] && chess[0][i] == '*' && chess[1][i] == ' ')
		{
			chess[1][i] = '#';
			return;
		}
		if (chess[1][i] == chess[2][i] && chess[1][i] == '*' && chess[0][i] == ' ')
		{
			chess[0][i] = '#';
			return;
		}
	}

	//对方差一棋子胜利,优先下(7)
	if (chess[0][0] == chess[1][1] && chess[0][0] == '*' && chess[2][2] == ' ')
	{
		chess[2][2] = '#';
		return;
	}
	if (chess[0][0] == chess[2][2] && chess[0][0] == '*' && chess[1][1] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[2][2] == chess[1][1] && chess[1][1] == '*' && chess[0][0] == ' ')
	{
		chess[0][0] = '#';
		return;
	}

	//对方差一棋子胜利,优先下(8)
	if (chess[0][2] == chess[1][1] && chess[0][2] == '*' && chess[2][0] == ' ')
	{
		chess[2][0] = '#';
		return;
	}
	if (chess[0][2] == chess[2][0] && chess[0][2] == '*' && chess[1][1] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[2][0] == chess[1][1] && chess[1][1] == '*' && chess[0][2] == ' ')
	{
		chess[0][2] = '#';
		return;
	}

	//抢占先机,下完这一棋子,差一步胜利;(1)
	for (int i = 0; i < lin; i++)
	{
		if (chess[0][i] == '#' && chess[1][i] == ' ' && chess[2][i] == ' ')
		{
			chess[1][i] = '#';
			return;
		}
		if (chess[1][i] == '#' && chess[0][i] == ' ' && chess[2][i] == ' ')
		{
			chess[0][i] = '#';
			return;
		}
		if (chess[2][i] == '#' && chess[0][i] == ' ' && chess[1][i] == ' ')
		{
			chess[0][i] = '#';
			return;
		}
	}

	//抢占先机,下完这一棋子,差一步胜利;(2)
	for (int i = 0; i < row; i++)
	{
		if (chess[i][0] == '#' && chess[i][1] == ' ' && chess[i][2] == ' ')
		{
			chess[i][1] = '#';
			return;
		}
		if (chess[i][1] == '#' && chess[i][0] == ' ' && chess[i][2] == ' ')
		{
			chess[i][0] = '#';
			return;
		}
		if (chess[i][2] == '#' && chess[i][0] == ' ' && chess[i][1] == ' ')
		{
			chess[i][0] = '#';
			return;
		}
	}

	//抢占先机,下完这一棋子,差一步胜利;(3)
	if (chess[0][0] == '#' && chess[1][1] == ' ' && chess[2][2] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[0][0] == ' ' && chess[1][1] == '#' && chess[2][2] == ' ')
	{
		chess[2][2] = '#';
		return;
	}
	if (chess[0][0] == ' ' && chess[1][1] == ' ' && chess[2][2] == '#')
	{
		chess[0][0] = '#';
		return;
	}

	//抢占先机,下完这一棋子,差一步胜利;(4)
	if (chess[0][2] == '#' && chess[1][1] == ' ' && chess[2][0] == ' ')
	{
		chess[1][1] = '#';
		return;
	}
	if (chess[0][2] == ' ' && chess[1][1] == '#' && chess[2][0] == ' ')
	{
		chess[0][2] = '#';
		return;
	}
	if (chess[0][2] == ' ' && chess[1][1] == ' ' && chess[2][0] == '#')
	{
		chess[0][2] = '#';
		return;
	}

	//第一步棋子,针对
	if (count_board == 1 && chess[0][0] == '*')
	{
		chess[2][2] = '#';
		return;
	}
	if (count_board == 1 && chess[0][2] == '*')
	{
		chess[2][0] = '#';
		return;
	}
	if (count_board == 1 && chess[2][0] == '*')
	{
		chess[0][2] = '#';
		return;
	}
	if (count_board == 1 && chess[2][2] == '*')
	{
		chess[0][0] = '#';
		return;
	}

	while (1)
	{
		int x = rand()%row;
		int y = rand()%lin;
		if (chess[x][y] == ' ')
		{
			chess[x][y] = '#';
			break;
		}
		
	}
}

 最后展示成果:

 这里我就已经输了,哈哈哈。

最后:

坚守之心就是不为苦难所惧。苦难是成功的磨刀石,是对人的胆识、智慧和毅力的考验。生活的道 路不是一帆风顺的,往往荆棘丛生。不少人就是迈不过这道坎,害怕、退缩、放弃、变向,结果只 能与成功失之交臂。努力成为你最喜欢的那种人,就算不成功,至少你会喜欢这样努力的自己。加油,诸君,山顶见!!!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的代码爱吃辣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值