#2
zhujianlin2013-05-23 09:51
|
#define WINVER 0x0500
#include <windows.h>
#include <time.h>
#define MAX_NODES 200
#define NODE_SIZE 20
#define SETP_SIZE NODE_SIZE
#define BLANK_SIZE 40
#define SNAKE_COLOR 0x00A5FF
#define SNAKE_BORDER_COLOR 0xFF
#define SNAKE_BORDER_WIDTH 1
#define GAME_AREA_BORDER_WIDTH 2
#define GAME_AREA_BORDER_CORLOR RGB(0,255,0)
#define BK_COLOR RGB(0,0,0)
#define MIN_NODES 2
#define MOVE_SPEED 1
#define MOVE_INTERVAL 1000/ MOVE_SPEED
#define IDT_SNAKE_MOVE 0x8080
#define FOOD_COLOR RGB(0,255,0)
#define SAFT_DISTANCE (MIN_NODES + 1)
typedef struct tagSnake
{
RECT rcNode[MAX_NODES];
int nodes;
int direction;
int life;
}SNAKE,*PSNAKE;
enum SnakeMoveState
{
OUT_BORDER = 0,
BITE_SELF = 1,
BITE_FOOD = 2,
NORMAL_MOVE = 3
};
enum SnakeState
{
SNAKE_LIVE = 1,
SNAKE_DEAD = 0
};
enum MovDirect
{
TO_LEFT = 0,
TO_UP = 1,
TO_RIGHT = 2,
TO_DOWN = 3,
};
enum FoodState
{
FOOD_EATUP = 1,
FOOD_FRESH = 0
};
typedef struct tagFood
{
RECT rc;
FoodState state;
}FOOD,*PFOOD;
RECT rtGameArea = {BLANK_SIZE,
BLANK_SIZE,
((GetSystemMetrics(SM_CXSCREEN) - 2*BLANK_SIZE)/NODE_SIZE)*NODE_SIZE + BLANK_SIZE,
((GetSystemMetrics(SM_CYSCREEN) - 2*BLANK_SIZE)/NODE_SIZE)*NODE_SIZE + BLANK_SIZE
};
RECT rtSnakePre,rtSnakeCur,rtScope;
POINT ptVital;
SNAKE theSnake;
FOOD theFood;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int MoveSnake(char);
void DrawSnake(HDC);
void Initial();
void DrawBackground(HDC);
void MakeNewSnake();
void PaintWindow(HDC);
int IsOutBorder(RECT *);
int IsBiteSelf(RECT *);
int IsInSnake();
void DrawFood(HDC);
void MakeNewFood();
int IsBiteFood(RECT*);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HappySnake");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbWndExtra = 0;
wndclass.cbClsExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox (NULL,TEXT("本程序需要Windws 2000以上!"),
szAppName,MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName,TEXT("快乐贪吃蛇1.0版"),
WS_POPUP |WS_VISIBLE,
0,0,
0,0,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_MAXIMIZE);
UpdateWindow(hwnd);
ShowCursor(FALSE);
while (GetMessage(&msg,NULL,0,0))
{TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
HPEN hPenCur;
HBRUSH hBrushCur;
PAINTSTRUCT ps;
RECT rtTemp;
switch(message)
{
case WM_CREATE:
Initial();
SetTimer(hWnd,IDT_SNAKE_MOVE,MOVE_INTERVAL,NULL);
break;
case WM_KEYUP:
switch(wParam)
{
case VK_ESCAPE:
PostMessage(hWnd,WM_QUIT,0,0);
break;
}
case WM_KEYDOWN:
hdc = GetDC(hWnd);
switch(wParam)
{
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
switch (MoveSnake(wParam - VK_LEFT))
{
case OUT_BORDER:
case BITE_SELF:
break;
case BITE_FOOD:
MakeNewFood();
DrawFood(hdc);
case NORMAL_MOVE:
DrawSnake(hdc);
break;
}
}
ReleaseDC(hWnd,hdc);
break;
case WM_PAINT:
PaintWindow(BeginPaint(hWnd,&ps));
EndPaint(hWnd,&ps);
break;
case WM_ERASEBKGND:
DefWindowProc(hWnd,message,wParam,lParam);
DrawBackground((HDC)wParam);
break;
case WM_TIMER:
SendMessage(hWnd,WM_KEYDOWN,VK_LEFT + theSnake.direction,0);
break;
case WM_DESTROY:
KillTimer(hWnd,IDT_SNAKE_MOVE);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}
void Initial()
{
srand((unsigned)time(NULL));
rtScope = rtGameArea;
InflateRect(&rtScope,-SAFT_DISTANCE*NODE_SIZE,-SAFT_DISTANCE*NODE_SIZE);
MakeNewSnake();
MakeNewFood();
}
void DrawBackground(HDC hdc)
{
HPEN hPenCur;
HBRUSH hBrushCur;
RECT rtTemp;
hPenCur = CreatePen(PS_SOLID,GAME_AREA_BORDER_WIDTH,GAME_AREA_BORDER_CORLOR);
SelectObject(hdc,hPenCur);
hBrushCur = (HBRUSH)GetStockObject(NULL_BRUSH);
SelectObject(hdc,hBrushCur);
rtTemp = rtGameArea;
InflateRect(&rtTemp,GAME_AREA_BORDER_WIDTH,GAME_AREA_BORDER_WIDTH);
Rectangle(hdc,rtTemp.left,rtTemp.top,rtTemp.right,rtTemp.bottom);
DeleteObject(hBrushCur);
}
int MoveSnake(char dir)
{
int xInc=0,yInc=0,i,state = NORMAL_MOVE;
if((dir - theSnake.direction) % 2 ==0
&& dir!= theSnake.direction)
return 0;
theSnake.direction = dir;
switch(theSnake.direction)
{
case TO_LEFT : xInc = -1;break;
case TO_RIGHT : xInc = 1;break;
case TO_UP : yInc = -1;break;
case TO_DOWN : yInc = 1;break;
}
rtSnakeCur = theSnake.rcNode[0];
OffsetRect(&rtSnakeCur,xInc * SETP_SIZE,yInc * SETP_SIZE);
if(IsOutBorder(&rtSnakeCur)) return OUT_BORDER;
if(IsBiteSelf(&rtSnakeCur)) return BITE_SELF;
if(IsBiteFood(&rtSnakeCur))
{
state = BITE_FOOD;
theFood.state = FOOD_EATUP;
theSnake.nodes++;
}
else
rtSnakePre = theSnake.rcNode[ theSnake.nodes -1];
for(i= theSnake.nodes - 1; i > 0;i--)
theSnake.rcNode[i] =theSnake.rcNode[i -1];
theSnake.rcNode[0] = rtSnakeCur;
return state;
}
void DrawSnake(HDC hdc)
{
HPEN hPenCur;
HBRUSH hBrushCur;
SelectObject(hdc,hPenCur = CreatePen(PS_SOLID,SNAKE_BORDER_WIDTH,BK_COLOR));
SelectObject(hdc,hBrushCur = (HBRUSH)CreateSolidBrush(BK_COLOR));
Rectangle(hdc,rtSnakePre.left,rtSnakePre.top,rtSnakePre.right,rtSnakePre.bottom);
DeleteObject(hBrushCur);
DeleteObject(hPenCur);
SelectObject(hdc,hPenCur = CreatePen(PS_SOLID,SNAKE_BORDER_WIDTH,SNAKE_BORDER_COLOR));
SelectObject(hdc,hBrushCur = CreateSolidBrush(SNAKE_COLOR));
Rectangle(hdc,rtSnakeCur.left,rtSnakeCur.top,rtSnakeCur.right,rtSnakeCur.bottom);
DeleteObject(hPenCur);
DeleteObject(hBrushCur);
}
int IsBiteSelf(RECT *pRect)
{
POINT pt;
int i;
pt.x = (pRect->left + pRect->right)/2;
pt.y = (pRect->top + pRect->bottom)/2;
for(i = 0; i < theSnake.nodes - 1; i++)
{
if(PtInRect(&theSnake.rcNode[i],pt)) return 1;
}
return 0;
}
int IsOutBorder(RECT *pRect)
{
POINT pt;
pt.x = (pRect->left + pRect->right) / 2;
pt.y = (pRect->top + pRect->bottom) / 2;
return (int)!PtInRect(&rtGameArea,pt);
}
void PaintWindow(HDC hdc)
{
int i;
HPEN oldPen = (HPEN)SelectObject(hdc,CreatePen(PS_SOLID,1,SNAKE_BORDER_COLOR));
HBRUSH odlBrush = (HBRUSH)SelectObject(hdc,CreateSolidBrush(SNAKE_COLOR));
if(!theSnake.life) return;
for(i = 0; i < theSnake.nodes; i++)
{
Rectangle(hdc,theSnake.rcNode[i].left,theSnake.rcNode[i].top,theSnake.rcNode[i].right,theSnake.rcNode[i].bottom);
}
SelectObject(hdc,oldPen);
SelectObject(hdc,odlBrush);
DrawFood(hdc);
}
void MakeRandRect(RECT *rc)
{
rc->left = (rand() %((rtScope.right - rtScope.left) / NODE_SIZE))*NODE_SIZE+rtScope.left;
rc->top = (rand() %((rtScope.bottom - rtScope.top) / NODE_SIZE))*NODE_SIZE+rtScope.top;
rc->right = rc->left + NODE_SIZE;
rc->bottom = rc->top + NODE_SIZE;
}
void MakeNewSnake()
{
int i ;
theSnake.direction = rand() %4;
theSnake.nodes = MIN_NODES;
theSnake.life = 1;
MakeRandRect(&theSnake.rcNode[0]);
for(i = 1 ; i < theSnake.nodes ; i++)
{
CopyRect(&theSnake.rcNode[i],&theSnake.rcNode[i-1]);
switch(theSnake.direction)
{
case TO_LEFT:
OffsetRect(&theSnake.rcNode[i],NODE_SIZE,0);
break;
case TO_UP:
OffsetRect(&theSnake.rcNode[i],0,NODE_SIZE);
break;
case TO_RIGHT:
OffsetRect(&theSnake.rcNode[i],-NODE_SIZE,0);
break;
case TO_DOWN:
OffsetRect(&theSnake.rcNode[i],0,-NODE_SIZE);
break;
}
}
}
void MakeNeWFood()
{
MakeRandRect(&theFood.rc);
while(IsInSnake())
MakeRandRect(&theFood.rc);
theFood.state = FOOD_FRESH;
}
int IsInSnake()
{
POINT pt;
int i;
pt.x = (theFood.rc.left + theFood.rc.right) / 2;
pt.y = (theFood.rc.top + theFood.rc.bottom) / 2;
for(i=0; i<theSnake.nodes ; i++)
if(PtInRect(&theSnake.rcNode[i],pt)) return 1;
return 0;
}
void DrawFood(HWND hWnd)
{
HDC hdc;
HBRUSH brush,oldBrush;
if(theFood.state) return;
hdc = GetDC(hWnd);
brush = CreateSolidBrush(FOOD_COLOR);
oldBrush = (HBRUSH)SelectObject(hdc,brush);
Ellipse(hdc,theFood.rc.left,theFood.rc.top,
theFood.rc.right,theFood.rc.bottom);
SelectObject(hdc,oldBrush);
}
int IsBiteFood(RECT *pRect)
{
POINT pt;
pt.x = (pRect->left + pRect->right) / 2;
pt.y = (pRect->top + pRect->bottom) / 2;
return PtInRect(&theFood.rc,pt);
}