基本思路:
蛇每吃一个食物蛇身子就增加一格,用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语言
#include<stdio.h>#include<stdlib.h>
#include<Windows.h>
#include<conio.h>
#include<time.h>
char gamemap[20][40]//游戏地图大小 20*40
int score=0//当前分数
//记录蛇的结点
int x[800]//每个结点的行编号
int y[800]//每个结点的列编号
int len = 0//蛇的长度
//记录水果信息
int fx=0//食物的横坐标
int fy=0//食物的纵坐标
int fcount=0//食物的数目
//主要函数操作
void createfood()//生成食物
void PrintgameMap(int x[],int y[])//画游戏地图
void move(int x[],int y[])//移动蛇
int main()
{
srand(time(NULL))
//初始化蛇头和身体的位置,默认刚开始蛇长为2
x[len] = 9
y[len] = 9
len++
x[len] = 9
y[len] = 8
len++
createfood()
PrintgameMap(x,y)
move(x,y)
return 0
}
void createfood()
{
if(0==fcount)
{
int tfx=rand()%18+1
int tfy=rand()%38+1
int i,j
int have=0//为0表示食物不是食物的一部分
for(i=0i<leni++)
{
for(j=0j<lenj++)
{
if(x[i]==fx&&y[j]==fy)
{
have=1
break
}
else
{
have=0
}
}
if(1==have)//若为蛇的一部分,执行下一次循环
{
continue
}
else//否则生成新的水果
{
fcount++
fx=tfx
fy=tfy
break
}
}
}
}
//游戏地图
void PrintgameMap(int x[],int y[])
{
int snake = 0,food=0
int i, j
//画游戏地图,并画出蛇的初始位置
for (i = 0i <20i++)
{
for (j = 0j <40j++)
{
if (i == 0 &&j >= 1 &&j <= 38)
{
gamemap[i][j] = '='
}
else if (i == 19 &&j >= 1 &&j <= 38)
{
gamemap[i][j] = '='
}
else if (j == 0 || j == 39)
{
gamemap[i][j] = '#'
}
else
{
gamemap[i][j] = ' '
}
//判断蛇是否在当前位置
int k
for ( k = 0k <lenk++)
{
if (i == x[k]&&j == y[k])
{
snake = 1
break
}
else
{
snake = 0
}
}
{
if(fcount&&fx==i&&fy==j)
{
food=1
}
else
{
food=0
}
}
//若蛇在当前位置
if (1==snake )
{
printf("*")
}
else if(1==food)
{
printf("f")
}
//若蛇不在当前位置并且当前位置没有水果
else
{
printf("%c", gamemap[i][j])
}
}
printf("\n")
}
printf("score:%d",score)
}
//移动
void move(int x[],int y[])
{
char s
s=getch()
int move=0,beat=0
while (1)
{
int cx[800]
int cy[800]
memcpy(cx, x, sizeof(int)*len)
memcpy(cy, y, sizeof(int)*len)
//头
if (s=='w')
{
x[0]--
move=1
if(x[0]<=0)
{
printf("Game over\n")
break
}
}
else if (s=='s')
{
x[0]++
move=1
if(x[0]>=19)
{
printf("Game over\n")
break
}
}
else if (s=='a')
{
y[0] --
move=1
if(y[0]<=0)
{
printf("Game over\n")
break
}
}
else if (s=='d')
{
y[0]++
move=1
if(y[0]>=39)
{
printf("Game over\n")
break
}
}
//身体
int i
for ( i = 1i <leni++)
{
x[i] = cx[i - 1]
y[i] = cy[i - 1]
}
for(i=1i<leni++)//要是咬到了自己
{
if(x[0]==x[i]&&y[0]==y[i])
{
beat=1
}
else
{
beat=0
}
}
if(1==beat)
{
printf("Game over\n")
break
}
if(1==move)
{
if(fcount&&x[0]==fx&&y[0]==fy)//如果吃到了果子
{
//拷贝当前蛇头地址到第二个结点
memcpy(x+1,cx,sizeof(int)*len)
memcpy(y+1,cy,sizeof(int)*len)
len++
fcount--
fx=0
fy=0
score++
createfood()
}
Sleep(70)
system("cls")
PrintgameMap( x, y)
}
else
continue
if(kbhit())//判断是否按下按键
{
s=getch()
}
}
}
#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