[完整版]c语言算法三五子棋-三子棋篇/代码/思路总结--新手向

c语言算法三子棋:

开发环境:visual studio

语言:c

1:构思和想法

2:框架代码

3:功能代码

本人只是一名大二学生非科班,技术有限,代码比较乱,希望指正,这也是我第一次写博客,见谅。

1:构思和想法

本人正在学习编程ing,学了点c语言,想实践一下,而且大多数文章代码只有核心功能,没有细节上的功能比如:识别输入是否正确及过滤非正确输入、返回主菜单、电脑算法之类的,于是便想着自行写个完整的程序锻炼一下。这个项目,包含一个比较完整的游戏框架包括:菜单、输入识别与过滤非正确输入、游戏运行、返回菜单、三子棋和五子棋电脑算法等......还请大佬们指正。

2:框架代码

一、框架图:

二、mian.c

本文只有三子棋部分代码完整,五子棋部分还在开发。

#include<stdio.h>
#include "game.h"



void game3()
{
	int board[ROW][COL] = { 0 },count=0,status=2;
	init_board3(board, ROW, COL); 
	display_board3(board, ROW, COL);
	while (1)
	{
		write3(board, ROW, COL);
			display_board3(board, ROW, COL);
			status = win3(board, ROW, COL);
			if (status==1)
			{
				printf("你赢了,恭喜!\n");
				break;
			}
			else if(status == 0)
			{
				printf("你输了,没事,还能再来!\n");
				break;
			}
			if (full3(board, ROW, COL))
			{
				printf("平局!请重新开始游戏!\n");
				break;
			}
	}
	system("cls");
	printf("\n\n");
	start();
}	

void game5()
{
	int board[RO][CO] = { 0 };
	init_board5(board, RO, CO);
	display_board5(board, RO, CO);
	while (1)
	{
		write5(board, RO, CO);
		display_board5(board, RO, CO);
	}
}


int main(void)
{
	start();
}

三、game.h文件的函数

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 3 //宏定义棋盘长宽
#define COL 3
#define RO  5
#define CO  5

//三子棋函数-----------------------------------------------

void game3();

void init_board3(char board[ROW][COL], int row, int col);//初始化棋盘

void write3(char board[ROW][COL], int row, int col);//放置函数

int full3(char board[ROW][COL], int row, int col);//判断棋盘是否满

int defense3(char board[ROW][COL], int row, int col);//进攻函数

int attack3(char board[ROW][COL], int row, int col);//防御函数

int win3(char board[ROW][COL], int row, int col);//判断胜负函数

//共用函数-------------------------------------------------

void delay();//延迟函数

int random(int status);//随机函数

void menu();//菜单展示函数

void choose(int input);//菜单选择函数

void start();//游戏开始函数


//五子棋函数-----------------------------------------------

void game5();

void display_board5(char board[RO][CO], int row, int col);

void init_board5(char board[RO][CO], int row, int col);

void write5(char board[RO][CO], int row, int col);

四、game.c文件的函数

这一部分就是实现游戏功能,单独在下面一部分讲解。

3:功能代码

①输入过滤的实现:

识别:

scanf'正确读取一个对应类型则返回值1,正确读取两个则为2,利用返回值+if识别输入是否正确。

过滤:

用getchar()函数过滤错误输入的字母。

不过滤的话程序会陷入无限循环,这与scanf函数读取机制有关。

具体查阅:

scanf读取机制

//此处代码为片段,仅作解释作用
printf("请输入你的选择----->");
status = scanf_s("%d", &input);
while (status != 1 || input > 3 || input <= 0)//过滤错误输入
{
	getchar();
	printf("输入数据有错误,请重新输入正确范围数字:\n");
	printf("请输入你的选择----->");
	status = scanf_s("%d", &input);
}

②返回主菜单的实现:

利用start()函数

//此处代码为片段,仅作解释作用
void game3()
{
	此处省略100000字的游戏代码
	system("cls");
	printf("\n\n");
	start();
}	

一、菜单函数展示和菜单选择函数

void menu()
{
	printf("      菜单\n");
	printf("----1.三子棋----\n");
	printf("----2.五子棋----\n");
	printf("----3.退出 ----\n");
}

void choose(int input)
{
	switch (input)
	{
	case 1:
		printf("欢迎来到三子棋,祝你游戏愉快!\n\n");
		game3();
		break;
	case 2:
		printf("欢迎来到五子棋,祝你游戏愉快!\n\n");
		game5();
		break;
	case 3:
		printf("欢迎下次光临!\n");
		break;
	}
}

