贪吃蛇

dark_ice_rain 2011-01-26 09:34:10

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<windows.h>
#define HEAD 300
#define FOOD 400
/*-------------欢迎词神马的-------------------*/
void welc()
{
printf("\n\n\n\n\n\n\t\t\t欢迎来到xiao_D贪吃蛇\n\n");
printf("\t\t此游戏用键盘的方向键控制即可。若想退出请按Esc建。\n");
printf("\n\t\t\t相反的方向的话是暂停。\n");
printf("\n\t\t\t请按任意键进入游戏。");
getch();
}
/*--------------------------------------------*/
/*------------人工画图程序--------------------*/
void drawpt(int a,int x,int y)
{

if(x==0)
{
printf("\t\t");
return ;
}
if(y==0)
{ printf("\t\t\t");
return ;
}
if(x==16)
{
printf("\n");
return ;
}
if(y==16)
{
printf("\t\t");
}
if(x>0&&x<16&&y>0&&y<16)
{
if(a==0)
printf("█");
else printf("□");
return ;
}

}

void draw(int (*sna)[17])
{
int i,j;
system("cls");
for(i=0;i<17;i++)
{
for(j=0;j<17;j++)
{
drawpt(sna[i][j],j,i);
}
}
}
/*-----------------------------------------------*/

/*---------------取随机数,出现食物用------------*/
int randno()
{
srand(time(NULL));
return rand()%15+1;
}
/*-----------------------------------------------*/
/*----------判断游戏是否结束---------------------*/
bool judgeGO(int (*sna)[17])
{
int x,y,i=0,max=0,count=0;
for(x=0,y=0;y<17;y++)
if(sna[x][y]==HEAD)//判断头部是否在最外层的。
return false;
for(x=16,y=0;y<17;y++)
if(sna[x][y]==HEAD)
return false;
for(y=0,x=0;x<17;x++)
if(sna[x][y]==HEAD)
return false;
for(y=16,x=0;x<17;x++)
if(sna[x][y]==HEAD)
return false;
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(max<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
max=sna[x][y];//这个也是求头部之后的。
}
}
for(i=0;i<max;i++)
{
for(x=1;x<16;x++)
{
for(y=1;y<16;y++)
{
if(sna[x][y]==i+1)
count++;//这个判断想了好久的,,,
}
}
}
if(count!=max)//判断身体部分是否连续。
return false;

return true;
}
/*--------------------------------------------------*/
/*-------------游戏结束显示-------------------------*/
void gameover()
{
system("cls");
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t");
printf("游戏结束\n");
printf("\t\t\t");
printf("按Esc键退出,按任意键重新开始。\n");
}
/*-------------------------------------------------*/
/*全程标记法,从尾巴开始123456....HEAD,食物是FOOD。*/
void marksn()
{
void downmove(int (*sna)[17]);
void upmove(int (*sna)[17]);
void leftmove(int (*sna)[17]);
void rightmove(int (*sna)[17]);
int judgeF(int (*sna)[17],int keym);
int snake[17][17]={0};
/*------各种东西初始化-------------------*/
int x=1,y=7,key,key1;


snake[1][1]=1;
snake[1][2]=2;
snake[1][3]=3;

snake[2][3]=HEAD;

while(snake[x][y]!=0)
{
x=randno();
y=randno();
}
snake[x][y]=FOOD;
draw(snake);
/*---------------------------------------*/
/*--------控制的部分---------------------*/
while(judgeGO(snake))
{
key=getch();
switch(key){
case 72:

while(!kbhit()&&key1!=80&&judgeGO(snake))//这个函数kbhit()自己查一下吧~控制输入很好
{

if(judgeF(snake,key))
{
draw(snake);
Sleep(100);
continue;
}
upmove(snake);
draw(snake);
key1=key;//这里的key1是就来标记上一步的方向,这样相反的方向就暂停了。
Sleep(100);
}
break;
case 80:
while(!kbhit()&&key1!=72&&judgeGO(snake))
{
if(judgeF(snake,key))
{
draw(snake);
Sleep(100);
continue;
}
downmove(snake);
draw(snake);
key1=key;
Sleep(100);
}
break;
case 75:
while(!kbhit()&&key1!=77&&judgeGO(snake))
{
if(judgeF(snake,key))
{
draw(snake);
Sleep(100);
continue;
}
leftmove(snake);
draw(snake);
key1=key;
Sleep(100);
}
break;
case 77:
while(!kbhit()&&key1!=75&&judgeGO(snake))
{
if(judgeF(snake,key))
{
draw(snake);
Sleep(100);
continue;
}
rightmove(snake);
draw(snake);
key1=key;
Sleep(100);
}
break;
case 27:
exit(0);
default:
switch(key1){
case 72:
while(!kbhit()&&judgeGO(snake))
{
upmove(snake);
draw(snake);
}
break;
case 80:
while(!kbhit()&&judgeGO(snake))
{
downmove(snake);
draw(snake);
}
break;
case 75:
while(!kbhit()&&judgeGO(snake))
{
leftmove(snake);
draw(snake);
}
break;
case 77:
while(!kbhit()&&judgeGO(snake) )
{
rightmove(snake);
draw(snake);
}
break;
}

}
}
/*---------------------------------------------------*/
/*------------是否继续游戏---------------------------*/
gameover();
if(getch()==27)
exit(0);
else
{
marksn();
getch();
}
/*---------------------------------------------------*/
}
/*-------------------------------------------------*/
/*-----------上下左右移动神马的--------------------*/
void downmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;//前面已经说了,12345....标记法,减去1的话,除了头部以外其他的就移动了。
}
}

}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];//这个是求头部之后的值。
}
}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]==HEAD)
{
sna[x+1][y]=HEAD;//头部的移动,
sna[x][y]=mark+1;//头部的赋值。
return;
}
}
}
}

void upmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}

}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]==HEAD)
{
sna[x-1][y]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}

void leftmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}

}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]==HEAD)
{
sna[x][y-1]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}

void rightmove(int (*sna)[17])
{
int x=0,y=0,mark=0;
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]!=0&&sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
{
sna[x][y]=sna[x][y]-1;
}
}

}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]==HEAD)
{
sna[x][y+1]=HEAD;
sna[x][y]=mark+1;
return;
}
}
}
}

int judgeF(int (*sna)[17],int keym)
{
int randno();
int x,y,mark=0,i=randno(),j=randno();
for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(mark<sna[x][y])
if(sna[x][y]!=HEAD&&sna[x][y]!=FOOD)
mark=sna[x][y];
}
}

for(x=0;x<16;x++)
{
for(y=0;y<16;y++)
{
if(sna[x][y]==HEAD)
{
if(sna[x-1][y]==FOOD&&keym==72)
{
sna[x-1][y]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x+1][y]==FOOD&&keym==80)
{
sna[x+1][y]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x][y+1]==FOOD&&keym==77)
{
sna[x][y+1]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
if(sna[x][y-1]==FOOD&&keym==75)
{
sna[x][y-1]=HEAD;
sna[x][y]=mark+1;
while(sna[i][j]!=0)
{
i=randno();
j=randno();
}
sna[i][j]=FOOD;
return 1;
}
}
}
}
return 0;
}
/*------------------------------------------------------*/
/*----------主函数没什么内容----------------------------*/
int main(void)
{
welc();
marksn();
return 0;
}

...全文
1051 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
dark_ice_rain 2011-01-30
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 ustcdiracsea 的回复:]
别的不说,C里面有bool类型吗?学C语言一定要注意细节
[/Quote]
额。。。那个啥我编译了之后能玩的。
如果不行了话,自己稍微改改bool也可以的,直接改成int 返回0和1就可以了。。。
游戏在vc6.0下编译通过。。。
jojofans1314 2011-01-30
  • 打赏
  • 举报
回复
别的不说,C里面有bool类型吗?学C语言一定要注意细节
goolloo 2011-01-30
  • 打赏
  • 举报
回复
我是新手。。。用vc6和turbo c++ 3的。。。两个都有error,为什么啊?
dark_ice_rain 2011-01-30
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 snser 的回复:]
[/Quote]那是当然的,关键是如何实现。
只改变一个位置的图标。
snser 2011-01-29
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 dark_ice_rain 的回复:]

引用 31 楼 diamont1001 的回复:
闪屏问题解决了吗

