基本思路:
蛇每吃一个食物蛇身子就增加一格,用UP, DOWN, LEFT, RIGHT控制蛇头的运动,而蛇身子跟着蛇头走,每后一格蛇身子下一步走到上一格蛇身子的位置,以此类推。
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#define BEG_X 2
#define BEG_Y 1
#define WID 20
#define HEI 20
HANDLE hout
typedef enum {UP, DOWN, LEFT, RIGHT} DIR
typedef struct Snake_body
{
COORD pos//蛇身的位置
struct Snake_body *next//下一个蛇身
struct Snake_body *prev//前一个蛇身
}SNAKE, *PSNAKE
PSNAKE head = NULL//蛇头
PSNAKE tail = NULL//蛇尾
//画游戏边框的函数
void DrawBorder()
{
int i, j
COORD pos = {BEG_X, BEG_Y}
for(i = 0i <HEI++i)
{
SetConsoleCursorPosition(hout, pos)
for(j = 0j <WID++j)
{
if(i == 0)//第一行
{
if(j == 0)
printf("┏")
else if(j == WID - 1)
printf("┓")
else
printf("━")
}
else if(i == HEI - 1)//最后一行
{
if(j == 0)
printf("┗")
else if(j == WID - 1)
printf("┛")
else
printf("━")
}
else if(j == 0 || j == WID - 1)//第一列或最后一列
printf("┃")
else
printf(" ")
}
++pos.Y
}
}
//添加蛇身的函数
void AddBody(COORD pos)
{
PSNAKE pnew = (PSNAKE)calloc(1, sizeof(SNAKE))
pnew->pos = pos
if(!head)
{
head = tail = pnew
}
else
{
pnew->next = head//新创建蛇身的next指向原先的蛇头
head->prev = pnew//原先的蛇头的prev指向新创建的蛇身
head = pnew//把新创建的蛇身作为新的蛇头
}
SetConsoleCursorPosition(hout, head->pos)
printf("◎")
}
//蛇身移动的函数
void MoveBody(DIR dir)
{
PSNAKE ptmp
COORD pos = head->pos
switch(dir)
{
case UP:
if(head->pos.Y >BEG_Y + 1)
--pos.Y
else
return
break
case DOWN:
if(head->pos.Y <BEG_Y + HEI - 2)
++pos.Y
else
return
break
case LEFT:
if(head->pos.X >BEG_X + 2)
pos.X -= 2
else
return
break
case RIGHT:
if(head->pos.X <BEG_X + (WID - 2) * 2)
pos.X += 2
else
return
break
}
AddBody(pos)//添加了一个新的蛇头
ptmp = tail//保存当前的蛇尾
tail = tail->prev
if(tail)
tail->next = NULL
SetConsoleCursorPosition(hout, ptmp->pos)
printf(" ")
free(ptmp)
}
int main()
{
int ctrl
DIR dir = RIGHT//初始蛇的方向是向右的
COORD pos = {BEG_X + 2, BEG_Y + HEI / 2}
system("color 0E")
system("mode con cols=90 lines=30")
hout = GetStdHandle(STD_OUTPUT_HANDLE)
printf(" ------------贪吃蛇的移动------------")
DrawBorder()
//自定义几个蛇的身体
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
//控制蛇的移动
while(ctrl = getch())
{
switch(ctrl)
{
case 'w':
if(dir == DOWN)
continue
dir = UP
break
case 's':
if(dir == UP)
continue
dir = DOWN
break
case 'a':
if(dir == RIGHT)
continue
dir = LEFT
break
case 'd':
if(dir == LEFT)
continue
dir = RIGHT
break
case 'q':
return 0
}
MoveBody(dir)
}
return 0
}
扩展资料:
实现逻辑
1,可以设置光标,就能实现制定位置打印制定符号。
2,涉及一个结构体,包含两个元素坐标元素和一个结构体指针。
3,结构体串联形成链表,遍历获取成员坐标,打印符号得到蛇身。
4,不断的加头,去尾,重新遍历坐标,再打印形成蛇的移动。
5,食物产生的位置判定,不能越界,也不能与蛇身体重合。
6,蛇的转向判定,一条规则,不允许倒退。
7,转向的实现,跟行进方向决定新的关节坐标(当前头的上下左右)
8,死亡检测,是否头节点坐标是否与墙壁重合,是否与身体其他关节重合。
9,加速减速,设置刷新休眠时间实现。
参考资料来源:百度百科-C语言
//******友情提示:如想速度快点,请改小_sleep(500)函数中参数*****
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <time.h>
const int H = 8 //地图的高
const int L = 16 //地图的长
char GameMap[H][L] //游戏地图
int key //按键保存
int sum = 1, over = 0 //蛇的长度, 游戏结束(自吃或碰墙)
int dx[4] = {0, 0, -1, 1} //左、右、上、下的方向
int dy[4] = {-1, 1, 0, 0}
struct Snake //蛇的每个节点的数据类型
{
int x, y //左边位置
int now //保存当前节点的方向, 0,1,2,3分别为左右上下
}Snake[H*L]
const char Shead = '@' //蛇头
const char Sbody = '#' //蛇身
const char Sfood = '*' //食物
const char Snode = '.' //'.'在地图上标示为空
void Initial() //地图的初始化
void Create_Food() //在地图上随机产生食物
void Show() //刷新显示地图
void Button() //取出按键,并判断方向
void Move() //蛇的移动
void Check_Border() //检查蛇头是否越界
void Check_Head(int x, int y) //检查蛇头移动后的位置情况
int main()
{
Initial()
Show()
return 0
}
void Initial() //地图的初始化
{
int i, j
int hx, hy
system("title 贪吃蛇") //控制台的标题
memset(GameMap, '.', sizeof(GameMap)) //初始化地图全部为空'.'
system("cls")
srand(time(0)) //随机种子
hx = rand()%H //产生蛇头
hy = rand()%L
GameMap[hx][hy] = Shead
Snake[0].x = hx Snake[0].y = hy
Snake[0].now = -1
Create_Food() //随机产生食物
for(i = 0 i < H i++) //地图显示
{
for(j = 0 j < L j++)
printf("%c", GameMap[i][j])
printf("\n")
}
printf("\n小小C语言贪吃蛇\n")
printf("按任意方向键开始游戏\n")
getch() //先接受一个按键,使蛇开始往该方向走
Button() //取出按键,并判断方向
}
void Create_Food() //在地图上随机产生食物
{
int fx, fy
while(1)
{
fx = rand()%H
fy = rand()%L
if(GameMap[fx][fy] == '.') //不能出现在蛇所占有的位置
{
GameMap[fx][fy] = Sfood
break
}
}
}
void Show() //刷新显示地图
{
int i, j
while(1)
{
_sleep(500) //延迟半秒(1000为1s),即每半秒刷新一次地图
Button() //先判断按键在移动
Move()
if(over) //自吃或碰墙即游戏结束
{
printf("\n**游戏结束**\n")
printf(" >_<\n")
getchar()
break
}
system("cls") //清空地图再显示刷新吼的地图
for(i = 0 i < H i++)
{
for(j = 0 j < L j++)
printf("%c", GameMap[i][j])
printf("\n")
}
printf("\n小小C语言贪吃蛇\n")
printf("按任意方向键开始游戏\n")
}
}
void Button() //取出按键,并判断方向
{
if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
{
while(kbhit() != 0) //可能存在多个按键,要全部取完,以最后一个为主
key = getch() //将按键从控制台中取出并保存到key中
switch(key)
{ //左
case 75: Snake[0].now = 0
break
//右
case 77: Snake[0].now = 1
break
//上
case 72: Snake[0].now = 2
break
//下
case 80: Snake[0].now = 3
break
}
}
}
void Move() //蛇的移动
{
int i, x, y
int t = sum //保存当前蛇的长度
//记录当前蛇头的位置,并设置为空,蛇头先移动
x = Snake[0].x y = Snake[0].y GameMap[x][y] = '.'
Snake[0].x = Snake[0].x + dx[ Snake[0].now ]
Snake[0].y = Snake[0].y + dy[ Snake[0].now ]
Check_Border() //蛇头是否越界
Check_Head(x, y) //蛇头移动后的位置情况,参数为: 蛇头的开始位置
if(sum == t) //未吃到食物即蛇身移动哦
for(i = 1 i < sum i++) //要从蛇尾节点向前移动哦,前一个节点作为参照
{
if(i == 1) //尾节点设置为空再移动
GameMap[ Snake[i].x ][ Snake[i].y ] = '.'
if(i == sum-1) //为蛇头后面的蛇身节点,特殊处理
{
Snake[i].x = x
Snake[i].y = y
Snake[i].now = Snake[0].now
}
else //其他蛇身即走到前一个蛇身位置
{
Snake[i].x = Snake[i+1].x
Snake[i].y = Snake[i+1].y
Snake[i].now = Snake[i+1].now
}
GameMap[ Snake[i].x ][ Snake[i].y ] = '#' //移动后要置为'#'蛇身
}
}
void Check_Border() //检查蛇头是否越界
{
if(Snake[0].x < 0 || Snake[0].x >= H
|| Snake[0].y < 0 || Snake[0].y >= L)
over = 1
}
void Check_Head(int x, int y) //检查蛇头移动后的位置情况
{
if(GameMap[ Snake[0].x ][ Snake[0].y ] == '.') //为空
GameMap[ Snake[0].x ][ Snake[0].y ] = '@'
else
if(GameMap[ Snake[0].x ][ Snake[0].y ] == '*') //为食物
{
GameMap[ Snake[0].x ][ Snake[0].y ] = '@'
Snake[sum].x = x //新增加的蛇身为蛇头后面的那个
Snake[sum].y = y
Snake[sum].now = Snake[0].now
GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#'
sum++
Create_Food() //食物吃完了马上再产生一个食物
}
else
over = 1
}
#include<conio.h>#include<graphics.h>#include<time.h>#include<string.h>#include<malloc.h>#include<stdio.h>int grade=5,point=0,life=3void set(),menu(),move_head(),move_body(),move(),init_insect(),left(),upon(),right(),down(),init_graph(),food_f(),ahead(),crate()struct bug { int xint ystruct bug *laststruct bug *next}struct fd { int xint yint judge}food={0,0,0}struct bug *head_f=NULL,*head_l,*p1=NULL,*p2=NULLvoid main() { char chinitgraph(800,600)set()init_insect()while(1) { food_f()Sleep(grade*10)setcolor(BLACK)circle(head_l->x,head_l->y,2)setcolor(WHITE)move_body()if(kbhit()) { ch=getch()if(ch==27) { ahead()set()} else if(ch==-32) { switch(getch()) { case 72:upon()breakcase 80:down()breakcase 75:left()breakcase 77:right()break} } else ahead()} else { ahead()} if(head_f->x==food.x&&head_f->y==food.y) { Sleep(100)crate()food.judge=0point=point+(6-grade)*10if(food.x<30||food.y<30||food.x>570||food.y>570) life++menu()} if(head_f->x<5||head_f->x>595||head_f->y<5||head_f->y>595) { Sleep(1000)life--food.judge=0init_graph()init_insect()menu()} for(p1=head_f->nextp1!=NULLp1=p1->next) { if(head_f->x==p1->x&&head_f->y==p1->y) { Sleep(1000)life--food.judge=0init_graph()init_insect()menu()break} } if(life==0) { outtextxy(280,300,"游戏结束!")getch()return} move()}} void init_graph() { clearviewport()setlinestyle(PS_SOLID,1,5)rectangle(2,2,600,598)setlinestyle(PS_SOLID,1,1)} void set() { init_graph()outtextxy(640,50,"1、开始 / 返回")outtextxy(640,70,"2、退出")outtextxy(640,90,"3、难度")outtextxy(640,110,"4、重新开始")switch(getch()) { case '1': menu()setcolor(GREEN)circle(food.x,food.y,2)setcolor(WHITE)returncase '2': exit(0)breakcase '3': outtextxy(700,90,":1 2 3 4 5")grade=getch()-48set()breakcase '4': food.judge=0,grade=5point=0life=3init_insect()menu()breakdefault: outtextxy(250,300,"输入错误!")set()break} } void menu() { char str[20],str1[]={"分数:"},str2[]={"难度:"},str3[]={"生命值:"}init_graph()sprintf(str,"%d",point)strcat(str1,str)outtextxy(640,50,str1)sprintf(str,"%d",grade)strcat(str2,str)outtextxy(640,70,str2)sprintf(str,"%d",life)strcat(str3,str)outtextxy(640,90,str3)outtextxy(640,110,"设置:ESC")} void init_insect() { head_f=(struct bug *)malloc(sizeof(struct bug))head_f->last=NULLhead_f->x=300head_f->y=300p2=head_f->next=p1=(struct bug *)malloc(sizeof(struct bug))p1->last=head_fp1->x=295p1->y=300p1=p1->next=(struct bug *)malloc(sizeof(struct bug))p1->next=NULLp1->x=290p1->y=300p1->last=p2head_l=p1} void move() { for(p1=head_fp1!=NULLp1=p1->next) { circle(p1->x,p1->y,2)} } void move_head() { } void move_body() { for(p1=head_l,p2=p1->lastp2!=NULLp1=p2,p2=p2->last) { p1->x=p2->xp1->y=p2->y} } void ahead() { p1=head_fp2=p1->nextp2=p2->nextif(p1->x==p2->x) { if(p1->y>p2->y) head_f->y+=5else head_f->y-=5} else { if(p1->x>p2->x) { head_f->x+=5} else head_f->x-=5} } void upon() { p1=head_f->nextp1=p1->nexthead_f->y-=5if(p1->x==head_f->x&&p1->y==head_f->y) { head_f->y+=5ahead()} } void down() { p1=head_f->nextp1=p1->nexthead_f->y+=5if(p1->x==head_f->x&&p1->y==head_f->y) { head_f->y-=5ahead()} } void left() { p1=head_f->nextp1=p1->nexthead_f->x-=5if(p1->x==head_f->x&&p1->y==head_f->y) { head_f->x+=5ahead()} } void right() { p1=head_f->nextp1=p1->nexthead_f->x+=5if(p1->x==head_f->x&&p1->y==head_f->y) { head_f->x-=5ahead()} } void food_f() { if(!food.judge) { food.x=(rand()%117+1)*5food.y=(rand()%117+1)*5food.judge=1if(food.x<30||food.y<30||food.x>570||food.y>570) { setcolor(RED)circle(f