二、随机函数代码

为了适用于三子棋同时也适用于五子棋,因此用函数来产生随机数。

random(3)产生1-3的随机数字

random(5)产生1-5的随机数字

int random(int status)
{
	int count=0;
	srand((unsigned int)time(0));
	if (status == 3)
	{
		while (count==0)
		{
			count = rand() % 4;
		}

		return count;
	}
	else if (status == 5)
	{
		while (count==0)
		{
			count = rand() % 6;
		}

		return count;
	}

}

三、延迟函数

i=x即为x秒延迟

用于增强游戏体验

void delay()
{
	int i = 5;
	while (i >= 0)
	{
		system("cls");
		printf("%d\n",i);
		Sleep(1000);
		i--;
	}
}

四、开始游戏函数

方便游戏的开始

集合了菜单展示、选择和输入过滤功能。

方便游戏结束后,利用start()函数直接跳转到菜单,进行下一局游戏的开始。

void start()//开始游戏
{
	int input = 0, status = 0;
	menu();
	printf("请输入你的选择----->");
	status = scanf_s("%d", &input);
	while (status != 1 || input > 3 || input <= 0)//过滤错误输入
	{
		getchar();
		printf("输入数据有错误,请重新输入正确范围数字:\n");
		printf("请输入你的选择----->");
		status = scanf_s("%d", &input);
	}
	choose(input);

}

五、三子棋游戏函数

1:初始化棋盘函数

用数组存储

void init_board3( char board[ROW][COL],int row, int col)//初始化函数
{
	int i=0,j=0;
	for (i=0 ; i <row ;i++)
	{
		for (j=0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

2:可自适应棋盘打印函数

更改game.h中宏定义即可打印不同大小棋盘

将棋盘拆分为以下这几个元素:

“|” 和“---|”和“---”

然后判断什么时候打印哪个即可

判断的时候只能使用函数输入的row、col作为条件判断,才能达到更好的适用性。

void display_board3(char board[ROW][COL],int row,int col)
{
	int i = 0,j=0,k=0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c", board[i][j]);
			if (j < (col - 1))//判断边缘
			{
				printf(" |");
			}
			else
			{
				printf("\n");
			}
		}
		if (i < (row - 1))//判断边缘
		{
			for (k = 0; k < (row - 1); k++)//判断边缘
			{
				printf("---|");
			}
			if ((k + 1) == row)//判断边缘
			{
				printf("---\n");
			}
		}
	}
	printf("\n\n");
}

3:棋盘是否满判断函数

int full3(char board[ROW][COL], int row, int col)
{
	int i, j, count = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] != ' ')
			{
				count++;
			}
		}
	}
	if (count == row * col)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

4:三子棋算法函数

①电脑防御函数

行列对角线判断。

中规中矩

(ps:难点在五子棋的算法

int defense3(char board[ROW][COL], int row, int col)//防御函数
{
	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] || board[i][1] == board[i][2])
		{
			if (board[i][1] == '#')
			{
				for (j = 0; j < col; j++)
				{
					if (board[i][j] == ' ')
					{
						board[i][j] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", i+1, j+1);
						return 1;
					}
				}
			}
		}
		if (board[i][0] == '#' && board[i][2] == '#' && board[i][1] == ' ')
		{
			board[i][1] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] || board[1][k] == board[2][k])
		{
			if (board[1][k] == '#')
			{
				for (l = 0; l < col; l++)
				{
					if (board[l][k] == ' ')
					{
						board[l][k] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", l + 1, k + 1);
						return 1; 
					}
				}
			}
		}
		if (board[0][k] == '#' && board[2][k] == '#' && board[1][k] == ' ')
		{
			board[1][k] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}

	//对角线判断
	//左对角线
	if (board[0][0] == board[1][1])
	{
		if (board[1][1] == '#')
		{
			if (board[2][2] == ' ')
			{
				board[2][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 3);
				return 1;
			}
		}
	}

	if (board[1][1] == board[2][2])
	{
		if (board[1][1] == '#')
		{
			if (board[0][0] == ' ')
			{
				board[0][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 1, 1);
				return 1;
			}
		}
	}

	if (board[0][0] == board[2][2] && board[0][0] =='#' && board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}

	//右对角线
	if (board[2][0] == board[1][1] || board[1][1] == board[0][2])
	{
		if (board[1][1] == '#')
	    {
		  if (board[2][0] == ' ')
		  {
			board[2][0] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
			return 1;
		  }

		  if (board[0][2] == ' ')
		  {
			board[0][2] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
			return 1;
		  }
	    }
	}

	if (board[2][0] == board[0][2] && board[2][0] == '#' & board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}
	return 0;

}

