贪吃蛇

来源:互联网 发布:linux listen函数 编辑:程序博客网 时间:2024/03/29 22:31

#include<windows.h>
#include<iostream>
#include<time.h>
using namespace std;

//------豆的 结构体------
typedef struct BeanNode
{
 int x;
 int y;
}BeanNode;

//------蛇的 结构体------
typedef struct snakeNode
{
 int x;
 int y;
 struct snakeNode* pNext;
}snakeNode;

//------蛇的全局变量 常量 宏 枚举------

enum dir{UP,DOWN,LEFT,RIGHT};   //定义方向

dir ditcetion=UP;   //默认初始方向是向上

const int LEN=30;   //画蛇 画豆的 长宽高!

int isEat=FALSE;    //是否吃豆
int isDead=FALSE;   //是否死了

snakeNode *snakeHead=NULL;   //蛇头
snakeNode *snakeTail;        //蛇尾

BeanNode bean;      //豆
int snackLenght;    //蛇的长度

//------蛇的 函数声明------

//初始化游戏
void createGame();

//画屏幕
void drawGame();

//蛇移动
void snakeMove();

//出豆
void createBean();

//吃豆
void eatBean();

//蛇死
void snakeDead();

//------应用程序的全局变量------
char className[20]="clever";    //设计出窗口图纸的名字
HDC hdc;              //设备的句柄
HINSTANCE hIns;       //应用程序的实例句柄
HWND Hwnd;            //窗口句柄
HBRUSH newHbrush;
HBRUSH oldHbrush;


//应用程序的函数声明
LRESULT CALLBACK wndProc(HWND hWnd,UINT message,WPARAM wParm,LPARAM lParam);  //回调函数

//应用程序的主函数
int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
 WNDCLASSEX wndClass;
 HWND hWnd;
 MSG msg;
 hIns=hInstance;

 wndClass.cbClsExtra=0;
 wndClass.cbSize=sizeof(WNDCLASSEX);
 wndClass.cbWndExtra=0;
 wndClass.hbrBackground=(HBRUSH)COLOR_WINDOW;
 wndClass.hCursor=NULL;
 wndClass.hIcon=NULL;
 wndClass.hIconSm=NULL;
 wndClass.hInstance=hInstance;
 wndClass.lpfnWndProc=wndProc;
 wndClass.lpszClassName=className;
 wndClass.lpszMenuName=NULL;
 wndClass.style=CS_VREDRAW|CS_HREDRAW;

 RegisterClassEx(&wndClass);

 hWnd=CreateWindow(className,"贪吃蛇",WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,400,100,600,600,NULL,NULL,hInstance,NULL);

 Hwnd=hWnd;

 if(!hWnd)
 {
  MessageBox(hWnd,"创建窗口没有成功!","ERROR!",MB_OK);
 }
 else
 {
  ShowWindow(hWnd,nShowCmd);
 }
 //================游戏初始化区==============
 createGame();   //初始化蛇
 createBean();   //初始化豆

 //================消息循环================
 while(GetMessage(&msg,NULL,0,0))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }

 return 0;
}

LRESULT CALLBACK wndProc(HWND hWnd,UINT message,WPARAM wParm,LPARAM lParam)
{
 switch(message)
 {
 case WM_PAINT:
  hdc=GetDC(hWnd);
  Rectangle(hdc,0,0,600,600);                   //铺平

  TextOut(hdc,240,200,"贪吃蛇游戏!",11);        //菜
  TextOut(hdc,240,350,"1. 按回车键开始",15);    //
  TextOut(hdc,240,390,"2. 按空格键暂停",15);    //单
  break; 
 case WM_DESTROY:
  ReleaseDC(hWnd,hdc);   //退出的时候 要释放 设备
  PostQuitMessage(0);
  break;
 case WM_KEYDOWN:
  {
   switch(wParm)
   {
   case VK_RETURN:   //按下回车 开始游戏
    SetTimer(hWnd,1,200,NULL);
    break;
    case VK_UP:       //向上走
    if(ditcetion!=DOWN)   //如果 蛇当前方向是向下 则不能下上走
    {
     ditcetion=UP;
    }
    break;
   case VK_DOWN:
    if(ditcetion!=UP)
    {
     ditcetion=DOWN;
    }
    break;
   case VK_LEFT:
    if(ditcetion!=RIGHT)
    {
     ditcetion=LEFT;
    }
    break;
   case VK_RIGHT:
    if(ditcetion!=LEFT)
    {
     ditcetion=RIGHT;
    }
    break;
   }
  } 
  break;
 case WM_TIMER:   //计时器
  {
   snakeMove();    //蛇移动
   drawGame();     //画屏幕
  }
  break;
 }
 return DefWindowProc(hWnd,message,wParm,lParam);
}
//----------蛇的函数体-------------

//初始化游戏
void createGame()
{
 snackLenght=4;    //初始化四节蛇
 for(int i=0;i<snackLenght;i++)
 {
  snakeNode *tempNode=(snakeNode*)malloc(sizeof(snakeNode));
  tempNode->x=300;
  tempNode->y=300+i*LEN;
  tempNode->pNext=NULL;
  if(!snakeHead)           //如果蛇头还灭有
  {
   snakeHead=tempNode;  //第一个初始化的节点 赋给蛇头 确定蛇头
  }
  else
  {
   snakeTail->pNext=tempNode;
  }
  snakeTail=tempNode;      //确定尾节点
 }
}

