#include<iostream.h>
#include<windows.h>
#include<stdlib.h>
#include"resource.h"
#define IDT_TIMER1 1001
#define HEIGHT 180
#define WIDTH 250
int random1=rand(),random2=rand();
int positionX=(random1%WIDTH)/11;//石块的X坐标
int positionY=(random2%HEIGHT)/11;//石块的Y坐标
char change ; //对同一行或列的判断和处理,不能返回行动
int count=0; //计分
int rate=70;
class point ////坐标类只是做为一个数据类型
{
public:
int x;
int y;
};
typedef point ElemType;
struct sNode
{
ElemType data;
sNode *next;
};
struct ListLK
{
sNode *head, *last;
};
ListLK a; //数据结构的核心,链表的头,也是所有设置的基础.
sNode snake; //设置第一个结点
char location='r'; //设置初始运动方向,右
void InitList(ListLK &HL,sNode &snake)//初始化蛇头和链表头,尾
{
HL.last=HL.head=&snake;
HL.last->next=NULL;
HL.last->data.x=5;
HL.last->data.y=5;
}
void OrderInsertList(ListLK &HL)//先设加入到蛇尾的下面
{
sNode *newp=new sNode;
if(HL.head==NULL)
{
newp->next=HL.head;
HL.head=newp;
HL.last=newp;
return;
}
sNode *q=HL.head;
while(q->next!=NULL)q=q->next;
newp->data.x=q->data.x;
newp->data.y=q->data.y+1;
newp->next=q->next;
q->next=newp;
HL.last=newp;
}
void move(ListLK &HL,int xx,int yy)//移动,后两个参数xx,yy是用来对后面对方向键的接收
{
sNode *q=HL.head;
while(q->next!=HL.last)q=q->next;
q->next=NULL;
HL.last->data.x=HL.head->data.x+xx;
HL.last->data.y=HL.head->data.y+yy;
HL.last->next=HL.head;
HL.head=HL.last;
HL.last=q;
}
void drowSnake(HWND hwnd,int &pX,int &pY)//进行窗口客户区的绘画
{
HDC hdc;
PAINTSTRUCT ps;
hdc = ::BeginPaint (hwnd, &ps) ;
HBRUSH hBrush=::CreateSolidBrush(RGB(0,0,0));
RECT rc;
//计分和静态文档
char sz[20],szl[20],szk[20];
::SetBkColor(hdc,RGB(0,0,255));
wsprintf(sz,"分数:%d",count*100);
::TextOut(hdc,WIDTH+15,10,sz,strlen(sz));
wsprintf(szl,"按F1中等 按F2快速 ");
::TextOut(hdc,WIDTH+15,40,szl,strlen(szl));
wsprintf(szk,"空格为停止 ");
::TextOut(hdc,WIDTH+15,70,szk,strlen(szk));
sNode *tp=a.head;
//画蛇
while(tp!=NULL)
{
rc.left=(tp->data.x)*11;
rc.right=rc.left+10;
rc.top=(tp->data.y)*11;
rc.bottom=rc.top+10;
::FillRect(hdc,&rc,hBrush);
tp=tp->next;
}
::DeleteObject(hBrush);
//重新画蛇头
HBRUSH phBrush=::CreateSolidBrush(RGB(255,0,0));
rc.left=(a.head->data.x)*11;
rc.right=rc.left+10;
rc.top=(a.head->data.y)*11;
rc.bottom=rc.top+10;
::FillRect(hdc,&rc,phBrush);
::DeleteObject(phBrush);
//画蛋
HBRUSH OhBrush=::CreateSolidBrush(RGB(255,248,95));
rc.left=pX*11;
rc.right=rc.left+10;
rc.top=pY*11;
rc.bottom=rc.top+10;
::FillRect(hdc,&rc,OhBrush);
//画边界
::MoveToEx(hdc,WIDTH+11,HEIGHT+15,NULL);
::LineTo(hdc,WIDTH+11,0);
::DeleteObject(OhBrush);
::EndPaint(hwnd, &ps);
}
bool DetectCollision(ListLK &HL)//检测是否吃到蛋
{
bool bCollision=true;//默认没有碰撞
if(positionX==(HL.head->data.x)&&positionY==(HL.head->data.y))
bCollision=false;
return bCollision;
}
bool DetectHitRect(ListLK &HL)//检测是否撞到边界或者撞到自身
{
bool bCollision=true;//默认没有碰撞
if(HL.head->data.x<0||(HL.head->data.x)*11>WIDTH||HL.head->data.y<0||(HL.head->data.y)*11>HEIGHT)
bCollision=false;
for(sNode *p=HL.head->next;p->next!=NULL;p=p->next)
if(p->data.x==HL.head->data.x&&p->data.y==HL.head->data.y)bCollision=false;
return bCollision;
}
// 窗口函数的函数原形
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainWClass";
WNDCLASSEX wndclass;
// 用描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); // 结构的大小
wndclass.style = CS_HREDRAW|CS_VREDRAW; // 指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针
wndclass.cbClsExtra = 0; // 没有额外的类内存
wndclass.cbWndExtra = 0; // 没有额外的窗口内存
wndclass.hInstance = hInstance; // 实例句柄
wndclass.hIcon = ::LoadIcon(hInstance,
(LPCTSTR)IDI_MAIN); // 使用预定义图标
wndclass.hCursor = ::LoadCursor(NULL,
IDC_ARROW); // 使用预定义的光标
wndclass.hbrBackground =(HBRUSH)(COLOR_3DFACE + 1); // 使用灰色背景画刷
wndclass.lpszMenuName = NULL; // 不指定菜单
wndclass.lpszClassName = szClassName ; // 窗口类的名称
wndclass.hIconSm =::LoadIcon(hInstance,
(LPCTSTR)IDI_MAIN); // 没有类的小图标
// 注册这个窗口类
::RegisterClassEx(&wndclass);
// 创建主窗口
HWND hwnd = ::CreateWindowEx(
0, // dwExStyle,扩展样式
szClassName, // lpClassName,类名
"snake_eggs", // lpWindowName,标题
WS_OVERLAPPEDWINDOW & (~WS_SIZEBOX) &(~WS_MAXIMIZEBOX),//WS_DISABLED , // dwStyle,窗口风格
300,//CW_USEDEFAULT, // X,初始 X 坐标
200,//CW_USEDEFAULT, // Y,初始 Y 坐标
WIDTH+150,//CW_USEDEFAULT, // nWidth,宽度
HEIGHT+42,//CW_USEDEFAULT, // nHeight,高度
NULL, // hWndParent,父窗口句柄
NULL, // hMenu,菜单句柄
hInstance, // hlnstance,程序实例句柄
NULL) ; // lpParam,用户数据
if(hwnd == NULL)
{
::MessageBox(NULL, "创建窗口出错!", "error", MB_OK);
return -1;
}
// 显示窗口,刷新窗口客户区
::ShowWindow(hwnd, nCmdShow);
::UpdateWindow(hwnd);
// 从消息堆中取出消息
MSG msg;
while(::GetMessage(&msg, NULL, 0, 0))
{
// 转化键盘消息
::TranslateMessage(&msg);
// 将消息发送到相应的窗口函数
::DispatchMessage(&msg);
}
// 当GetMessage返回0时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
InitList(a,snake);
OrderInsertList(a);
OrderInsertList(a);
break;
case WM_PAINT: // 窗口客户区需要重画
{
::SetTimer(hwnd,IDT_TIMER1,rate,NULL);
drowSnake(hwnd,positionX,positionY);
if(DetectCollision(a)==false) //发生吃蛋的时候增加个尾巴
{
positionX=(rand()%WIDTH)/11,positionY=(rand()%HEIGHT)/11;
::OrderInsertList(a);
count++;
}
if(::DetectHitRect(a)==false) //发生撞到边界的时候停止
{
::KillTimer(hwnd,IDT_TIMER1);
int Result=::MessageBox(NULL, "you lost!", "message", MB_OK);
if(Result==IDOK)
::PostQuitMessage(0);
}
return 0;
}
case WM_TIMER:
{
if (location=='l')
{
if(change=='r')location='r';
else {move(a,-1,0);
change='l';}
}
else if (location=='r')
{
if(change=='l')location='l';
else {move(a,1,0);
change='r';}
}
else if (location=='u')
{
if(change=='d')location='d';
else {move(a,0,-1);
change='u';}
}
else if(location=='d')
{
if(change=='u')location='u';
else {move(a,0,1);
change='d';}
}
::InvalidateRect(hwnd,NULL,true);
break;
}
case WM_KEYDOWN:
{
sNode *tp=a.head;
//if (bPause)
{
switch (LOWORD(wParam))
{
case VK_UP:
{
location='u';
break;
}
case VK_DOWN:
{
location='d';
break;
}
case VK_RIGHT:
{
location='r';
break;
}
case VK_LEFT:
{
location='l';
break;
}
case VK_SPACE:
{
location='1';
break;
}
case VK_F1:
{
rate=130;
break;
}
case VK_F2:
{
rate=70;
break;
}
}
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0;
}
case WM_DESTROY: // 正在销毁窗口
// 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
::PostQuitMessage(0) ;
return 0 ;
}
// 将我们不处理的消息交给系统做默认处理
return ::DefWindowProc(hwnd, message, wParam, lParam);
}