win 32sdk編寫貪喫蛇(附源代碼)


       某天晚上閒着無聊就寫了個貪喫蛇鏈表,然後第二天就開始就主程序了,很快就寫完了,所以大家如果有好的思路,不妨也動動手嘛。好記性不如爛筆頭嘛。貪喫蛇的思路挺簡單的,就是用一個鏈表來保存蛇的路線,不過這個鏈表是經過特殊構造的,主要思路就是把客戶區分成若干個小方格子,然後鏈表會保存x和y座標,這個算是最重要的了,其它的都挺簡單的,在這裏就不贅述了。

打開vc6,然後新建一個win32空項目就可以了。

 

這個是運行截圖

這個是snake_list.h

 

#ifndef SNAKE_LIST_H
#define SNAKE_LIST_H

#define CLIENT_WIDTH	600
#define CLIENT_HEIGHT	600
#define ARRAY_COUNT		1600
#define ARRAY_WIDTH		40
#define ARRAY_HEIGHT	40
#define SANKE_UNIT		15
#define SNAKE_NUM		5

//定製版貪喫蛇鏈表
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 201314

static 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;
	char	temp;
	
	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 HFONT	hFont, hOldFont;
	static LOGFONT	logFont;
	POINT tempPoint;
	snake_list* temp;
	PAINTSTRUCT ps;
	static RECT	fontRect;
	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 place
		tempPoint.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 place
		tempPoint.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);
}

就寫到這裏把,明天還得早起呢。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章