②电脑进攻函数

Ctrl C+V防御函数然后改一下条件就可以了

int attack3(char board[ROW][COL], int row, int col)//进攻函数
{

	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] || board[i][1] == board[i][2])
		{
			if (board[i][1] == '*')
			{
				for (j = 0; j < col; j++)
				{
					if (board[i][j] == ' ')
					{
						board[i][j] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, j + 1);
						return 1;
					}
				}
			}
		}
		if (board[i][0] == '*' && board[i][2] == '*' && board[i][1] == ' ')
		{
			board[i][1] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] || board[1][k] == board[2][k])
		{
			if (board[1][k] == '*')
			{
				for (l = 0; l < col; l++)
				{
					if (board[l][k] == ' ')
					{
						board[l][k] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", l + 1, k + 1);
						return 1;
					}
				}
			}
		}
		if (board[0][k] == '*' && board[2][k] == '*' && board[1][k] == ' ')
		{
			board[1][k] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}

	//对角线判断
	//左对角线
	if (board[0][0] == board[1][1])
	{
		if (board[1][1] == '*')
		{
			if (board[2][2] == ' ')
			{
				board[2][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 3);
				return 1;
			}
		}
	}

	if (board[1][1] == board[2][2])
	{
		if (board[1][1] == '*')
		{
			if (board[0][0] == ' ')
			{
				board[0][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 1, 1);
				return 1;
			}
		}
	}

	if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}

	//右对角线
	if (board[2][0] == board[1][1] || board[1][1] == board[0][2])
	{
		if (board[1][1] == '*')
		{
			if (board[2][0] == ' ')
			{
				board[2][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
				return 1;
			}

			if (board[0][2] == ' ')
			{
				board[0][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
				return 1;
			}
		}
	}

	if (board[2][0] == board[0][2] && board[2][0] == '*' & board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}
	return 0;

}

5:三子棋下棋函数

void write3(char board[ROW][COL], int row, int col)//放置函数
{
	int x=0, y=0, status=0;
	int j=0, k=0;
	//注:数组坐标记得减1
	//玩家放置-------------------------------------
	printf ("请输入你要放置的坐标(x,y)---->");
	status = scanf_s("%d %d", &x, &y);//判断是否输入非数字
	while (1)//判断输入
	{
		if (((x > ROW) || (y > COL)|| (x < 0) || (y < 0))||status!=2||board[x-1][y-1]!=' ')
		{
			getchar();//过滤非数字
			printf("输入数据有错误,请重新输入:\n");
			printf("请输入你要放置的坐标(x,y)---->");
			status=scanf_s("%d %d", &x, &y);
		}
		else
		{
			printf("\n你放置的坐标是(%d,%d)\n", x, y);
			break;
		}
	}
	board[x-1][y-1]='#';

	//电脑放置-----------------------------------
	int status1 = 0, status2 = 0;
	if (!full3(board, ROW, COL))//判断棋盘是否满
	{
		if(!(status1 = attack3(board, ROW, COL)))//判断防御/进攻函数是否生效
		{
			status2 = defense3(board, ROW, COL);
		}

	    if(status2!=1)//不生效则随机放status1!=1&&
		{
			while (board[j - 1][k - 1] != ' ')
			{
				j = random(3);
				k = random(3)-random(5);
				while (k > 3||k<-4)
				{
				k = random(3) - random(5);
				}
				if (k < 0)
				{
					k = -k;
				}
			}
			board[j - 1][k - 1] = '*';
			printf("\n随机电脑放置的坐标是(%d,%d)\n\n", j, k);
		}
	}
}

6:三子棋判断输赢函数

int win3(char board[ROW][COL], int row, int col)//判断输赢
{
	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
		{
			if (board[i][0] == '#')
			{
				return 1;
			}
			else if (board[i][0] == '*')
			{
				return 0;
			}
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] && board[1][k] == board[2][k])
		{
			for (l = 0; l < col; l++)
			{
				if (board[0][k] == '#')
				{
					return 1;
				}
				else if (board[0][k] == '*')
				{
					return 0;
				}
			}
		}
	}

	//对角线判断
//左对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
	{
		if (board[0][0] == '#')
		{
			return 1;
		}
		else if (board[0][0] == '*')
		{
			return 0;
		}
	}
	//右对角线
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2])
	{
		if (board[2][0] == '#')
		{
			return 1;
		}
		else if (board[2][0] == '*')
		{
			return 0;
		}
	}
}

