win 32sdk编写贪吃蛇(附源代码)

来源:互联网 发布:网络降费提速发布会 编辑:程序博客网 时间:2024/06/05 04:01


       某天晚上闲着无聊就写了个贪吃蛇链表,然后第二天就开始就主程序了,很快就写完了,所以大家如果有好的思路,不妨也动动手嘛。好记性不如烂笔头嘛。贪吃蛇的思路挺简单的,就是用一个链表来保存蛇的路线,不过这个链表是经过特殊构造的,主要思路就是把客户区分成若干个小方格子,然后链表会保存x和y坐标,这个算是最重要的了,其它的都挺简单的,在这里就不赘述了。

打开vc6,然后新建一个win32空项目就可以了。

 

这个是运行截图

这个是snake_list.h

 

#ifndef SNAKE_LIST_H#define SNAKE_LIST_H#define CLIENT_WIDTH600#define CLIENT_HEIGHT600#define ARRAY_COUNT1600#define ARRAY_WIDTH40#define ARRAY_HEIGHT40#define SANKE_UNIT15#define SNAKE_NUM5//定制版贪吃蛇链表typedef struct Snake_List{int x;//x坐标int y;//y坐标struct Snake_List* next;}snake_list;extern void init_snake(snake_list** head, char* snake_array);//初始化蛇extern int add_head_hit(const int* x, const int* y, snake_list** head, char* snake_array);//撞上蛇extern int add_head_no_hit(const int* x, const int* y, snake_list** head, char* snake_array);//没撞上蛇extern void destory(snake_list* head);//清空蛇extern void get_head_info(snake_list* head, int *x, int *y);//获取蛇头#endif


这个是snake_list.c

#include "snake_list.h"#include <stdio.h>#include <stdlib.h>static snake_list* snake_tail;//蛇伪尾巴static void set_snake_tail(snake_list* head);//设置新的蛇伪尾巴void init_snake(snake_list** head, char* snake_array){snake_list *p, *q;int i, max_num;max_num = 18 + SNAKE_NUM;for (i = 18; i < max_num; i++) {//默认蛇长5个单位 坐标从20*ARRAY_WIDTH 13开始p = (snake_list* )malloc(sizeof(snake_list));if (i == 18) {*head = p;} else {q->next = p;if (i == max_num - 2) {snake_tail = p;//设置伪尾巴}}p->x = 30;p->y = i;snake_array[p->x*ARRAY_WIDTH+p->y] = 1;//更改蛇数组的位q = p;}p->next = NULL;}//x, y是撞击的位置坐标,撞击后头部改变,尾巴不变int add_head_hit(const int* x, const int* y, snake_list** head, char* snake_array){snake_list *p, *q;p = (snake_list*)malloc(sizeof(snake_list));q = *head;*head = p;(*head)->x = *x;(*head)->y = *y;(*head)->next = q;snake_array[*x*ARRAY_WIDTH+*y] = 1;return 1;}//x, y是前进的位置坐标,前进后头部改变,尾巴改变int add_head_no_hit(const int* x, const int* y, snake_list** head, char* snake_array){snake_list *p, *q;p = (snake_list*)malloc(sizeof(snake_list));q = *head;*head = p;(*head)->x = *x;(*head)->y = *y;(*head)->next = q;snake_array[*x*ARRAY_WIDTH+*y] = 1;p = snake_tail;//设置新的尾巴q = p->next;p->next = NULL;snake_array[q->x*ARRAY_WIDTH+q->y] = 0;free(q);set_snake_tail(*head); return 1;}void destory(snake_list* head){snake_list *p, *q;p = head;while (p) {q = p->next;free (p);p = q;}}void get_head_info(snake_list* head, int *x, int *y){*x = head->x;*y = head->y;}static void set_snake_tail(snake_list* head){snake_list* temp;temp = head;while (temp->next->next) {//找到到第二个位置temp = temp->next;}snake_tail = temp;}


 

