【C语言游戏】井字棋游戏(电脑下棋算法优化)

一、项目介绍

1. 项目功能

        1. 玩家电脑轮流先手

        2. 优化了电脑下棋的算法,实现智能落子

        3. 优化游戏界面,提高游戏体验

二、设计思路

【C语言游戏】井字棋游戏(电脑下棋算法优化)_第1张图片

三、代码实现

        game.h文件:内容包括文件包含,宏定义,全局数据类型的声明,外部链接函数的声明

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

#define MENUBLANK "\t\t\t    "
#define BOARDBLANK "\t\t\t"

enum state{
	DRAW = 1,
	WIN,
	LOSE,
	CONTINUE
};
//1. iswin函数的返回值与judgment中相应游戏状态的下标设置相同,方便使用
//2. 枚举类型state,为代表游戏状态的数字定义了名称,方便理解代码。

void ShowBoard(const char board[3][3], const int score, const char* judgment);
void PlayerMove(char board[3][3]);
enum state IsWin(const char board[3][3]);
void ComputerMove(char board[3][3]);

1. main函数

        处理玩家选项,决定是否开始游戏或是退出程序。

int main(){
	enum option input = 0;
	do{
		//2.打印菜单
		Menu();
		//3.处理用户选项
		fflush(stdin);//清除缓冲区中残留的非法输入***
		scanf("%d", &input);
		switch (input)
		{
		case PLAY:
			//3.玩游戏:控制游戏流程
			PlayGame();
			system("pause");
			break;
		case EXIT:
			printf("退出游戏!\n");
			system("pause");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			system("pause");
			break;
		}
	} while (input);
	
	return 0;
}

2. Menu函数

        打印菜单以供玩家选择

void Menu(){

	system("cls");
	printf("\n\n\n\n\n\n");
	printf("\t\t\t\tTic Tac Toe");
	printf("\n\n\n");
	printf(MENUBLANK"****************************\n");
	printf(MENUBLANK"           1.PLAY           \n");
	printf(MENUBLANK"****************************\n");
	printf(MENUBLANK"           0.EXIT           \n");
	printf(MENUBLANK"****************************\n");
	//MENUBLANK替换为空白字符使菜单显示在窗口中央
	printf("\n\n\n");

}

3. PlayGame函数

        通过调用游戏具体实现的函数,控制游戏的整个流程,是设计思路的直接体现

void PlayGame(){	

	char board[3][3];//棋盘:0代表空,#代表玩家,*代表电脑
	char* judgment[5] = { "Game in Progress",
						"It's a draw",
						"You Win",
						"You Lose",
						"New game starting..."};//游戏状态
	int jud = 0;//游戏状态标记
	int score = 0;//游戏得分
	enum state ret = 0;//输赢结果
	int op = 1;//人机轮换先手标记
	while (1)
	{
		//初始化棋盘和状态标记
		memset(board, 0, 3 * 3);
		jud = 0;
		while (1)
		{
			//*打印棋盘
			ShowBoard(board, score, judgment[jud]);
			//人机轮换先手下棋
			if (op==1)
			{ 
				PlayerMove(board);//玩家下
			}
			else
			{
				ComputerMove(board);//电脑下
			}
			//*判断输赢
			if ((ret = IsWin(board)) != CONTINUE)
				break;
			//*打印棋盘
			ShowBoard(board, score, judgment[jud]);
			if (op == -1)
			{
				PlayerMove(board);
			}
			else
			{
				ComputerMove(board);
			}
			//*判断输赢
			if ((ret = IsWin(board)) != CONTINUE)
				break;
			//*打印棋盘
			ShowBoard(board, score, judgment[jud]);
		}
		switch (ret)
		{
		case DRAW:
			jud = DRAW;
			score += 50;
			break;
		case WIN:
			jud = WIN;
			score += 100;
			break;
		case LOSE:
			jud = LOSE;
			score -= 100;
			break;
			
		}
		ShowBoard(board, score, judgment[jud]);
		Sleep(2000);
		jud = 4;
		ShowBoard(board, score, judgment[jud]);
		Sleep(2000);
		op *= -1;//交换先后手
	}
	
}

4. ShowBoard函数

        负责打印棋盘,当前得分和游戏状态(赢或输等)