//画屏幕
void drawGame()
{
 ReleaseDC(Hwnd,hdc);
 
 //铺屏
 hdc=GetDC(Hwnd);
 Rectangle(hdc,0,0,600,600);
 ReleaseDC(Hwnd,hdc);

 //画蛇
 hdc=GetDC(Hwnd);
 newHbrush=CreateSolidBrush(RGB(150,130,78));
 oldHbrush=(HBRUSH)SelectObject(hdc,newHbrush);
 snakeNode *tempHead=snakeHead;
 while(tempHead)    //循环蛇 画蛇
 {
  Rectangle(hdc,tempHead->x,tempHead->y,tempHead->x+LEN,tempHead->y+LEN);
  tempHead=tempHead->pNext;
 }
 DeleteObject(oldHbrush);
 ReleaseDC(Hwnd,hdc);

 //画豆
 hdc=GetDC(Hwnd);
 newHbrush=CreateSolidBrush(RGB(123,30,78));
 oldHbrush=(HBRUSH)SelectObject(hdc,newHbrush);

 if(isEat==TRUE)   //如果吃豆了 就从新 生成一个豆
 {
  createBean();
  isEat=FALSE;
  snackLenght++;
 }
 Ellipse(hdc,bean.x,bean.y,bean.x+LEN,bean.y+LEN);   //画豆
 DeleteObject(oldHbrush);
 ReleaseDC(Hwnd,hdc);

 //蛇挂没挂
 if(isDead==TRUE)  //如果蛇挂了 铺屏 打印 蛇死了 关掉计时器
 {
  hdc=GetDC(Hwnd);
  newHbrush=CreateSolidBrush(RGB(34,130,78));
  oldHbrush=(HBRUSH)SelectObject(hdc,newHbrush);
  
  Rectangle(hdc,0,0,600,600);
  TextOut(hdc,250,300,"GameOver!",9);
  KillTimer(Hwnd,1);  
  DeleteObject(oldHbrush);
  DeleteObject(oldHbrush);
  ReleaseDC(Hwnd,hdc);
 }
}

//蛇移动
void snakeMove()
{
 snakeNode *tempNode=(snakeNode*)malloc(sizeof(snakeNode));   //创建一个新的节点 储存蛇要移动的那个坐标
 snakeNode *tempHead=snakeHead;    //弄一个临时的 头结点 为了删除尾巴用
 switch(ditcetion)
 {
 case UP:       //如果向上 就将蛇头上面那个节点的坐标 储存到新申请的那个节点
  {
   tempNode->x=snakeHead->x;
   tempNode->y=snakeHead->y-LEN;
   tempNode->pNext=snakeHead;
  }
  break;
 case DOWN:     //如果向下 就将蛇头下面那个节点的坐标 储存到新申请的那个节点
  {
   tempNode->x=snakeHead->x;
   tempNode->y=snakeHead->y+LEN;
   tempNode->pNext=snakeHead;
  }
  break;
 case LEFT:     //如果向左 就将蛇头左面那个节点的坐标 储存到新申请的那个节点
  {
   tempNode->x=snakeHead->x-LEN;
   tempNode->y=snakeHead->y;
   tempNode->pNext=snakeHead;
  }
  break;  
 case RIGHT:    //如果向右 就将蛇头右面那个节点的坐标 储存到新申请的那个节点
  {
   tempNode->x=snakeHead->x+LEN;
   tempNode->y=snakeHead->y;
   tempNode->pNext=snakeHead;
  }
  
 }

 snakeHead=tempNode;   //最后 将头结点 指向新的节点 (头结点 有新的值了 蛇 就开始移动了)

 //判断是否吃豆
 eatBean();
 //如果没有吃豆
 if(FALSE==isEat)
 { 
  int i=1;
  while(i<snackLenght-1)
  {
   tempHead=tempHead->pNext;
   i++;
  }
  free(snakeTail);
  snakeTail=tempHead;
  tempHead->pNext=NULL;
 }
 //如果吃豆了 就不删除节点了

 //判断是否撞车了
 snakeDead();
}

//出豆
void createBean()
{
 srand((unsigned)time(NULL));  //用随机数 生成一个豆
 bean.x=rand()%20*LEN;    //这个屏幕横着 最多可以有20个豆
 bean.y=rand()%20*LEN;    //这个屏幕竖着 最多可以有20个豆
}
//吃豆
void eatBean()
{
 if((bean.x==snakeHead->x)&&(bean.y==snakeHead->y))  //如果蛇头和豆重合了 就说明 吃豆了 isEat=TRUE
 {
  isEat=TRUE;
 }
}

//蛇死
void snakeDead()
{
 //撞墙死
 if(((snakeHead->x)>570)||((snakeHead->y)>570)||(snakeHead->x<0)||(snakeHead->y<0))//如果蛇头和墙重合了 就说明 蛇死了 isDead=TRUE
 {
  isDead=TRUE;
 }
 
 //撞身上死

 snakeNode *tempHead=snakeHead;   //弄一个临时的蛇头
 tempHead=tempHead->pNext;        //将他指向第二个节点

 while(tempHead)   //从第二个节点循环蛇
 {
  if((snakeHead->x==tempHead->x)&&(snakeHead->y==tempHead->y))   //如果蛇头 和蛇身的坐标重合了 那么蛇自己就把自己干掉了 isDead=TRUE
  {
   isDead=TRUE;
   break;
  }
  tempHead=tempHead->pNext;
 }
}


 

0 0
原创粉丝点击