没,,,api什么的,,,压力太大了。。。
[/Quote]
我试了在win7下闪,楼主的贪吃蛇在xp下闪吗?
我以前写的俄罗斯方块只在win7下闪
尽量减少每次擦除的内容应该有助于改善闪屏吧
yql0105 2011-01-29
  • 打赏
  • 举报
回复
閃的厲害...
不過LZ更厲害...
dark_ice_rain 2011-01-29
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 diamont1001 的回复:]
闪屏问题解决了吗
[/Quote]
没,,,api什么的,,,压力太大了。。。
dark_ice_rain 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 snser 的回复:]
C/C++ code

int gotoxy(int x,int y) /*将光标定位到 (x,y)*/
{
COORD c;
c.X=x-1;
c.Y=y-1;
SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
[/Quote]原来这个函数这么用啊~~~以前群里的仁兄给了我一坨代码,,,叫我帮忙写五子棋。。。
我认为这个没什么用。直接卡擦了~
snser 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 xiepanqi 的回复:]

引用 25 楼 snser 的回复:
他输出的是中文
横坐标应该乘2
[/Quote]
是这样,我用的时候是单独考虑×2的,因为有时候打的是字符,比如在指定位置打印提示信息
谢攀琪 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 snser 的回复:]
C/C++ code

int gotoxy(int x,int y) /*将光标定位到 (x,y)*/
{
COORD c;
c.X=x-1;
c.Y=y-1;
SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
[/Quote]
他输出的是中文
横坐标应该乘2
dark_ice_rain 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 xiepanqi 的回复:]
引用 21 楼 dark_ice_rain 的回复:


循环队列不懂的话那你就把链表头尾相接试试,
在另外用两个指针分别表示头尾
[/Quote]
链表神马的也不知道如何实现,,,可以详解的话就好了
snser 2011-01-28
  • 打赏
  • 举报
回复

int gotoxy(int x,int y) /*将光标定位到 (x,y)*/
{
COORD c;
c.X=x-1;
c.Y=y-1;
SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
可乐崽 2011-01-28
  • 打赏
  • 举报
回复
闪屏问题解决了吗
AAA20090987 2011-01-28
  • 打赏
  • 举报
回复
如果可以的话,LZ去学一下数据结构吧,毕竟这是基本功

附:我写的贪吃蛇
http://topic.csdn.net/u/20101001/01/2280b2dd-1446-439d-b1f8-cdd9db1fd615_5.html
yellowcath 2011-01-28
  • 打赏
  • 举报
回复
还在慢慢学基础,啥时候自己才能也整一条贪吃的蛇
qq120848369 2011-01-27
  • 打赏
  • 举报
回复
还可以再给结点加一个域:当前移动方向direction。

这样就不必每次移动一步前判断往哪个方向移动才能直线逼近top了,一直到top移出队列以后,可以更新根据新的top

更新direction了。
qq120848369 2011-01-27
  • 打赏
  • 举报
回复
没写过,自己的想法是双向链表来做,情况没有那么复杂,具有统一性。

每个结点里有一个目标队列,里边记录头部已经拐过而自己还没有到达的拐点。

每次头部拐弯,那么给链表里所有结点的目标队列push这个拐点。之后,链表内每个结点根据自己目标队里的top

做单方向平移一次,并判断是否到达top拐点,如果到达了,则pop。

思路很简单,做法很幼稚,代码没几行。
谢攀琪 2011-01-27
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 dark_ice_rain 的回复:]
[/Quote]

循环队列不懂的话那你就把链表头尾相接试试,
在另外用两个指针分别表示头尾
qq120848369 2011-01-27
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 aaa20090987 的回复:]

引用 15 楼 dark_ice_rain 的回复:

引用 13 楼 aaa20090987 的回复:
不过我不懂win32 API, 只能帮顶了,呵呵
大哥看清楚点儿。。。没用到win32 api。。。


哦,不好意思
我一看见windows.h,就以为是win32了
[/Quote]

学习了,这个设计更帅.
zps007 2011-01-27
  • 打赏
  • 举报
回复
厉害啊。。。收藏了。有机会照着写一个。新手啊,以前用java写过一个。
加载更多回复(15)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