7:组成的game.c的内容

#include"game.h"
//共用函数-----------------------------------------------------
void delay()
{
	int i = 5;
	while (i >= 0)
	{
		system("cls");
		printf("%d\n",i);
		Sleep(1000);
		i--;
	}
}

int random(int status)
{
	int count=0;
	srand((unsigned int)time(0));
	if (status == 3)
	{
		while (count==0)
		{
			count = rand() % 4;
		}

		return count;
	}
	else if (status == 5)
	{
		while (count==0)
		{
			count = rand() % 6;
		}

		return count;
	}

}

void menu()
{
	printf("      菜单\n");
	printf("----1.三子棋----\n");
	printf("----2.五子棋----\n");
	printf("----3.退出 ----\n");
}

void choose(int input)
{
	switch (input)
	{
	case 1:
		printf("欢迎来到三子棋,祝你游戏愉快!\n\n");
		game3();
		break;
	case 2:
		printf("欢迎来到五子棋,祝你游戏愉快!\n\n");
		game5();
		break;
	case 3:
		printf("欢迎下次光临!\n");
		break;
	}
}

void start()//开始游戏
{
	int input = 0, status = 0;
	menu();
	printf("请输入你的选择----->");
	status = scanf_s("%d", &input);
	while (status != 1 || input > 3 || input <= 0)//过滤错误输入
	{
		getchar();
		printf("输入数据有错误,请重新输入正确范围数字:\n");
		printf("请输入你的选择----->");
		status = scanf_s("%d", &input);
	}
	choose(input);

}


//三③子棋函数----------------------------------------------------

void init_board3( char board[ROW][COL],int row, int col)//初始化函数
{
	int i=0,j=0;
	for (i=0 ; i <row ;i++)
	{
		for (j=0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void display_board3(char board[ROW][COL],int row,int col)
{
	int i = 0,j=0,k=0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c", board[i][j]);
			if (j < (col - 1))//判断边缘
			{
				printf(" |");
			}
			else
			{
				printf("\n");
			}
		}
		if (i < (row - 1))//判断边缘
		{
			for (k = 0; k < (row - 1); k++)//判断边缘
			{
				printf("---|");
			}
			if ((k + 1) == row)//判断边缘
			{
				printf("---\n");
			}
		}
	}
	printf("\n\n");
}


int full3(char board[ROW][COL], int row, int col)
{
	int i, j, count = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] != ' ')
			{
				count++;
			}
		}
	}
	if (count == row * col)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int defense3(char board[ROW][COL], int row, int col)//防御函数
{
	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] || board[i][1] == board[i][2])
		{
			if (board[i][1] == '#')
			{
				for (j = 0; j < col; j++)
				{
					if (board[i][j] == ' ')
					{
						board[i][j] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", i+1, j+1);
						return 1;
					}
				}
			}
		}
		if (board[i][0] == '#' && board[i][2] == '#' && board[i][1] == ' ')
		{
			board[i][1] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] || board[1][k] == board[2][k])
		{
			if (board[1][k] == '#')
			{
				for (l = 0; l < col; l++)
				{
					if (board[l][k] == ' ')
					{
						board[l][k] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", l + 1, k + 1);
						return 1; 
					}
				}
			}
		}
		if (board[0][k] == '#' && board[2][k] == '#' && board[1][k] == ' ')
		{
			board[1][k] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}

	//对角线判断
	//左对角线
	if (board[0][0] == board[1][1])
	{
		if (board[1][1] == '#')
		{
			if (board[2][2] == ' ')
			{
				board[2][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 3);
				return 1;
			}
		}
	}

	if (board[1][1] == board[2][2])
	{
		if (board[1][1] == '#')
		{
			if (board[0][0] == ' ')
			{
				board[0][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 1, 1);
				return 1;
			}
		}
	}

	if (board[0][0] == board[2][2] && board[0][0] =='#' && board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}

	//右对角线
	if (board[2][0] == board[1][1] || board[1][1] == board[0][2])
	{
		if (board[1][1] == '#')
	    {
		  if (board[2][0] == ' ')
		  {
			board[2][0] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
			return 1;
		  }

		  if (board[0][2] == ' ')
		  {
			board[0][2] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
			return 1;
		  }
	    }
	}

	if (board[2][0] == board[0][2] && board[2][0] == '#' & board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}
	return 0;

}

