代码如下,希望大家批评指正哈。很多没有加注释,但是有基础的人还是能看懂的 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;
}