这个是resource.h

//{{NO_DEPENDENCIES}}// Microsoft Developer Studio generated include file.// Used by resource.rc//#define IDB_BITMAP1                     101#define IDI_ICON1                       102// Next default values for new objects// #ifdef APSTUDIO_INVOKED#ifndef APSTUDIO_READONLY_SYMBOLS#define _APS_NEXT_RESOURCE_VALUE        103#define _APS_NEXT_COMMAND_VALUE         40001#define _APS_NEXT_CONTROL_VALUE         1000#define _APS_NEXT_SYMED_VALUE           101#endif#endif


 

这个是snake.c

 

#include <windows.h>#include <stdio.h>#include <time.h>#include "snake_list.h"#include "resource.h"#define bool  int#define true  1#define false 0#define TIMERID 201314static HINSTANCE ghInstance;static UINT gDirection;static RECT gClientRect;static POINT gSnakeFood;//食物static bool gStop;//是否暂停static snake_list* gSnakeHead;//蛇头static bool   gGameStart;//游戏是否开始static char   gSnakeArray[ARRAY_HEIGHT*ARRAY_WIDTH];//保存蛇的路径void Init(HWND hwnd);//初始化一些变量void HandleMove(HWND hwnd, UINT keyCode);//处理上下左右键消息void HandleQuit(HWND hwnd);//处理用户是否退出void DrawSnake(HWND hwnd);//绘制蛇的身体void GenerateFood();//随机产生食物void AutoForward(HWND hwnd);//自动前进LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wpara,LPARAM lpara);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ){WNDCLASS wndclass;MSG msg;HWND hwnd;RECT windowRect, clientRect;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);wndclass.hCursor = LoadCursor(hInstance, IDC_UPARROW);//光标属性wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));//图标wndclass.hInstance = hInstance;wndclass.lpfnWndProc = WinProc;wndclass.lpszClassName = "snake";wndclass.lpszMenuName = NULL;//无菜单wndclass.style = CS_HREDRAW | CS_VREDRAW;//窗口风格ghInstance = hInstance;//注册窗口RegisterClass(&wndclass);//创建窗口hwnd = CreateWindow("snake", "Snake-by-inconsolablev", WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX, 0, 0,CLIENT_WIDTH, CLIENT_HEIGHT, NULL, NULL, ghInstance, NULL);//调整客户区的大小GetWindowRect(hwnd,&windowRect);GetClientRect(hwnd,&clientRect);windowRect.right += CLIENT_WIDTH - clientRect.right + clientRect.left;windowRect.bottom += CLIENT_HEIGHT - clientRect.bottom + clientRect.top;MoveWindow(hwnd, (GetSystemMetrics(SM_CXSCREEN) - windowRect.right + windowRect.left) / 2, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, true);Init(hwnd);ShowWindow(hwnd, SW_SHOWNORMAL);UpdateWindow(hwnd);while (GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wpara,LPARAM lpara){switch (uMsg){case WM_KEYDOWN:if (wpara == VK_SPACE && gGameStart == false) {gGameStart = true;GenerateFood();SetTimer(hwnd, TIMERID, 150, NULL);} else if (wpara == VK_RETURN && gGameStart == true) {//Enter 暂停KillTimer(hwnd, TIMERID);gStop = true;InvalidateRect(hwnd, &gClientRect, false);} else if (wpara == VK_SPACE && gStop == true) {//继续游戏gStop = false;SetTimer(hwnd, TIMERID, 150, NULL);} else if (gGameStart == true && gStop == false) {HandleMove(hwnd, wpara);}break;case WM_TIMER:HandleMove(hwnd, gDirection);break;case WM_PAINT:DrawSnake(hwnd);break;case WM_CLOSE:if (IDYES == MessageBox(hwnd,"是否真的结束?","snake",MB_YESNO)){KillTimer(hwnd, TIMERID);DestroyWindow(hwnd);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd,uMsg,wpara,lpara);}return (LRESULT)NULL;}void Init(HWND hwnd){gGameStart = false;gStop = false;gDirection = VK_LEFT;//默认左边memset(gSnakeArray, 0, ARRAY_HEIGHT*ARRAY_WIDTH);GetClientRect(hwnd, &gClientRect);init_snake(&gSnakeHead, gSnakeArray);}void HandleQuit(HWND hwnd){KillTimer(hwnd, TIMERID);destory(gSnakeHead);Init(hwnd);InvalidateRect(hwnd, &gClientRect, false);}void HandleMove(HWND hwnd, UINT keyCode){static POINT basePoint;chartemp;get_head_info(gSnakeHead, &basePoint.x, &basePoint.y);switch (keyCode){case VK_UP:if (basePoint.x != 0) {//没到达最顶端就可以继续basePoint.x--;temp = gSnakeArray[basePoint.x*ARRAY_WIDTH+basePoint.y];if (temp == 0) {//无障碍物gDirection = VK_UP;add_head_no_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 2) {//碰到食物 吃掉gDirection = VK_UP;add_head_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);GenerateFood();InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 1) {if (gDirection != VK_DOWN) {//蛇绕成一团 而不是后退HandleQuit(hwnd);}}} else {HandleQuit(hwnd);}break;case VK_DOWN:if (basePoint.x != ARRAY_HEIGHT - 1) {//没到达最下端就可以继续basePoint.x++;temp = gSnakeArray[basePoint.x*ARRAY_WIDTH+basePoint.y];if (temp == 0) {//无障碍物gDirection = VK_DOWN;add_head_no_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 2) {//碰到食物 吃掉gDirection = VK_DOWN;add_head_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);GenerateFood();InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 1) {if (gDirection != VK_UP) {//蛇绕成一团 而不是后退HandleQuit(hwnd);}}} else {HandleQuit(hwnd);}break;case VK_LEFT:if (basePoint.y != 0) {//没到达最左端就可以继续basePoint.y--;temp = gSnakeArray[basePoint.x*ARRAY_WIDTH+basePoint.y];if (temp == 0) {//无障碍物gDirection = VK_LEFT;add_head_no_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 2) {//碰到食物 吃掉gDirection = VK_LEFT;add_head_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);GenerateFood();InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 1) {if (gDirection != VK_RIGHT) {//蛇绕成一团 而不是后退HandleQuit(hwnd);}}} else {HandleQuit(hwnd);}break;case VK_RIGHT:if (basePoint.y != ARRAY_WIDTH - 1) {//没到达最右端就可以继续basePoint.y++;temp = gSnakeArray[basePoint.x*ARRAY_WIDTH+basePoint.y];if (temp == 0) {//无障碍物gDirection = VK_RIGHT;add_head_no_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 2) {//碰到食物 吃掉gDirection = VK_RIGHT;add_head_hit(&basePoint.x, &basePoint.y, &gSnakeHead, gSnakeArray);GenerateFood();InvalidateRect(hwnd, &gClientRect, false);} else if (temp == 1) {if (gDirection != VK_LEFT) {//蛇绕成一团 而不是后退HandleQuit(hwnd);}}} else {HandleQuit(hwnd);}break;default:break;}}void GenerateFood(){int i = 0, j = 0;static short int temp[ARRAY_COUNT];for (i = 0; i < ARRAY_COUNT; i++) {if (gSnakeArray[i] == 0) {temp[j++] = i;//保存是0的位置}}//然后在这些元素是0里面取一个就行了srand((unsigned)time(NULL));j = rand() % j; //随机获取一个是0的元素gSnakeFood.x = temp[j] / ARRAY_WIDTH;gSnakeFood.y = temp[j] % ARRAY_WIDTH;gSnakeArray[gSnakeFood.x*ARRAY_WIDTH+gSnakeFood.y] = 2;//食物标记}void DrawSnake(HWND hwnd){static HDC hMemDC, hDC;static HBRUSH  hBrush, hOldBrush;static HBITMAP hBitmap, hOldBitmap;static HFONThFont, hOldFont;static LOGFONTlogFont;POINT tempPoint;snake_list* temp;PAINTSTRUCT ps;static RECTfontRect;char str[25];temp = gSnakeHead;hDC = BeginPaint(hwnd, &ps);hMemDC = CreateCompatibleDC(hDC);hBitmap = (HBITMAP)LoadBitmap(ghInstance, MAKEINTRESOURCE(IDB_BITMAP1));hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);//保存旧的位图hBrush = CreateSolidBrush(RGB(87, 66, 189));hOldBrush = (HBRUSH)SelectObject(hMemDC, hBrush);//保存旧的画刷SetBkMode(hMemDC, TRANSPARENT);while (temp) {//遍历整个蛇 绘制蛇身tempPoint.x = temp->y*SANKE_UNIT;//notify this placetempPoint.y = temp->x*SANKE_UNIT;Rectangle(hMemDC, tempPoint.x, tempPoint.y, tempPoint.x+SANKE_UNIT, tempPoint.y+SANKE_UNIT);temp = temp->next;}if (gGameStart == false) {//游戏未开始 写提示sprintf(str, "Press Space To Start!");SetTextColor(hMemDC, RGB(255, 0, 0));ZeroMemory(&logFont,   sizeof(LOGFONT));   logFont.lfCharSet = ANSI_CHARSET;   logFont.lfHeight = 30;      //设置字体的大小logFont.lfWidth= 15;logFont.lfWeight = 10;hFont = CreateFontIndirect(&logFont);   fontRect.left = 150;fontRect.right = fontRect.left+400;fontRect.top = 100;fontRect.bottom = 400;hOldFont = (HFONT)SelectObject(hMemDC,hFont);//保存旧的的字体DrawText(hMemDC, str, strlen(str), &fontRect, DT_BOTTOM);} else {if (gStop == true) {//暂停游戏sprintf(str, "Press Space to Continue!");SetTextColor(hMemDC, RGB(255, 0, 0));hFont = CreateFontIndirect(&logFont);   hOldFont = (HFONT)SelectObject(hMemDC,hFont);//保存旧的的字体DrawText(hMemDC, str, strlen(str), &fontRect, DT_BOTTOM);} else {//继续游戏sprintf(str, "Press Enter to Stop!");SetTextColor(hMemDC, RGB(255, 0, 0));hFont = CreateFontIndirect(&logFont);   hOldFont = (HFONT)SelectObject(hMemDC,hFont);//保存旧的的字体DrawText(hMemDC, str, strlen(str), &fontRect, DT_BOTTOM);}//绘制食物DeleteObject(hBrush);hBrush = CreateSolidBrush(RGB(55, 208, 47));hOldBrush = (HBRUSH)SelectObject(hMemDC, hBrush);tempPoint.x = gSnakeFood.y*SANKE_UNIT;//notify this placetempPoint.y = gSnakeFood.x*SANKE_UNIT;Rectangle(hMemDC, tempPoint.x, tempPoint.y, tempPoint.x+SANKE_UNIT, tempPoint.y+SANKE_UNIT);}BitBlt(hDC, 0, 0, gClientRect.right - gClientRect.left, gClientRect.bottom - gClientRect.top, hMemDC, 0, 0, SRCCOPY);SelectObject(hMemDC, hOldFont);//选回旧的SelectObject(hMemDC, hOldBitmap);SelectObject(hMemDC, hOldBrush);EndPaint(hwnd,&ps);DeleteDC(hMemDC);//释放资源DeleteDC(hDC);DeleteObject(hBitmap);DeleteObject(hFont);DeleteObject(hBrush);}

就写到这里把,明天还得早起呢。

 

原创粉丝点击