int attack3(char board[ROW][COL], int row, int col)//进攻函数
{

	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] || board[i][1] == board[i][2])
		{
			if (board[i][1] == '*')
			{
				for (j = 0; j < col; j++)
				{
					if (board[i][j] == ' ')
					{
						board[i][j] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, j + 1);
						return 1;
					}
				}
			}
		}
		if (board[i][0] == '*' && board[i][2] == '*' && board[i][1] == ' ')
		{
			board[i][1] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] || board[1][k] == board[2][k])
		{
			if (board[1][k] == '*')
			{
				for (l = 0; l < col; l++)
				{
					if (board[l][k] == ' ')
					{
						board[l][k] = '*';
						printf("\n电脑放置的坐标是(%d,%d)\n\n", l + 1, k + 1);
						return 1;
					}
				}
			}
		}
		if (board[0][k] == '*' && board[2][k] == '*' && board[1][k] == ' ')
		{
			board[1][k] = '*';
			printf("\n电脑放置的坐标是(%d,%d)\n\n", i + 1, 2);
			return 1;
		}
	}

	//对角线判断
	//左对角线
	if (board[0][0] == board[1][1])
	{
		if (board[1][1] == '*')
		{
			if (board[2][2] == ' ')
			{
				board[2][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 3);
				return 1;
			}
		}
	}

	if (board[1][1] == board[2][2])
	{
		if (board[1][1] == '*')
		{
			if (board[0][0] == ' ')
			{
				board[0][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 1, 1);
				return 1;
			}
		}
	}

	if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}

	//右对角线
	if (board[2][0] == board[1][1] || board[1][1] == board[0][2])
	{
		if (board[1][1] == '*')
		{
			if (board[2][0] == ' ')
			{
				board[2][0] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
				return 1;
			}

			if (board[0][2] == ' ')
			{
				board[0][2] = '*';
				printf("\n电脑放置的坐标是(%d,%d)\n\n", 3, 1);
				return 1;
			}
		}
	}

	if (board[2][0] == board[0][2] && board[2][0] == '*' & board[1][1] == ' ')
	{
		board[1][1] = '*';
		printf("\n电脑放置的坐标是(%d,%d)\n\n", 2, 2);
		return 1;
	}
	return 0;

}

void write3(char board[ROW][COL], int row, int col)//放置函数
{
	int x=0, y=0, status=0;
	int j=0, k=0;
	//注:数组坐标记得减1
	//玩家放置-------------------------------------
	printf ("请输入你要放置的坐标(x,y)---->");
	status = scanf_s("%d %d", &x, &y);//判断是否输入非数字
	while (1)//判断输入
	{
		if (((x > ROW) || (y > COL)|| (x < 0) || (y < 0))||status!=2||board[x-1][y-1]!=' ')
		{
			getchar();//过滤非数字
			printf("输入数据有错误,请重新输入:\n");
			printf("请输入你要放置的坐标(x,y)---->");
			status=scanf_s("%d %d", &x, &y);
		}
		else
		{
			printf("\n你放置的坐标是(%d,%d)\n", x, y);
			break;
		}
	}
	board[x-1][y-1]='#';

	//电脑放置-----------------------------------
	int status1 = 0, status2 = 0;
	if (!full3(board, ROW, COL))//判断棋盘是否满
	{
		if(!(status1 = attack3(board, ROW, COL)))//判断防御/进攻函数是否生效
		{
			status2 = defense3(board, ROW, COL);
		}

	    if(status2!=1)//不生效则随机放status1!=1&&
		{
			while (board[j - 1][k - 1] != ' ')
			{
				j = random(3);
				k = random(3)-random(5);
				while (k > 3||k<-4)
				{
				k = random(3) - random(5);
				}
				if (k < 0)
				{
					k = -k;
				}
			}
			board[j - 1][k - 1] = '*';
			printf("\n随机电脑放置的坐标是(%d,%d)\n\n", j, k);
		}
	}
}

int win3(char board[ROW][COL], int row, int col)//判断输赢
{
	int i = 0, k = 0, j = 0, l = 0;
	//行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
		{
			if (board[i][0] == '#')
			{
				return 1;
			}
			else if (board[i][0] == '*')
			{
				return 0;
			}
		}
	}
	//列判断
	for (k = 0; k < col; k++)
	{
		if (board[0][k] == board[1][k] && board[1][k] == board[2][k])
		{
			for (l = 0; l < col; l++)
			{
				if (board[0][k] == '#')
				{
					return 1;
				}
				else if (board[0][k] == '*')
				{
					return 0;
				}
			}
		}
	}

	//对角线判断