void ShowBoard(const char board[3][3], const int score, const char* judgment){

	//打印内容:棋盘,分数,游戏状态

	system("cls");
	printf("\n\n\n\n");
	printf("\t\t\t\tTic Tac Toe");
	int i;

	printf("\n\n\n\n\n");
	for (i = 0; i < 3; i++)
	{
		printf(BOARDBLANK);
		
		printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);

		//*打印游戏状态
		if (i == 0){
			printf("\t\t");
			printf(judgment);
		}
		
		//*打印分数
		if (i == 1){
			printf("\t\t");
			printf("Score: %d", score);
		}

		printf("\n");
		if (i<2)
			printf(BOARDBLANK"---|---|---\n");

	}

	printf("\n\n\n");

}

5. PlayerMove函数

        负责玩家下棋的具体实现(对应设计思路图中“玩家下棋”)

void PlayerMove(char board[3][3]){
	int x = 0;
	int y = 0;
	printf("玩家下:\n");
	while (1)
	{
		//*输入坐标
		printf("请输入坐标:");
		fflush(stdin);
		scanf("%d %d", &x, &y);
		//*检查坐标: 
		if (x >= 1 && x <= 3 && y >= 1 && y <= 3)//1.在不在范围
		{
			if (board[x - 1][y - 1] == 0)//2.棋位是否为空
			{
				//*落子
				board[x - 1][y - 1] = '#';
				break;
			}
			else
			{
				printf("棋位已占!\n");
			}
		}
		else
		{
			printf("非法坐标!\n");
		}

	}
}

6. IsWin函数

        判断输赢情况

enum state IsWin(const char board[3][3]){

	int i,j; 
	char ch;
	//*判断是否平局
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (board[i][j] == 0)
				break;
		}
		if (board[i][j] == 0)
			break;
	}
	if (i == 3){
		return DRAW;
	}
	//*判断行
	for ( i = 0; i < 3; i++)
	{
		ch = board[i][0];
		for ( j = 1; j < 3; j++)
		{
			if (ch != board[i][j])
				break;
		}
		if (j == 3 && ch != 0){
			return ch=='#'? WIN : LOSE;
		}
	}

	//*判断列
	for (i = 0; i < 3; i++)
	{
		ch = board[0][i];
		for (j = 1; j < 3; j++)
		{
			if (ch != board[j][i])
				break;
		}
		if (j == 3 && ch != 0){
			return ch == '#' ? WIN : LOSE;
		}
	}

	//*判断右下
	ch = board[0][0];
	for ( i = 1; i < 3; i++)
	{
		if (ch != board[i][i])
			break;
	}
	if (i == 3 && ch != 0){
		return ch == '#' ? WIN : LOSE;
	}

	//*判断左下
	ch = board[0][2];
	for (i = 1; i < 3; i++)
	{
		if (ch != board[i][2-i])
			break;
	}
	if (i == 3 && ch != 0){
		return ch == '#' ? WIN : LOSE;
	}

	//*游戏继续
	return CONTINUE;
	
}

7. ComputerMove函数

        负责电脑下棋的具体实现(对应设计思路图中“电脑下棋”)

void ComputerMove(char board[3][3]){

	printf("电脑下:\n");
	int rank[3][3] = {7,7,7,7,7,7,7,7,7};
	int i, j;

	//*为每个空位评定等级
	for ( i = 0; i < 3; i++)
	{
		for ( j = 0; j < 3; j++)
		{
			if (board[i][j] == 0)
			{
				rank[i][j] = ChackBoard(board,i,j);
			}
		}
	}

	//*找出最高等级落子
	int top = 7;
	int tpx = 0;
	int tpy = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (rank[i][j] < top){
				top = rank[i][j];
				tpx = i;
				tpy = j;
			}
		}

	}
	Sleep(1000);
	board[tpx][tpy] = '*';

}

8. ChackBoard函数

        根据等级评定规则为给定的棋位评定优先级

