当前位置:   article > 正文

双人联网贪吃蛇C语言,c语言贪吃蛇-单人模式&双人对抗

双人联网贪吃蛇C语言,c语言贪吃蛇-单人模式&双人对抗

一、项目说明

​ 使用c语言编写,实现了如下功能:

​ 1、较简单的用户界面,提供多种模式供选择

​ 2、贪吃蛇的四向移动、吃到食物后长度增长、分数增长并实时刷新等基本功能

​ 3、创新双人模式玩法,设置积分上限,让玩家相互竞争与攻击

二、 代码/设计结构说明

1、头文件使用说明:

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

#include//

#include//

#include

​ windows.h: windows窗口相关头文件,用于定义窗口尺寸、编写用户界面;

​ time.h:日期和时间头文件,用于需要时间方面的函数,用于控制时间;

​ string.h:字符串相关操作;

​ stdlib.h:standard library标准库函数头文件;

​ conio.h:控制台输入输出文件;

2、分别定义蛇、玩家等的结构体,用结构体更加清楚的表达蛇的节点数、节点位置、当前状态,以及玩家的名称、分数等信息,并用main函数内的while循环实时刷新相关信息。

struct FOOD{

int x;

int y;

};

struct SNAKE{

int x[maxsize];

int y[maxsize];//坐标

int len ;//设定长度

int speed;//蛇移动的速度

char key;

};

struct INFO {

char name[7];

char moshi[6];

int score;

};

3、光标相关函数

/定义隐藏光标函数,更加美观

void HideCursor()

{

CONSOLE_CURSOR_INFO cursor;

cursor.bVisible = FALSE;

cursor.dwSize = sizeof(cursor);

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorInfo(handle, &cursor);

}

//将光标移动到控制台的(int x,int y)处,非常重要的函数

void movefile(int x,int y)

{

COORD coord;//坐标结构

coord.X=x;

coord.Y=y;

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);//定义设置控制台光标位置。

HideCursor();

}

4、运动控制函数

//键盘控制函数

void keycontrl()

{

//fflush(stdin);

if(_kbhit())//响应键盘输入事件

{

fflush(stdin);//清空缓冲区的字符

keys=_getch();

keys=_getch();

}

if(keys!=72&&keys!=80&&keys!=77&&keys!=75)

keys=pre_key;

//防止蛇直接反向行进

if (pre_key == 72 && keys == 80)

keys = 72;

if (pre_key == 80 && keys == 72)

keys = 80;

if (pre_key == 75 && keys == 77)

keys = 75;

if (pre_key == 77 && keys == 75)

keys = 77;

pre_key=keys;

movefile(81,31);

}

/**

*控制台按键所代表的数字

*“↑”:72

*“↓”:80

*“←”:75

*“→”:77

*"W":87

*“A”:65

*"S":83

*"D":68*/

//判断蛇头应该往哪个方向移动

//运动相关函数

void runcontrl()

{

//若没有吃到食物,即flag=0,则在移动时抹去最后一位的字符

if(flag==0)

{

movefile(snake.x[snake.len-1],snake.y[snake.len-1]);

printf(" ");

for(int i=snake.len-1;i>0;i--)//画蛇身

{

snake.x[i]=snake.x[i-1];

snake.y[i]=snake.y[i-1];

}

}

else if(flag==1)

{

movefile(snake.x[snake.len-2],snake.y[snake.len-2]);

printf(" ");

for(int i=snake.len-1;i>0;i--)//画蛇身

{

snake.x[i]=snake.x[i-1];

snake.y[i]=snake.y[i-1];

}

flag=0;

}

switch (keys)

{

case 75:

snake.x[0] -= 2;//往左

pre_key=keys;

break;

case 77:

snake.x[0] += 2;//往右

pre_key=keys;

break;

case 72:

snake.y[0]--;//往上

pre_key=keys;

break;

case 80:

snake.y[0]++;//往下

pre_key=keys;

break;

default:

keys=pre_key;

break;

}

//打印出蛇头

movefile(snake.x[0], snake.y[0]);

printf("◆");

//由于目前没有吃到食物,flag值为0

}

​ 前一个函数为键盘控制函数,用于读取键盘的键入情况,并记录在int key中,第二个函数用于处理第一个函数的结果,移动蛇头部的坐标以达到蛇移动的效果。

5、判断函数

int judge()