//左对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
	{
		if (board[0][0] == '#')
		{
			return 1;
		}
		else if (board[0][0] == '*')
		{
			return 0;
		}
	}
	//右对角线
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2])
	{
		if (board[2][0] == '#')
		{
			return 1;
		}
		else if (board[2][0] == '*')
		{
			return 0;
		}
	}
}


//五⑤子棋函数----------------------------------------------------
void init_board5(char board[RO][CO], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}


void display_board5(char board[RO][CO], int row, int col)
{
	int i = 0, j = 0, k = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c", board[i][j]);
			if (j < (col - 1))//判断边缘
			{
				printf(" |");
			}
			else
			{
				printf("\n");
			}
		}
		if (i < (row - 1))//判断边缘
		{
			for (k = 0; k < (row - 1); k++)//判断边缘
			{
				printf("---|");
			}
			if ((k + 1) == row)//判断边缘
			{
				printf("---\n");
			}
		}
	}
	printf("\n\n");
}


void write5(char board[RO][CO], int row, int col)
{
	int x = 0, y = 0, status = 0;
	int j, k;
	//注:数组坐标记得减1
	//玩家放置-------------------------------------
	printf("请输入你要放置的坐标(x,y)---->");
	status = scanf_s("%d %d", &x, &y);//判断是否输入非数字
	while (1)//判断输入
	{
		if ((x > RO) || (y > CO) || (x < 0) || (y < 0) || status != 2 || board[x - 1][y - 1] != ' ')
		{
			getchar();//过滤非数字
			printf("输入数据有错误,请重新输入:\n");
			printf("请输入你要放置的坐标(x,y)---->");
			status = scanf_s("%d %d", &x, &y);
		}
		else
		{
			break;
		}
	}
	board[x-1][y-1] = '#';
	//电脑放置-----------------------------------
	j = random(5);
	k = random(5);
	while (board[j - 1][k - 1] != ' ')
	{
		j = random(5);
		k = random(5);
	}
	board[j - 1][k - 1] = '*';

}

4:main.c中三子棋功能运行逻辑函数

一、流程图

二、代码

void game3()
{
	int board[ROW][COL] = { 0 },count=0,status=2;
	init_board3(board, ROW, COL); 
	display_board3(board, ROW, COL);
	while (1)
	{
		write3(board, ROW, COL);
			display_board3(board, ROW, COL);
			status = win3(board, ROW, COL);
			if (status==1)
			{
				printf("你赢了,恭喜!\n");
				break;
			}
			else if(status == 0)
			{
				printf("你输了,没事,还能再来!\n");
				break;
			}
			if (full3(board, ROW, COL))
			{
				printf("平局!请重新开始游戏!\n");
				break;
			}
	}
	system("cls");
	printf("\n\n");
	start();
}	

5:总结