int ChackBoard(const char board[3][3], const int x, const int y){
	//评定等级:
	//1.追三 2.堵二 3.对角 4.边角 5.中心 6.普通 7.棋位已占

	int ret = 6;
	char line[3] = { 0 };
	int i = 0;
	int tmp = 0;

	//*中心
	if (x == 1 && y == 1)
	{
		ret = 5;
	}

	//*边角
	if ((x == 2 || x == 0) && (y == 2 || y == 0))
	{
		ret = 4;
	}

	//*对角
	if (board[2 - x][2 - y] == '*')
	{
		ret = 3;
	}

	//*行
	for ( i = 0; i < 3; i++)
	{
		line[i] = board[x][i];
	}
	tmp=ChackLine(line);
	ret = MIN(ret, tmp);

	//*列
	for (i = 0; i < 3; i++)
	{
		line[i] = board[i][y];
	}
	tmp = ChackLine(line);
	ret = MIN(ret, tmp);

	//*右下
	if (x == y)
	{
		for (i = 0; i < 3; i++)
		{
			line[i] = board[i][i];
		}
		tmp = ChackLine(line);
		ret = MIN(ret, tmp);
	}

	//*左下
	if (x + y == 2)
	{
		for (i = 0; i < 3; i++)
		{
			line[i] = board[i][2-i];
		}
		tmp = ChackLine(line);
		ret = MIN(ret, tmp);
	}

	return ret;
}

9. ChackLine函数

        检查给定的棋位在行或列或对角线上的落子情况

int ChackLine(const char line[3]){
	int i = 0;
	int count = 0;
	for (i = 0; i < 3; i++)
	{
		if (line[i] == '*')
		{
			count++;
		}
		else if (line[i] == '#')
		{
			count--;
		}
	}

	//*追三
	if (count == 2)
	{
		return 1;
	}

	//*堵二
	else if (count == -2)
	{
		return 2;
	}

	//*普通
	else
	{
		return 6;
	}
}

四、重难点讲解

1. PlayGame函数

                1. 每局游戏开始前都需要清空棋盘,并将游戏状态标记设置为0。(初始化)

                2. op:人机轮换先手标记,当op==1时玩家先手,当op==-1是电脑先手,每局游戏结束后op*=-1实现每局轮换。

        一局游戏结束后评定分数,打印棋盘:

2. ComputerMove函数

         1. 等级评定规则(7级等级最低,1级等级最高。选择等级最高的棋位下棋):

                7级:已占棋位;        6级:一般棋位;        5级:中心棋位(2 2);        4级:四个脚上的棋位(1 1或3 1);

                3级:位于角落且对角有自己的棋子;           2级:对手已经在一条直线上已经下了两个棋子;      

                1级:自己已经在一条直线上已经下了两个棋子;

        2. 将rank中所有等级初始化为7级,且只有未占的棋位才能评定等级,就成功将已占棋位筛除在外。

2. ChackBoard函数

                这里只解释1,2级的评定方法:

【C语言游戏】井字棋游戏(电脑下棋算法优化)_第2张图片

                1. 评定方法:先将棋位所在的一整行或一整列或整条对角线收集到line数组中。

                                     再交给ChackLine函数评定1级或2级。结果当然应该取最高等级。

【C语言游戏】井字棋游戏(电脑下棋算法优化)_第3张图片

                2. 右下对角线上的棋位横纵坐标相同,如果x==y表示存在右下对角线。

                3. 左下对角线上的棋位横纵坐标相加等于2,如果x+y==2表示存在左下对角线。

五、实现效果

 经过简单的优化,电脑确实变得不好对付了:

【C语言游戏】井字棋游戏(电脑下棋算法优化)_第4张图片

                 说实话,平局容易,胜局难。我也是尝试了很多次才找到了几种获胜的办法,你也可以下载来试一试。

六、分享交流

        最后将完整源码分享给大家,希望大家能与我在交流中共同学习,共同进步:
https://gitee.com/zty857016148/C_OS_Project/tree/master/TicTacToehttps://gitee.com/zty857016148/C_OS_Project/tree/master/TicTacToe

        如果大家还有什么问题欢迎提问,我抽空一定回答!

        若是各位大佬发现了代码中的错误或是遗漏之处还请海涵,最好在评论区交流助我一臂之力!

【C语言游戏】井字棋游戏(电脑下棋算法优化)_第5张图片

 下一篇:【初级C语言】详解扫雷游戏(含难度选择,雷位标记,递归展开等功能)https://blog.csdn.net/zty857016148/article/details/126754920

                

        

你可能感兴趣的:(c++,c语言)