Visual Studio C++/C 游戏——双人贪吃蛇 实现方法+代码讲解+算法优化+成功展示+源代码+总结(超详细,适合小白)
C++/C小游戲?? 雙人貪吃蛇——金蛇狂舞?? 課程設(shè)計(jì)作業(yè)分享
Visual Studio C++/C 游戲——雙人貪吃蛇 ? ?實(shí)現(xiàn)方法+代碼講解+算法優(yōu)化+成功展示+總結(jié)(超詳細(xì),適合小白)
源碼見(jiàn)文末
?
?
目錄
一、問(wèn)題描述
二、準(zhǔn)備工作
三、部分代碼分析與實(shí)現(xiàn)(詳細(xì)代碼見(jiàn)附件)
四、游戲運(yùn)行展示
五、總結(jié)
?
感想(可借鑒)
源碼
?
一、問(wèn)題描述
?? 把數(shù)據(jù)結(jié)構(gòu)中的基本知識(shí)點(diǎn),如棧、隊(duì)列、線性表、圖、樹(shù)等運(yùn)用到實(shí)際的問(wèn)題當(dāng)中,以小游戲或小工具等程序方式呈現(xiàn),要求理解基本結(jié)構(gòu)并能拓展,最后達(dá)到應(yīng)用的目的。
二、準(zhǔn)備工作
- 使用Audacity對(duì)所需音頻進(jìn)行處理并導(dǎo)入目標(biāo)文件夾
- 使用Photoshop將所需圖片素材進(jìn)行編輯與格式轉(zhuǎn)換
??
- 使用 2019 Visual Studio Community集成環(huán)境C++程序開(kāi)發(fā)功能進(jìn)行游戲設(shè)計(jì)
將背景、貼圖、頭部、身體、食物照片提前轉(zhuǎn)為bmp格式并調(diào)好像素轉(zhuǎn)入目標(biāo)文件夾
?
三、部分代碼分析與實(shí)現(xiàn)(詳細(xì)代碼見(jiàn)附件)
-
背景墻的顏色改變
拓展部分:將背景墻樣式重新設(shè)計(jì)為具有中國(guó)紅元素的喜慶風(fēng)格,洋溢春節(jié)喜慶色彩。
實(shí)現(xiàn)方式:
分析:此設(shè)計(jì)目的在于將背景打造出新年廣場(chǎng)舞獅的感覺(jué),個(gè)人認(rèn)為中國(guó)紅元素也是紅色元素,喜慶的色彩使得整個(gè)游戲民族文化的氛圍更加濃郁。
-
名稱(chēng):貼圖的引用與文本的生成
拓展部分:玩家一蛇身為橙色龍鱗,頭部為舞獅畫(huà)像,代表舞獅,玩家二蛇身為藍(lán)色龍鱗,頭部為年獸畫(huà)像,代表年獸,食物使用紅色燈籠圖片,并且取名玩家一為舞獅,玩家二為年獸,游戲?yàn)榻鹕呖裎?#xff0c;并貼入主題圖片,在右側(cè)顯示相關(guān)信息,介紹操作方式與身體長(zhǎng)度。
實(shí)現(xiàn)方式:
?
分析:本游戲舞獅與年獸在新年廣場(chǎng)(指背景版)爭(zhēng)奪燈籠的比賽設(shè)計(jì)靈感來(lái)自于舞獅與年獸的傳說(shuō),添加主題圖片“金蛇狂舞”對(duì)應(yīng)雙人貪吃蛇對(duì)戰(zhàn),所有的中國(guó)風(fēng)紅色喜慶元素的加入旨在烘托出新年喜慶活動(dòng)舞獅子的春節(jié)氛圍,右側(cè)提示欄方便玩家理解游戲操作與分?jǐn)?shù)統(tǒng)計(jì)。
?
-
名稱(chēng):雙人對(duì)戰(zhàn)操作的實(shí)現(xiàn)
拓展部分:本游戲擴(kuò)展為雙人對(duì)戰(zhàn),雙方均可通過(guò)吞噬食物增長(zhǎng)體型。主要玩法為保護(hù)自身的頭部,吞噬食物同時(shí)利用身體長(zhǎng)度優(yōu)勢(shì)對(duì)另一方進(jìn)行圍堵,若一方的頭部撞到另一方的身體,則另一方獲勝,反之,則以。
實(shí)現(xiàn)方式:
分析:在原有的基礎(chǔ)上添加了另一個(gè)玩家的身體參數(shù)記錄操作控制、食物吞噬、撞墻死亡判定,算法原理不變,在此之外還添加了雙方對(duì)戰(zhàn)的死亡判定,若一方頭部碰到另一方身體,則判定前者死亡,反之則以。增加了游戲的可玩性與操作性,但也出現(xiàn)了很多新的問(wèn)題,例如身體與背景的疊加打印會(huì)導(dǎo)致快速閃爍,引起視覺(jué)的不舒服,在后面擴(kuò)展中會(huì)一一解決。
?
-
名稱(chēng):多個(gè)食物的隨機(jī)生成
拓展部分:隨機(jī)生成多個(gè)食物供兩個(gè)玩家吞噬
實(shí)現(xiàn)方式:
分析:貪吃蛇雙人對(duì)戰(zhàn)一個(gè)食物肯定會(huì)影響游戲的體驗(yàn),所以出于這個(gè)考慮將食物設(shè)定為可調(diào)節(jié)的多個(gè)食物,在游戲初次運(yùn)行或重新開(kāi)始時(shí)生成多個(gè)新的隨機(jī)食物,當(dāng)一位玩家吃掉一個(gè)食物時(shí)身體長(zhǎng)度會(huì)加一,同時(shí)會(huì)生成一個(gè)新的隨機(jī)食物,但也出現(xiàn)了新的問(wèn)題,例如多個(gè)食物生成會(huì)重疊,新的食物生成在舊的食物身上或者在蛇身上,食物生成多個(gè)的同時(shí)還要考慮生成食物的代價(jià),與判定食物吞噬的代價(jià),食物與背景重疊打印會(huì)閃爍,這些問(wèn)題在后面的優(yōu)化擴(kuò)展中會(huì)給予解答。
?
-
名稱(chēng):解決食物與身體重疊打印的閃爍問(wèn)題 + 結(jié)構(gòu)優(yōu)化
拓展部分:建立判定身體食物位置狀態(tài)的數(shù)組,解決重疊打印帶來(lái)的身體食物閃爍問(wèn)題,優(yōu)化結(jié)構(gòu)減少程序代價(jià)。
實(shí)現(xiàn)方式:
分析:游戲初次運(yùn)行或重新開(kāi)始時(shí)將身體判定數(shù)組與食物判定數(shù)組初始化為零,在初次生成多個(gè)食物時(shí)將食物判定數(shù)組中各食物位置權(quán)值置1,在游戲進(jìn)行的同時(shí)每次打印前將身體位置判定數(shù)組初始化權(quán)值置為0,并將此時(shí)的身體位置所在權(quán)值更新為1;當(dāng)食物被吞噬時(shí),將該位置食物判定數(shù)組權(quán)值重新置0,并生成新食物;在新食物生成時(shí)使用do-while語(yǔ)句先生成隨機(jī)位置再判定是否此位置已有食物或者此位置為玩家身體,若不符合要求則重新生成,若符合要求則將此位置的食物判定數(shù)組權(quán)值置為1;在每次打印背景板時(shí)加入該位置的身體與食物的判定,若此處食物判定數(shù)組權(quán)值為1或身體判定數(shù)組權(quán)值為1則不打印背景板,若此處兩判定權(quán)值均為0則打印背景板;以上操作有效解決了多個(gè)食物產(chǎn)生的錯(cuò)誤位置打印問(wèn)題,與背景板重疊打印在身體和食物上產(chǎn)生的閃爍問(wèn)題。
?
-
名稱(chēng):背景音樂(lè)“金蛇狂舞”
拓展部分:在游戲開(kāi)始時(shí)自動(dòng)播放喜慶主題背景音樂(lè)“金蛇狂舞”
實(shí)現(xiàn)方式:
分析:插入提前通過(guò)Audacity編輯好的BGM“金蛇狂舞”呼應(yīng)主題金蛇狂舞,一同作用,共同渲染了中國(guó)紅的新年喜慶舞獅氛圍,并且激烈喜慶的音樂(lè)也為游戲的體驗(yàn)添加了幾份別樣風(fēng)采。
?
-
名稱(chēng):開(kāi)場(chǎng)主題圖片
拓展部分:在初次打開(kāi)游戲時(shí)在窗口中央顯示主題圖片,并在游戲開(kāi)始后消失
實(shí)現(xiàn)方式:
分析:通過(guò)設(shè)置全局變量kk控制游戲在初次開(kāi)始時(shí)進(jìn)入開(kāi)場(chǎng)圖片打印函數(shù)start(),該圖片在呼應(yīng)主題的同時(shí),使得玩家在初次打開(kāi)游戲時(shí)的視覺(jué)上得到滿足,提升游戲的整體觀賞檔次。
?
-
名稱(chēng):游戲開(kāi)始與快速重來(lái)
拓展部分: 空格控制游戲初次開(kāi)始與快速重新開(kāi)始
實(shí)現(xiàn)方式:
分析:初次進(jìn)入游戲按下空格,主題圖片消失,游戲進(jìn)行時(shí)按下空格,快速重新開(kāi)始,豐富了玩家的操作內(nèi)容與游戲體驗(yàn)。
?
四、游戲運(yùn)行展示
?
五、總結(jié)
在原有的游戲基礎(chǔ)上進(jìn)行了徹頭徹尾的修改與添加,將游戲單獨(dú)的貪吃蛇游戲模式改為了雙人貪吃蛇對(duì)戰(zhàn)模式,雙方均可通過(guò)吞噬食物增長(zhǎng)體型。主要玩法為保護(hù)自身的頭部,吞噬食物同時(shí)利用身體長(zhǎng)度優(yōu)勢(shì)對(duì)另一方進(jìn)行圍堵,若一方的頭部撞到另一方的身體,則另一方獲勝,反之,則以。多項(xiàng)修改大幅增加了游戲的可玩性,同時(shí)針對(duì)很多出現(xiàn)的bug與問(wèn)題進(jìn)行了比較完善的解決
感想(純屬應(yīng)付作業(yè)? 可借鑒):
本次游戲設(shè)計(jì)使我收獲良多,從最早的毫無(wú)頭緒,拿到基礎(chǔ)代碼不知從何下手,一改就是很多bug,到后來(lái)的的井井有條,在原來(lái)的基礎(chǔ)上可以靈活的進(jìn)行刪改與創(chuàng)新,我不僅掌握了編寫(xiě)游戲的能力,更加掌握了優(yōu)化結(jié)構(gòu),創(chuàng)造游戲的能力,也在一定程度上提升了自身的審美設(shè)計(jì)能力。一開(kāi)始我的目標(biāo)只是制作一個(gè)雙人貪吃蛇游戲,像前一陣子很火的一款手游(蛇蛇大作戰(zhàn)),即兩只蛇進(jìn)行pk,一方頭部碰到另一方的身體即為死亡,反之則以,兩只蛇的操作與死亡判定的代碼實(shí)現(xiàn)過(guò)程很是順利,在進(jìn)行的過(guò)程中遇到了其他的麻煩,比如兩條蛇爭(zhēng)奪一個(gè)食物,雖變成了雙人游戲,但游戲的可玩性卻大幅下降,在認(rèn)識(shí)到這個(gè)問(wèn)題后,便開(kāi)始嘗試生成多個(gè)食物,而生成多個(gè)食物最早的想法只是單純的生成多個(gè)食物,但陸續(xù)發(fā)現(xiàn)多個(gè)食物生成時(shí)會(huì)出現(xiàn)重疊打印導(dǎo)致食物越來(lái)越少,或者一個(gè)食物生長(zhǎng)長(zhǎng)度不為一的情況,針對(duì)這個(gè)問(wèn)題在每次生成食物時(shí)添加了for循環(huán)的判定原則,用于判定此位置是否為蛇身或者已有食物生成,但在運(yùn)行起來(lái)之后發(fā)現(xiàn)使用這種多層循環(huán)的結(jié)構(gòu)程序運(yùn)行代價(jià)過(guò)高,在食物數(shù)量設(shè)定為十個(gè)以上時(shí),程序會(huì)經(jīng)常掛掉,之后參考了陳偉斌老師算法設(shè)計(jì)這門(mén)課程中講到的眾多實(shí)例,最終設(shè)立全局身體與食物位置的判定數(shù)組,通過(guò)這種方式使得在每次食物更新時(shí)只需一個(gè)do-while語(yǔ)句便可完成更新,大大減小了計(jì)算復(fù)雜度,在此基礎(chǔ)上也通過(guò)該判定數(shù)組的設(shè)立于打印時(shí)添加條件,解決了背景塊與食物重復(fù)打印導(dǎo)致的閃爍問(wèn)題,以上的操作過(guò)程使得整個(gè)游戲得以基本成型,之后便是美化環(huán)節(jié),但考慮到融入五星紅旗元素過(guò)于僵硬,甚至導(dǎo)致起到反效果,正逢臨近新年,于是思考之下決定將紅色元素的范疇擴(kuò)大到中國(guó)紅,民族紅,一開(kāi)始想到的便是與兩蛇很接近的新年喜慶音樂(lè)“金蛇狂舞”,但兩只蛇爭(zhēng)搶食物的設(shè)定過(guò)于單薄,后來(lái)查閱了相關(guān)資料,將游戲環(huán)境定義為新年廣場(chǎng)的舞獅表演,背景顏色選擇中國(guó)紅與金黃色,寓意紅紅火火,吉祥如意,玩家一的頭部改為舞獅頭部畫(huà)像,身軀選用橙色龍鱗,獅是兇猛的代表,吉祥的象征,他的舞動(dòng)對(duì)應(yīng)中華民族傳統(tǒng)文化“舞獅子”,并將食物改為燈籠樣式,寓意新年新氣象,爭(zhēng)奪燈籠便是代表著百姓對(duì)新一年的憧憬,而玩家二則選用年獸頭部畫(huà)像作為頭部,選擇藍(lán)色龍鱗作為身軀,該設(shè)計(jì)源自于佛山起源說(shuō)——年獸與舞獅的故事,簡(jiǎn)要內(nèi)容為百姓用舞獅的舞動(dòng)配合敲響樂(lè)(金蛇狂舞便是其中一種)嚇走了想要破壞村莊的年獸(除夕),隨后便用舞獅的方式慶祝佳節(jié),玩家一與玩家二的對(duì)戰(zhàn),便對(duì)應(yīng)著舞獅與年獸的對(duì)戰(zhàn),象征著佳節(jié)將至,營(yíng)造了中華民族傳統(tǒng)節(jié)日的氛圍,及中國(guó)紅元素。本次游戲設(shè)計(jì),我個(gè)人認(rèn)為自己設(shè)計(jì)的很滿意,在本來(lái)的基礎(chǔ)上進(jìn)行了多次的蛻變,從基礎(chǔ)的貪吃蛇,到雙人貪吃蛇對(duì)戰(zhàn),到多食物的雙人對(duì)戰(zhàn),再到最后的金蛇狂舞——舞獅與年獸的宿命之戰(zhàn),新年氣運(yùn)燈籠的搶奪,其中不僅加入了很多自己的設(shè)計(jì)創(chuàng)意,很多中國(guó)紅元素,更是解決了程序運(yùn)行代價(jià)大、背景塊與身體食物重疊打印的閃爍問(wèn)題,并且在最終成品上竟然真的營(yíng)造出了一種“年味兒”,這也是我本次游戲設(shè)計(jì)最大的收獲。
?
?
源碼:
// MySnake.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "stdio.h" #include "resource.h" #include "time.h" #include <mmsystem.h> #include <string.h> #pragma comment(lib,"winmm.lib") #define MAX_LOADSTRING 100 HINSTANCE hInst; TCHAR szTitle[MAX_LOADSTRING]; TCHAR szWindowClass[MAX_LOADSTRING]; ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {MSG msg;HACCEL hAccelTable;LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_MYSNAKE, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);if (!InitInstance (hInstance, nCmdShow)) {return FALSE;}hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MYSNAKE);while (GetMessage(&msg, NULL, 0, 0)) {if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {TranslateMessage(&msg);DispatchMessage(&msg);}}return msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) {WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc = (WNDPROC)WndProc;wcex.cbClsExtra = 0;wcex.cbWndExtra = 0;wcex.hInstance = hInstance;wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MYSNAKE);wcex.hCursor = LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName = (LPCSTR)IDC_MYSNAKE;wcex.lpszClassName = szWindowClass;wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);return RegisterClassEx(&wcex); }//框架系數(shù) HDC hdc,mdc,bufdc; int row=20; int col=25; int kk = 0; int heightT = 200; HBITMAP bg,bg2,pi1,pi2, food,pn[2];//貼圖 #define WIDTH 30 #define HEIGHT 30 #define MAXSIZE 50 //身體 數(shù)據(jù)結(jié)構(gòu) struct Snake {POINT m_pos[MAXSIZE];int m_direction;int len; }; Snake m_snake,m_snake2;//舞獅 年獸 #define NUMBER 15 //食物數(shù)量 POINT m_food[NUMBER];//食物生成 int foods[30][25],body[30][25];//防止重復(fù)打印//食物初始化 void foodbegin() {for (int i = 0; i < NUMBER; i++) {m_food[i].x = rand() %(col-1)+1;m_food[i].y = rand() %(row-1)+1;foods[m_food[i].x][m_food[i].y] = 1;} }//食物更新 void generatefood(int i) {srand((unsigned)time(NULL));do {m_food[i].x = rand() % (col - 1) + 1;m_food[i].y = rand() % (row - 1) + 1;} while (foods[m_food[i].x][m_food[i].y] == 1); //避免食物重復(fù)生成foods[m_food[i].x][m_food[i].y] = 1; }//身體系數(shù)初始化 void init_snake() {//舞獅 身體初始化m_snake.len=3;m_snake.m_pos[0].x=1;m_snake.m_pos[0].y=5;m_snake.m_direction=1;for(int n=1;n<MAXSIZE;n++){m_snake.m_pos[n].x=-1;m_snake.m_pos[n].y=-1;}//年獸 身體初始化m_snake2.len = 3;m_snake2.m_pos[0].x =1;m_snake2.m_pos[0].y =row-5;m_snake2.m_direction = 1;for (int n = 1; n < MAXSIZE; n++){m_snake2.m_pos[n].x = -1;m_snake2.m_pos[n].y = -1;}foodbegin(); }//畫(huà)面生成 void MyPaint(HDC hdc) {//入場(chǎng)效果kk++;//身體位置系數(shù)化memset(body, 0, sizeof(body));for (int ii = m_snake.len; ii > -1; ii--) body[m_snake.m_pos->x][m_snake.m_pos->y] = 1;for (int ii = m_snake2.len; ii > -1; ii--) body[m_snake2.m_pos->x][m_snake2.m_pos->y] = 1;//背景板生成HBRUSH hbr=CreateSolidBrush(RGB(220, 205, 50));SelectObject(hdc,hbr);for(int y=1;y<row;y++)for (int x = 1; x < col; x++)if(foods[x][y]!=1&&body[x][y]!=1)Rectangle(hdc,x*WIDTH,y*HEIGHT,(x+1)*WIDTH,(y+1)*HEIGHT);//邊緣墻生成HBRUSH hbr2 =CreateSolidBrush(RGB(255,0,0));SelectObject(hdc, hbr2);for (int y = 0; y <= row; y++)Rectangle(hdc, col*WIDTH, y*HEIGHT, (col + 1)*WIDTH, (y + 1)*HEIGHT);for (int y = 0; y <= row; y++)Rectangle(hdc, 0*WIDTH, y*HEIGHT, (0 + 1)*WIDTH, (y + 1)*HEIGHT);for (int x = 0; x < col; x++)Rectangle(hdc, x*WIDTH, row*HEIGHT, (x + 1)*WIDTH, (row + 1)*HEIGHT);for (int x = 0; x < col; x++)Rectangle(hdc, x*WIDTH, 0*HEIGHT, (x + 1)*WIDTH, (0 + 1)*HEIGHT);//右側(cè)數(shù)據(jù)欄生成HFONT font = CreateFont(30, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("楷體"));SelectObject(hdc, font);//SetBkMode(hdc, TRANSPARENT); //底色透明char str1[8];sprintf(str1, "%4d km", m_snake.len); //舞獅分?jǐn)?shù)char str2[8];sprintf(str2, "%4d km", m_snake2.len); //年獸分?jǐn)?shù)TextOut(hdc, col*WIDTH + 50, 90, "空格:", 6);TextOut(hdc, col*WIDTH + 50, 120, "開(kāi)始/重來(lái)", 10);TextOut(hdc, col*WIDTH + 60, heightT, "舞獅",4);TextOut(hdc, col*WIDTH + 80, heightT+40, "↑", 2);TextOut(hdc, col*WIDTH + 50, heightT+70, "←↓→", 6);TextOut(hdc, col*WIDTH + 80, heightT+100, str1, 8);TextOut(hdc, col*WIDTH + 60, heightT+200, "年獸",4);TextOut(hdc, col*WIDTH + 80, heightT+240, "W ", 2);TextOut(hdc, col*WIDTH + 50, heightT+270, "A S D ", 6);TextOut(hdc, col*WIDTH + 80, heightT+300, str2, 8);SelectObject(mdc, bg2);BitBlt(hdc, col*WIDTH + 40, 0, 150, 80, mdc, 0, 0, SRCCOPY); //粘貼主題圖片//食物生成for (int i = 0; i < NUMBER; i++) {SelectObject(mdc, food);BitBlt(hdc, m_food[i].x * WIDTH, m_food[i].y * HEIGHT, 30, 30, mdc, 0, 0, SRCCOPY);}//舞獅身體生成HBRUSH hbrgreen=CreateSolidBrush(RGB(0,109,163));SelectObject(hdc,hbrgreen);for (int n = 1; n < m_snake.len; n++) {SelectObject(mdc, pi1);BitBlt(hdc, m_snake.m_pos[n].x * 30, m_snake.m_pos[n].y * 30, 30, 30, mdc, 0, 0, SRCCOPY);}/* Rectangle(hdc,m_snake.m_pos[n].x*WIDTH,m_snake.m_pos[n].y*HEIGHT,(m_snake.m_pos[n].x+1)*WIDTH,(m_snake.m_pos[n].y+1)*HEIGHT);*///年獸身體生成HBRUSH hbrgreen2 = CreateSolidBrush(RGB(235, 95, 37));SelectObject(hdc, hbrgreen2);for (int n = 1; n < m_snake2.len; n++) {SelectObject(mdc, pi2);BitBlt(hdc, m_snake2.m_pos[n].x * 30, m_snake2.m_pos[n].y * 30, 30, 30, mdc, 0, 0, SRCCOPY);}/* Rectangle(hdc, m_snake2.m_pos[n].x * WIDTH, m_snake2.m_pos[n].y * HEIGHT, (m_snake2.m_pos[n].x + 1) * WIDTH,(m_snake2.m_pos[n].y + 1) * HEIGHT);*///頭部生成SelectObject(mdc, pn[0]);BitBlt(hdc, m_snake.m_pos[0].x * 30, m_snake.m_pos[0].y * 30, 30, 30, mdc, 0, 0, SRCCOPY);SelectObject(mdc, pn[1]);BitBlt(hdc, m_snake2.m_pos[0].x * 30, m_snake2.m_pos[0].y * 30, 30, 30, mdc, 0, 0, SRCCOPY);}//游戲重開(kāi) 開(kāi)始 void OnStart(HWND hWnd) {//食物初始化memset(foods, 0, sizeof(foods));//蛇身數(shù)據(jù)初始化init_snake();//重置計(jì)時(shí)器SetTimer(hWnd, 1, 100, NULL); } //窗口設(shè)置 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {//窗口初始化HWND hWnd;hInst = hInstance; hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);if (!hWnd){return FALSE;}RECT crc,wrc;GetClientRect(hWnd,&crc);GetWindowRect(hWnd,&wrc);int borderwidth=(wrc.right-wrc.left)-(crc.right-crc.left);int borderheight=(wrc.bottom-wrc.top)-(crc.bottom-crc.top);SetWindowPos(hWnd,NULL,0,0,950+borderwidth,630+borderheight,SWP_NOMOVE);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);//句柄給予hdc=GetDC(hWnd);mdc = CreateCompatibleDC(hdc);bufdc = CreateCompatibleDC(hdc);//素材導(dǎo)入pn[0] = (HBITMAP)LoadImage(NULL, "H1.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);pn[1] = (HBITMAP)LoadImage(NULL, "H2.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);pi1 = (HBITMAP)LoadImage(NULL, "pi1.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);pi2 = (HBITMAP)LoadImage(NULL, "pi2.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);bg = (HBITMAP)LoadImage(NULL, "bg.bmp", IMAGE_BITMAP, 333, 179, LR_LOADFROMFILE);bg2 = (HBITMAP)LoadImage(NULL, "bg2.bmp", IMAGE_BITMAP, 150, 80, LR_LOADFROMFILE);food = (HBITMAP)LoadImage(NULL, "shi.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);//播放背景音樂(lè)PlaySound("bgm.wav", NULL, SND_FILENAME | SND_ASYNC);return TRUE; }//入場(chǎng)設(shè)置 void start() {SelectObject(mdc, bg2);BitBlt(hdc, col*WIDTH + 40, 0, 150, 80, mdc, 0, 0, SRCCOPY);SelectObject(mdc, bg);BitBlt(hdc, 300, 200, 333, 3179, mdc, 0, 0, SRCCOPY); }//游戲函數(shù) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {int n;int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;TCHAR szHello[MAX_LOADSTRING];LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);//進(jìn)入開(kāi)場(chǎng)界面if (kk == 1) start();switch (message) {case WM_COMMAND:wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId){case IDM_EXIT:DestroyWindow(hWnd); //退出游戲break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_KEYDOWN:switch(wParam){//開(kāi)場(chǎng) 重開(kāi)case 32:OnStart(hWnd);break;//舞獅控制case VK_UP:m_snake.m_direction=0;break;case VK_RIGHT:m_snake.m_direction=1;break;case VK_DOWN:m_snake.m_direction=2;break;case VK_LEFT:m_snake.m_direction=3;break;//年獸控制case 87:m_snake2.m_direction = 0;break;case 68:m_snake2.m_direction = 1;break;case 83:m_snake2.m_direction = 2;break;case 65:m_snake2.m_direction = 3;break;}break;case WM_TIMER://舞獅前進(jìn)for( n=m_snake.len-1;n>=1;n--)m_snake.m_pos[n]=m_snake.m_pos[n-1];if(0==m_snake.m_direction)m_snake.m_pos[0].y=m_snake.m_pos[0].y-1;if(1==m_snake.m_direction)m_snake.m_pos[0].x=m_snake.m_pos[0].x+1;if(2==m_snake.m_direction)m_snake.m_pos[0].y=m_snake.m_pos[0].y+1;if( 3==m_snake.m_direction)m_snake.m_pos[0].x=m_snake.m_pos[0].x-1;//年獸前進(jìn)for (n = m_snake2.len - 1; n >= 1; n--)m_snake2.m_pos[n] = m_snake2.m_pos[n - 1];if (0 == m_snake2.m_direction)m_snake2.m_pos[0].y = m_snake2.m_pos[0].y - 1;if (1 == m_snake2.m_direction)m_snake2.m_pos[0].x = m_snake2.m_pos[0].x + 1;if (2 == m_snake2.m_direction)m_snake2.m_pos[0].y = m_snake2.m_pos[0].y + 1;if (3 == m_snake2.m_direction)m_snake2.m_pos[0].x = m_snake2.m_pos[0].x - 1;//捕獲食物判定for (int i = 0; i < NUMBER; i++) {if(m_snake.m_pos[0].x==m_food[i].x&&m_snake.m_pos[0].y==m_food[i].y){m_snake.len++; //身體增長(zhǎng)foods[m_food[i].x][m_food[i].y] = 0; //防止食物重復(fù)打印系數(shù) 歸零generatefood(i); //食物更新}if (m_snake2.m_pos[0].x == m_food[i].x && m_snake2.m_pos[0].y == m_food[i].y){m_snake2.len++;foods[m_food[i].x][m_food[i].y] = 0;generatefood(i);}}//舞獅 死亡判定for (int i = 1; i < m_snake2.len; i++){if (m_snake.m_pos[0].x == m_snake2.m_pos[i].x && m_snake.m_pos[0].y == m_snake2.m_pos[i].y){KillTimer(hWnd, 1);if (IDYES == MessageBox(hWnd, "年獸奪魁", "提示", MB_YESNO))OnStart(hWnd);elsePostQuitMessage(0);}}if(m_snake.m_pos[0].x>col||m_snake.m_pos[0].y>row||m_snake.m_pos[0].x<0||m_snake.m_pos[0].y<0){KillTimer(hWnd,1);if(IDYES == MessageBox(hWnd, "年獸奪魁", "提示",MB_YESNO))OnStart(hWnd);elsePostQuitMessage(0);}//年獸 死亡判定for (int i = 1; i < m_snake.len; i++){if (m_snake2.m_pos[0].x == m_snake.m_pos[i].x && m_snake2.m_pos[0].y == m_snake.m_pos[i].y){KillTimer(hWnd, 1);if (IDYES == MessageBox(hWnd, "舞獅奪魁", "提示", MB_YESNO))OnStart(hWnd);elsePostQuitMessage(0);}}if (m_snake2.m_pos[0].x > col || m_snake2.m_pos[0].y > row || m_snake2.m_pos[0].x < 0 || m_snake2.m_pos[0].y < 0){KillTimer(hWnd,1);if (IDYES == MessageBox(hWnd, "舞獅奪魁", "提示", MB_YESNO))OnStart(hWnd);elsePostQuitMessage(0);}//畫(huà)面刷新hdc=GetDC(hWnd);MyPaint(hdc);break;case WM_PAINT://畫(huà)面產(chǎn)生hdc = BeginPaint(hWnd, &ps);MyPaint(hdc);EndPaint(hWnd, &ps);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0; }?
?
?
總結(jié)
以上是生活随笔為你收集整理的Visual Studio C++/C 游戏——双人贪吃蛇 实现方法+代码讲解+算法优化+成功展示+源代码+总结(超详细,适合小白)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: My Seventy-seventh P
- 下一篇: C++ 随机函数