贪食蛇的程序


无聊,分析了一个用C语言写的贪食蛇的程序。

写的非常简练,就是函数的名字起得不是很好。


#include <stdio.h>
#include <windows.h>

#define KUAN 20         //地图的大小
int iz[KUAN][KUAN];		//地图

struct _JieDian            //蛇的结点位置,使用链表结构来存储蛇身上各结点的位置
{
    _JieDian *pNext;       //下一个结点
    POINT pt;              //在地图中的位置
};

POINT ptShiWu;						//食物的位置

struct _She  
{
    _JieDian *SheTou;           //蛇头
    _JieDian *SheWei;		    //蛇尾
    int iFangXiang;              //移动方向
}She;                           //蛇的结构体

//初始化函数,用来初始化蛇的位置和移动方向
//以及随机产生食物的位置
void ChuShiHua()             //在Main中调用
{
    She.SheTou=new _JieDian;   //创建蛇头
    She.SheTou->pNext=NULL;    //初始蛇没有身体,只有一个蛇头结点
    She.SheTou->pt.x=6;        //初始化蛇头的位置x,y
    She.SheTou->pt.y=6;
    She.SheWei=She.SheTou;     //初始化蛇尾=蛇头,说明蛇还没有身体
    She.iFangXiang=0;          //初始化方向
    ptShiWu.x=rand()%20;            //随机产生食物的位置 
    ptShiWu.y=rand()%20;			//随机产生食物的位置 
    iz[She.SheTou->pt.y][She.SheTou->pt.x]=1;   //在地图上标记1,表示蛇头,用于后面的显示
    iz[ptShiWu.y][ptShiWu.x]=2;					//在地图上标记2,表示食物,用于后面的显示
}

void pr()                  //在Move中调用,pr是print的缩写,用来画图的
{
    printf("\n\n");           //两行空白
    for (int i=0;i<KUAN;i++)
    {
        printf("\t\t");          //两个制表符
        for (int j=0;j<KUAN;j++)
        {
			//地图中存0表示空白█,2表示食物☆,1表示蛇□
            printf(iz[i][j]==0?"█":iz[i][j]==2?"☆":"□");        //画地图,有食物,蛇和空白
        }
        printf("\n");			//画完了一行
    }
}

// 蛇吃食物函数
// 需要增加蛇身,重新随机生成食物
void SheChiShi()               //在Move中调用,  
{
    if(iz[She.SheWei->pt.y][She.SheWei->pt.x]!=2)  //蛇尾的位置不是食物的位置则返回
		return;
    _JieDian *p=new _JieDian;        //创建一个蛇身结点
    p->pNext=NULL;                    //下一结点为空
    p->pt=ptShiWu;                    //在食物的位置
    switch(She.iFangXiang)            //蛇的移动方向,根据移动方向来改变位置
    {
    case 1:p->pt.y--;break;          //上移一个
    case 2:p->pt.x--;break;          //左移一个
    case 3:p->pt.x++;break;          //右移一个
    case 4:p->pt.y++;break;          //下移一个
    }
    iz[p->pt.y][p->pt.x]=1;          //标记蛇头的新位置
    She.SheWei->pNext=p;             //加入蛇的尾部
    She.SheWei=p;                    //作为新的蛇尾
    iz[ptShiWu.y][ptShiWu.x]=1;      //食物的位置变成了蛇的身体
    ptShiWu.x=rand()%KUAN;           //生成新的食物位置
    ptShiWu.y=rand()%KUAN;
    iz[ptShiWu.y][ptShiWu.x]=2;      //在地图上标记食物的位置
}

//蛇的移动
//这里的蛇头其实是链表的头部,实际是蛇的尾部,链表是从蛇的尾部指向蛇头部的
void Move()               //在Main中调用
{
    _JieDian *p1=She.SheTou;							//保存蛇链表头结点
    if(iz[She.SheTou->pt.y][She.SheTou->pt.x]==1 )      //如果头结点的位置为1,则变成0,表示蛇移走了
        iz[She.SheTou->pt.y][She.SheTou->pt.x]=0;
    She.SheTou->pt=She.SheWei->pt;                  //头结点位置指向链表尾,这是真的蛇头位置                
	switch(She.iFangXiang)                          //蛇的移动方向,改变头结点位置
    {
    case 1:She.SheTou->pt.y=(She.SheWei->pt.y+KUAN-1)%KUAN;break;     //上y-1
    case 2:She.SheTou->pt.x=(She.SheWei->pt.x+KUAN-1)%KUAN;break;     //左x-1
    case 3:She.SheTou->pt.x=(She.SheWei->pt.x+1)%KUAN;break;		  //右x+1
    case 4:She.SheTou->pt.y=(She.SheWei->pt.y+1)%KUAN;break;		  //下y-1
    }
    She.SheWei->pNext=She.SheTou;               //将新走的一步结点加入链表尾部
    She.SheWei=She.SheTou;                      //产生新的链表尾部
    if(She.SheTou->pNext!=NULL)                 
		She.SheTou=She.SheTou->pNext;             //重新指回链表头部
    p1->pNext=NULL;									//链表尾的指针清空                
    if(iz[She.SheWei->pt.y][She.SheWei->pt.x]==0)   //地图上添加蛇链表尾的位置,也就是新走的一步产生的蛇的身体
		iz[She.SheWei->pt.y][She.SheWei->pt.x]=1;
    SheChiShi();                                    //蛇吃食物
    pr();                                           //打印地图
}

void main()
{
    ChuShiHua();									//初始化
    while (1)
    {
		//下面函数的参数参考:http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
        if(GetAsyncKeyState(87)&0x8000)She.iFangXiang=1;            //W键,蛇向上移动
        else if(GetAsyncKeyState(65)&0x8000)She.iFangXiang=2;       //A键,蛇向左移动
        else if(GetAsyncKeyState(68)&0x8000)She.iFangXiang=3;       //D键,蛇向右移动
        else if(GetAsyncKeyState(83)&0x8000)She.iFangXiang=4;       //S键,蛇向下移动
        system("cls");                   //清屏
        Move();                          //移动蛇
        Sleep(60);                       //挂起60ms
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值