{

int i=0;//判断结果传递参数

if(snake.y[0]==0||snake.y[0]==maxheight-2)//蛇撞上上下边界视为失败

i=1;

if(snake.x[0]==0||snake.x[0]==54)//蛇撞上左后边界视为失败

i=1;

for(int j=1;j

{

if(snake.x[j]==snake.x[0]&&snake.y[j]==snake.y[0])//蛇头撞上自身身体视为失败

i=1;

}

return i;

}

使用int型变量i传递结果,蛇撞到上下界和自身算为失败。

6、双人模式与单人模式的不同

1、键盘函数(以左蛇的控制函数为例)

void keycontrl1()

{

if (GetAsyncKeyState(VK_UP))

{

if (snake1.key!= down)snake1.key= up;

}

else if (GetAsyncKeyState(VK_DOWN))

{

if (snake1.key!= up)snake1.key = down;

}

else if (GetAsyncKeyState(VK_RIGHT))

{

if (snake1.key!= left)snake1.key= right;

}

else if (GetAsyncKeyState(VK_LEFT))

{

if (snake1.key != right)snake1.key = left;

}

//若没有吃到食物,即flag=0,则在移动时抹去最后一位的字符

if(flag==0)

{

movefile(snake1.x[snake1.len-1],snake1.y[snake1.len-1]);

printf(" ");

for(int i=snake1.len-1;i>0;i--)//画蛇身

{

snake1.x[i]=snake1.x[i-1];

snake1.y[i]=snake1.y[i-1];

}

}

else if(flag==1)

{

movefile(snake1.x[snake1.len-2],snake1.y[snake1.len-2]);

printf(" ");

for(int i=snake1.len-1;i>0;i--)//画蛇身

{

snake1.x[i]=snake1.x[i-1];

snake1.y[i]=snake1.y[i-1];

}

flag=0;

}

switch (snake1.key)

{

case right:snake1.x[0] += 2; break;

case left:snake1.x[0]-= 2; break;

case up:snake1.y[0] -= 1; break;

case down:snake1.y[0] += 1; break;

}

//打印出蛇头

movefile(snake1.x[0], snake1.y[0]);

printf("◆");

movefile(81,31);

}

单人模式使用数字键码代表键盘键入的内容,双人模式直接使用虚拟键码控制,更加便捷与清楚。

2、判断函数

//判断是否结束

int judge2(){

int i=0;//判断结果传递参数

int k=0;

if(snake1.y[0]==0||snake1.y[0]==maxheight-2)//蛇撞上上下边界视为失败

i=1;

if(snake1.x[0]==0||snake1.x[0]==54)//蛇撞上左后边界视为失败

i=1;

for(int j=1;j

{

if(snake1.x[j]==snake1.x[0]&&snake1.y[j]==snake1.y[0])//蛇头撞上自身身体视为失败

i=1;

}

if(info1.score==maxscore) k=1;//分数达到上限结束

for(int j=1;j

{

if(snake1.x[j]==snake2.x[0]&&snake1.y[j]==snake2.y[0])//另一蛇头撞上自身身体视为失败

k=1;

}

if(snake2.y[0]==0||snake2.y[0]==maxheight-2)//蛇撞上上下边界视为失败

k=1;

if(snake2.x[0]==0||snake2.x[0]==54)//蛇撞上左后边界视为失败

k=1;

for(int j=1;j

{

if(snake2.x[j]==snake2.x[0]&&snake2.y[j]==snake2.y[0])//蛇头撞上自身身体视为失败

k=1;

}

for(int j=1;j

{

if(snake2.x[j]==snake1.x[0]&&snake2.y[j]==snake1.y[0])//另一蛇头撞上自身身体视为失败

i=1;

}

if(info2.score==maxscore) i=1;//分数达到上限结束

if(k==1&&i==1)

return 1;

else if(k==0&&i==1)

return 0;

else if(k==1&&i==0)

return -1;

else return 2;

除了碰撞的判定,还加入了分数上限的判定。

三、 难点与解决

​ 双人模式中两蛇的操作相互干扰:更换了键盘键入的读取形式后解决了该问题

四、 参考资料

[1]贪吃蛇算法:https://blog.csdn.net/zs120197/article/details/88420297?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

[2]窗口相关:https://blog.csdn.net/liluo_2951121599/article/details/66474233

五、完整代码

https://download.csdn.net/download/qzl19/12573923

本文地址:https://blog.csdn.net/qzl19/article/details/107112929

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/750218
推荐阅读
相关标签
  

闽ICP备14008679号