C语言双人贪吃蛇游戏瘦身版本

代码如下,希望大家批评指正哈。很多没有加注释,但是有基础的人还是能看懂的 hhhhh

运行环境 vs2017

VS2017中使用fopen、sprintf等函数会出现安全问题,如下: 
error C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.


经测试成功的解决方法:右键工程名–>属性–>C/C++–>预处理器–>预处理器定义,编辑右边输入框加入: 
_CRT_SECURE_NO_WARNINGS 
保存。

/*
贪吃蛇游戏 //双人版本  玩家2使用 W 上    S下	A左   D右边
                       玩家1使用 箭头上   箭头下  箭头左   箭头右
*/
/*
作者:李金虎
*/
/*
时间:2018-04-06
*/
/*
QQ:1910084514
*/

#include
#include
#include
#include
int a = 1;
int a2 = 1;
int snack_life=1;//1代表游戏继续  0代表游戏结束
int snack_life2 = 1;//1代表游戏继续  0代表游戏结束 玩家2
int count = 0;//得分
int count2 = 0;//得分  玩家2
int speed=0;//贪吃蛇的速度
int who_flag=0;//判断是谁吃了标志位  0为玩家1吃了  1为玩家2吃了
void gotoxy(int x, int y)//光标移动函数,光标想在哪里就在哪里
{
	COORD coord = { x , y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

struct food //食物结构体
{
	int x;
	int y;
	int life;
}Food;

struct snack //蛇结构体
{
	int x;
	int y;
	struct snack *next;
} *snack_body, *snack_body2;


void color(short x) //自定义函根据参数改变颜色   
{
	if (x >= 0 && x <= 15)//参数在0-15的范围颜色  
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);    //只有一个参数,改变字体颜色   
	else//默认的颜色白色  
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}

void product_food() //产生食物坐标函数
{
	remake:
	struct snack *p;//定义一个临时指针变量 指向snack_body
	struct snack *p2;//定义一个临时指针变量 指向snack_body
	p = snack_body;
	p2 = snack_body2;
	srand(time(NULL));
	Food.x = (rand() % 16 + 4)*2;
	Food.y = rand() % 17 + 2;
	Food.life = 1;
	while (p != NULL)  //防止食物生成在蛇所处的位置,如果生成在蛇身体的位置,则重新生成食物
	{
		if (Food.x == p->x&&p->y == Food.y)
			goto remake;//跳转回去,重新产生一个食物
		p = p->next;
	}
	//while (p2 != NULL)  //防止食物生成在蛇所处的位置,如果生成在蛇身体的位置,则重新生成食物
	//{
	//	if (Food.x == p2->x&&p2->y == Food.y)
	//		goto remake;//跳转回去,重新产生一个食物
	//	p2 = p2->next;
	//}
	gotoxy(Food.x, Food.y);
	printf("G");
}


void introduce()
{
	
	system("cls");
	gotoxy(10, 2);
	printf("欢迎来到贪吃蛇的世界 ,这次带来的是一个双人贪吃蛇游戏\n");
	gotoxy(10, 4);
	printf("我是李金虎,此代码的作者\n");
	gotoxy(10, 6);
	printf("完成时间: 2018-04-09 , 历时7小时\n");
	gotoxy(10, 8);
	printf("初次编写贪吃蛇,代码风格以及逻辑有很多的不足\n");
	gotoxy(10, 10);
	printf("如果有些代码不懂的小伙伴可以加我QQ1910084514私信我,乐意为您效劳\n");
	gotoxy(10, 12);
	printf("希望您游戏愉快\n");

	while (speed<=0||speed>=21)
	{
		gotoxy(10, 14);
		printf("请输入游戏的级别 最快的为20级,最慢为1级,请输入一个整数:");
		scanf_s("%d", &speed);
	}
	system("cls");
	gotoxy(10, 16);
	printf("按任意键盘,确认开始游戏");
	system("pause");
	system("cls");
	
}

void map()  //打印地图函数
{
	for (int i = 0; i < 20; i++)
	{
		gotoxy(i*2, 0);
		printf("〇");
		gotoxy(i * 2, 19);
		printf("〇");
		gotoxy(0, i);
		printf("〇");
		gotoxy(40, i);
		printf("〇");
	}
	gotoxy(50, 7);
	printf("玩家1得分:%d", count);
	gotoxy(50, 8);
	printf("玩家2得分:%d", count);
	gotoxy(50, 9);
	printf("游戏难度:%d 级",speed);
	gotoxy(50, 10);
	printf("-----贪吃蛇小游戏-----");
	gotoxy(50, 11);
	printf("--作者--李金虎");
}

void init_snack()//蛇初始化函数
{
	struct snack *p;
	struct snack *p2;

	color(3);
	p2 = (struct snack *)(malloc(sizeof(struct snack)));
	p2->x = 10;
	p2->y = 10;
	snack_body2 = p2;
	p2->next = (struct snack *)(malloc(sizeof(struct snack)));
	p2 = p2->next;
	p2->x = 10;
	p2->y = 9;
	p2->next = (struct snack *)(malloc(sizeof(struct snack)));
	p2 = p2->next;
	p2->x = 10;
	p2->y = 8;
	p2->next = (struct snack *)(malloc(sizeof(struct snack)));
	p2 = p2->next;
	p2->x = 10;
	p2->y = 7;
	p2->next = NULL;
	p2 = snack_body2;
	while (p2 != NULL)
	{
		gotoxy(p2->x, p2->y);
		printf("G");
		p2 = p2->next;
	}
	color(16);


	color(4);
	p= (struct snack *)(malloc(sizeof(struct snack)));
	p->x = 30;
	p->y = 10;
	snack_body = p;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 30;
	p->y = 9;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 30;
	p->y = 8;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 30;
	p->y = 7;
	p->next = NULL;
	p= snack_body;
	while (p != NULL)
	{
		gotoxy(p->x, p->y);
		printf("G");
		p = p->next;
	}
	color(16);
}

int control(void)//蛇的控制函数
{

	int down;
	int left;//左
	int right;//右
	int up;
		down = GetKeyState(VK_DOWN);//获取上箭头键状态   
		if (down < 0&& a!=2 )      //如果上箭头键被按下   a!=2 的作用在于复制头朝下的时候蛇还会往上走
		{
			a = 1;
		}
		up = GetKeyState(VK_UP);//获取下箭头键状态  
		if (up < 0 && a != 1)      //如果下箭头键被按下   
		{
			a = 2;
		}
		left = GetKeyState(VK_LEFT);//获取左箭头键状态   
		if (left < 0 && a != 4)      //如果左箭头键被按下   
		{
			a = 3;
		}
		right = GetKeyState(VK_RIGHT);//获取右箭头键状态   
		if (right < 0 && a != 3)      //如果右箭头键被按下   
		{
			a = 4;
		}
		return a;
}
int control2(void)//蛇的控制函数 玩家2
{

	int down;
	int left;//左
	int right;//右
	int up;
	down = GetKeyState('S');//获取箭下头键状态   
	if (down < 0 && a2 != 2)      //如果上箭头键被按下   a!=2 的作用在于复制头朝下的时候蛇还会往上走
	{
		a2 = 1;
	}
	up = GetKeyState('W');//获取上箭头键状态  
	if (up < 0 && a2 != 1)      //如果下箭头键被按下   
	{
		a2 = 2;
	}
	left = GetKeyState('A');//获取左箭头键状态   
	if (left < 0 && a2 != 4)      //如果左箭头键被按下   
	{
		a2 = 3;
	}
	right = GetKeyState('D');//获取右箭头键状态   
	if (right < 0 && a2 != 3)      //如果右箭头键被按下   
	{
		a2 = 4;
	}
	return a2;
}

int is_eat_itself(int x, int y)
{
	struct snack *p;
	p = snack_body;
	p = p->next;//跳过蛇头
	while (p != NULL)
	{
		if (x == p->x &&  y == p->y)//如果蛇咬到自己
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}
int is_eat_itself2(int x, int y)
{
	struct snack *p;
	p = snack_body2;
	p = p->next;//跳过蛇头
	while (p != NULL)
	{
		if (x == p->x &&  y == p->y)//如果蛇咬到自己
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}

void is(int x, int y, struct snack *p2, struct snack *p1)
{
	p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
	p1->x = x;
	p1->y = y;
	p1->next = snack_body;
	snack_body = p1;
	p2 = snack_body;

	if (!((y < 1 || y > 18) || (x < 2 || x >38)) && !is_eat_itself(x, y))//判断是否撞墙
	{
		gotoxy(snack_body->x, snack_body->y);
		printf("G");//打印新蛇头
		if (x == Food.x&&y == Food.y)
		{
			Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			who_flag = 1;//表示被此玩家吃掉
		}
		else
		{
			while (((p2->next)->next) != NULL)//倒数第二个身体
			{
				p2 = p2->next;
			}
			gotoxy(p2->next->x, p2->next->y);
			printf(" ");//清除蛇尾
			free(p2->next);//释放蛇尾
			p2->next = NULL;
			p2 = NULL;
		}
	}
	else
	{
		snack_life = 0;
	}
}

void snack_move(int direction )//蛇移动函数  direction为方向    direction的值是1向上 2向下 3向左 4向右
{
	 int y=0;
	 int x=0;
	struct snack *p4=NULL;
	struct snack *p1=NULL;
	struct snack *p2 = NULL;
	p4 = snack_body;
	x = p4->x;//临时储存当前的蛇头坐标
	y = p4->y;
	color(4);
	if (1 == direction)
	{
		y=y + (1);

		is(x, y, p2, p1);
	}
	else if (2 == direction)
	{
		y=y -(1);

		is(x, y, p2, p1);
	}

	else if (3 == direction)
	{
		x=x - (1 * 2);

		is(x, y, p2, p1);
	}
	
	if (4 == direction)
	{
		x = x + (1 * 2);

		is(x, y, p2, p1);
	}
	color(16);
}





void is2(int x,int y, struct snack *p2, struct snack *p1)
{
	p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
	p1->x = x;
	p1->y = y;
	p1->next = snack_body2;
	snack_body2 = p1;
	p2 = snack_body2;
	if (!((y < 1 || y > 18) || (x < 2 || x >38)) && !is_eat_itself2(x, y))//判断是否撞墙 满足条件就是没撞墙
	{
		gotoxy(snack_body2->x, snack_body2->y);
		printf("G");//打印新蛇头
		if (x == Food.x&&y == Food.y)
		{
			Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			who_flag = 0;//表示被此玩家吃掉
		}
		else
		{
			while (((p2->next)->next) != NULL)//倒数第二个身体
			{
				p2 = p2->next;
			}
			gotoxy(p2->next->x, p2->next->y);
			printf(" ");//清除蛇尾
			free(p2->next);//释放蛇尾
			p2->next = NULL;
			p2 = NULL;
		}
	}
	else
	{
		snack_life2 = 0;
	}
}

void snack_move2(int direction)//蛇移动函数  direction为方向    direction的值是1向上 2向下 3向左 4向右  玩家2
{
	int y = 0;
	int x = 0;
	struct snack *p4 = NULL;
	struct snack *p1 = NULL;
	struct snack *p2 = NULL;
	p4 = snack_body2;
	x = p4->x;//临时储存当前的蛇头坐标
	y = p4->y;
	color(3);
	if (1 == direction)
	{
		y = y + (1);

		is2(x, y, p2,p1);	
	}
	else if (2 == direction)
	{

		y = y - (1);

			is2(x, y, p2,p1);
	}

	else if (3 == direction)
	{

		x = x - (1 * 2);

		is2(x, y, p2,p1);
	}

	if (4 == direction)
	{
		x = x + (1 * 2);
	
		is2(x, y, p2,p1);
	}
	color(16);
}


void add_grade()//加分函数
{
	if (0 == Food.life)//被吃掉就在此产生食物
	{
		if (0 == who_flag)
		{
			count = count + speed;
			gotoxy(60, 8);
			printf("%d", count);
		}

		if (1 == who_flag)
		{
			count2 = count2 + speed;
			gotoxy(60, 7);
			printf("%d", count2);
		}
		product_food();
	}
}

void is_who_winner()//判断谁赢的函数
{
	if (snack_life == 0 || snack_life2 == 0)//谁死谁输
	{
		gotoxy(20, 20);
		printf("有玩家撞死了,游戏结束!!!\n");
		if (snack_life == 0 && snack_life2 == 1)
		{
			printf("玩家2胜利\n");
		}
		if (snack_life == 1 && snack_life2 == 0)
		{
			printf("玩家1胜利\n");
		}
		if (snack_life == 0 && snack_life2 == 0)
		{
			printf("平局\n");
		}
	}
	else//都没死
	{
		gotoxy(20, 20);
		printf("\n");
		if (count > count2)
		{
			printf("玩家1胜利\n");
		}
		else if (count < count2)
		{
			printf("玩家2胜利\n");
		}
	}
}



int main()
{	
	int i = 0;
	char ch;
restart:
	count = 0;//玩家1分数清零
	count2 = 0;//玩家2分数清零
	a = 1;//向下走 玩家1初始向下走
	a2 = 1;//向下走 玩家2初始向下走
	Food.life = 0;//使重新产生食物
	snack_life = 1;//蛇活着  玩家1活着
	snack_life2 = 1;//蛇活着  玩家2活着
	speed = 0;//游戏速度
	introduce();//自我介绍
	map();//打印地图
	product_food();//随机产生食物
	init_snack();//蛇的初始化,打印蛇
	while (1)
	{
		i = 10;
		add_grade();//分数计算函数
		snack_move(control());//玩家1移动函数
		snack_move2(control2());//玩家2移动函数
		if (snack_life == 0|| snack_life2 == 0||count>100||count2>100)
		{
			break; //游戏结束
		}
		while (i--)//把延时分开来增加检测的次数
		{
			control();//按键检测
			control2();//按键检测
			Sleep(210 - speed * 10);
		}
	}
	is_who_winner();
	while (1)
	{
		gotoxy(20, 21);
		printf("是否继续:Y/N:");
		scanf_s("%c", &ch);
	
		if ('Y' == ch)
		{
		free(snack_body);//释放上一局游戏内存
		snack_body = NULL;
		free(snack_body2);//释放上一局游戏内存
		snack_body = NULL;
			goto restart;
		}
		else if('N'==ch)
		{
			
			break;//退出游戏
		}
		
	}
	return 0;
}

你可能感兴趣的:(C语言双人贪吃蛇游戏瘦身版本)