作为一名新手,这次写这个项目,让我更加熟悉了c语言在实际中的应用。而且这个写起来并没有我想的那么简单。过程中很可能因为一些很低级很小的错误比如复制下来后==没改=,==用成=等等,导致bug,然后找半天。还要考虑代码的可读性,可维护性。反正就是考虑的东西会比我想的多,实际写下来会遇到问题,比我想的要困难一些。这还只是三子棋。然后我要继续完成比较难的五子棋了(主要在算法实现处)。

  • 32
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 以下是一个简单的C语言实现六子棋α-β剪枝的代码代码中使用了一个双重递归函数,其中alpha和beta是剪枝参数。这个函数在每个节点上执行,并尝试通过剪枝来减少搜索空间。在搜索树的每一层上,它从所有可能的动作中选择一个动作,并将其应用于当前状态。然后它递归地调用自身,以查找下一层的最佳动作。如果一个节点的值被剪枝,则不需要再搜索该节点的子树,因为已经知道它的值不会优于其他节点。 ``` #include <stdio.h> #include <stdlib.h> #include <limits.h> #define BOARD_SIZE 6 #define MAX_DEPTH 4 typedef struct { int board[BOARD_SIZE][BOARD_SIZE]; } State; int evaluate(State state) { // TODO: Implement a heuristic evaluation function return 0; } int alphabeta(State state, int depth, int alpha, int beta, int maximizingPlayer) { if (depth == 0) { return evaluate(state); } if (maximizingPlayer) { int value = INT_MIN; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (state.board[i][j] == 0) { state.board[i][j] = 1; value = max(value, alphabeta(state, depth - 1, alpha, beta, 0)); state.board[i][j] = 0; alpha = max(alpha, value); if (beta <= alpha) { break; } } } } return value; } else { int value = INT_MAX; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (state.board[i][j] == 0) { state.board[i][j] = -1; value = min(value, alphabeta(state, depth - 1, alpha, beta, 1)); state.board[i][j] = 0; beta = min(beta, value); if (beta <= alpha) { break; } } } } return value; } } int main() { State initialState = {0}; // Initialize the board to all zeros int bestValue = alphabeta(initialState, MAX_DEPTH, INT_MIN, INT_MAX, 1); printf("Best value: %d\n", bestValue); return 0; } ``` 现在我们来详细解释一下代码中的每个部分。 首先我们定义了一个State结构体来表示游戏状态。它包含一个二维数组,表示六子棋棋盘上每个位置的状态。0表示该位置为空,1表示该位置为黑子,-1表示该位置为白子。 ``` typedef struct { int board[BOARD_SIZE][BOARD_SIZE]; } State; ``` 接下来,我们实现了一个evaluate函数,用于评估当前游戏状态的好坏。该函数应该根据当前状态返回一个分数,表示该状态的好坏。这是一个关键函数,因为它决定了如何搜索游戏树。如果它能够正确地评估状态的好坏,那么搜索算法就可以更快地找到最佳动作。 ``` int evaluate(State state) { // TODO: Implement a heuristic evaluation function return 0; } ``` 接下来,我们实现了一个alphabeta函数,用于执行α-β剪枝搜索。它采用当前状态、搜索深度、α和β剪枝参数以及一个布尔值maximizingPlayer作为输入。如果maximizingPlayer为true,则它正在搜索玩家的最佳动作。如果maximizingPlayer为false,则它正在搜索对手的最佳动作。 ``` int alphabeta(State state, int depth, int alpha, int beta, int maximizingPlayer) { if (depth == 0) { return evaluate(state); } if (maximizingPlayer) { int value = INT_MIN; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (state.board[i][j] == 0) { state.board[i][j] = 1; value = max(value, alphabeta(state, depth - 1, alpha, beta, 0)); state.board[i][j] = 0; alpha = max(alpha, value); if (beta <= alpha) { break; } } } } return value; } else { int value = INT_MAX; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (state.board[i][j] == 0) { state.board[i][j] = -1; value = min(value, alphabeta(state, depth - 1, alpha, beta, 1)); state.board[i][j] = 0; beta = min(beta, value); if (beta <= alpha) { break; } } } } return value; } } ``` 该函数使用递归方式搜索游戏树。如果搜索深度达到最大深度,则返回当前状态的评估值。否则,如果maximizingPlayer为true,则从当前状态的所有可能动作中选择一个动作,并递归地调用自身来查找下一层的最佳动作。在递归调用返回后,它更新alpha参数并检查是否可以剪枝。如果beta小于等于alpha,则它返回当前节点的值。如果maximizingPlayer为false,则执行类似的操作,但这次是搜索对手的最佳动作。它选择一个动作,并递归地调用自身来查找下一层的最佳动作。在递归调用返回后,它更新beta参数并检查是否可以剪枝。如果beta小于等于alpha,则它返回当前节点的值。 最后,我们在main函数中调用alphabeta函数,传递初始状态、最大深度以及α和β的初始值。该函数返回最佳动作的分数。我们可以使用这个分数来选择最佳动作。 ``` int main() { State initialState = {0}; // Initialize the board to all zeros int bestValue = alphabeta(initialState, MAX_DEPTH, INT_MIN, INT_MAX, 1); printf("Best value: %d\n", bestValue); return 0; } ``` 这是一个非常简单的例子,但它展示了如何使用α-β剪枝搜索来解决六子棋问题。在实践中,您需要实现更复杂的评估函数,并使用更多的搜索深度来获得更好的结果。 ### 回答2: C语言实现六子棋α-β剪枝的代码并详细解释 六子棋是一种双人对弈游戏,类似于五子棋。α-β剪枝是一种搜索树剪枝算法,可以在搜索树中减少无用的搜索步骤,提高搜索效率。 首先,我们需要定义棋盘和棋子的数据结构。 ```c #define SIZE 6 typedef struct { int x; int y; } Point; typedef struct { char board[SIZE][SIZE]; Point move; } State; ``` 然后,我们需要定义评估函数,用于评估当前局面的分数。 ```c int evaluate(State state) { // 根据当前局面评估分数 // 实现自己的评估算法 } ``` 接下来,我们需要定义最大值算法和最小值算法,分别代表电脑和玩家的决策过程。 ```c int max_value(State state, int alpha, int beta) { if (terminal_state(state)) { return evaluate(state); } int value = INT_MIN; for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { if (is_valid_move(state, i, j)) { State new_state = make_move(state, i, j); int min_val = min_value(new_state, alpha, beta); if (min_val > value) { value = min_val; if (value > alpha) { alpha = value; } if (alpha >= beta) { return value; } } } } } return value; } int min_value(State state, int alpha, int beta) { if (terminal_state(state)) { return evaluate(state); } int value = INT_MAX; for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { if (is_valid_move(state, i, j)) { State new_state = make_move(state, i, j); int max_val = max_value(new_state, alpha, beta); if (max_val < value) { value = max_val; if (value < beta) { beta = value; } if (alpha >= beta) { return value; } } } } } return value; } ``` 最后,我们需要定义主函数来调用最大值算法和最小值算法。 ```c int main() { State initial_state; // 初始化棋盘 while (!game_over) { Point move = get_player_move(); make_move(initial_state, move.x, move.y); Point best_move = alpha_beta_search(initial_state); make_move(initial_state, best_move.x, best_move.y); } return 0; } ``` 以上就是使用C语言实现六子棋α-β剪枝的代码及其详细解释。其中,评估函数在实际应用中需要根据具体情况进行设计,最大值算法和最小值算法配合α-β剪枝可以大幅度提高搜索效率,在棋类游戏等决策问题中具有重要作用。 ### 回答3: C语言实现六子棋α-β剪枝的代码并详细解释如下: ```c #include<stdio.h> #include<stdlib.h> // 定义棋盘大小和玩家 #define ROWS 8 #define COLS 8 #define EMPTY 0 #define PLAYER_X 1 #define PLAYER_O 2 // 评估函数,用于估计当前棋局对玩家X的价值 int evaluate(int chessboard[][COLS], int player) { // 获取玩家X和玩家O在棋盘上的得分 int player_x_score = 0; int player_o_score = 0; // 在代码中计算每个玩家在所有可能的连续六个位置上所得分 // 并将这些得分累加到各自的总分中 // ... // 返回玩家X的得分减去玩家O的得分作为棋局的评估值 return player_x_score - player_o_score; } // α-β剪枝搜索函数,用于预测接下来的最佳行动 int alpha_beta_search(int chessboard[][COLS], int depth, int alpha, int beta, int player) { // 判断是否达到了搜索的最深深度或者游戏结束 if (depth == 0 || game_over(chessboard)) { return evaluate(chessboard, PLAYER_X); } // 如果是玩家X的回合,即极大节点 if (player == PLAYER_X) { int max_eval = INT_MIN; // 对于每一个合法的行动 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (valid_move(chessboard, i, j)) { // 在复制的棋盘上做出这一行动 chessboard[i][j] = player; // 调用递归搜索下一层,当前玩家为玩家O int eval = alpha_beta_search(chessboard, depth - 1, alpha, beta, PLAYER_O); // 恢复棋盘 chessboard[i][j] = EMPTY; // 更新最大值和alpha值 if (eval > max_eval) { max_eval = eval; } if (eval > alpha) { alpha = eval; } // 进行剪枝 if (alpha >= beta) { break; } } } } return max_eval; } // 如果是玩家O的回合,即极小节点,代码类似于玩家X的回合 else { int min_eval = INT_MAX; // ... return min_eval; } } // 可以实现其他辅助函数,如判断游戏是否结束、判断行动是否合法等 int main() { // 初始化棋盘和其他变量 // ... // 调用alpha_beta_search函数搜索最佳行动 int best_move = alpha_beta_search(chessboard, depth, INT_MIN, INT_MAX, PLAYER_X); // 执行最佳行动 // ... return 0; } ``` 以上是使用C语言实现六子棋α-β剪枝的简单代码框架。主要思路是通过递归地搜索棋盘的各种可能性,并使用α-β剪枝进行优化以减少搜索空间。其中,evaluate函数用于评估当前局面对玩家X的价值,根据得分的差异来评估棋局的优劣。alpha_beta_search函数实现了α-β剪枝算法,根据当前节点是极大节点还是极小节点,进行不同的操作。在玩家X的回合,遍历所有合法行动,对每个行动进行搜索,并更新最大值和alpha值,同时进行剪枝。在玩家O的回合,代码与玩家X的回合类似,只是更新最小值和beta值。最后通过调用alpha_beta_search函数从当前局面中搜索出最佳行动,并执行该行动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值