您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“怎么用C語(yǔ)言寫一個(gè)貪吃蛇小游戲”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“怎么用C語(yǔ)言寫一個(gè)貪吃蛇小游戲”吧!
編譯環(huán)境:vs2019
需求:
統(tǒng)計(jì)游戲開始后的時(shí)間,控制貪吃蛇;吃到食物蛇身加長(zhǎng),得分加一;碰墻或蛇頭碰到身體減一條生命;生命消耗完則結(jié)束游戲。
思路:
使用wasd鍵控制蛇的移動(dòng)方向,蛇頭碰到食物得分加一,并在地圖上隨機(jī)產(chǎn)生一個(gè)食物,累加得分,碰墻或碰自己減一條生命,并初始化整條蛇,生命值為0時(shí)結(jié)束游戲。
做法:
使用單鏈表控制貪吃蛇移動(dòng)的核心思想就是:鏈表存儲(chǔ)貪吃蛇所有坐標(biāo),每次循環(huán)貪吃蛇不斷向一個(gè)方向插入一個(gè)新的結(jié)點(diǎn)作為新的蛇頭,按下按鍵控制新蛇頭產(chǎn)生的位置,然后從新蛇頭處遍歷鏈表輸出蛇身到上一個(gè)蛇尾,清除上一個(gè)蛇尾的痕跡,并釋放相關(guān)結(jié)點(diǎn)。
每次向鏈表插入新節(jié)點(diǎn)后,判斷新節(jié)點(diǎn)的坐標(biāo)是否和食物的坐標(biāo)重合,如果重合本輪循環(huán)不釋放清除蛇尾結(jié)點(diǎn),反之釋放清除上一個(gè)蛇尾的結(jié)點(diǎn)。
另外,在寫蛇生命相關(guān)代碼的時(shí)候,還需要注意一下哪些值應(yīng)該初始化,哪些值不應(yīng)該初始化。只要明白了貪吃蛇運(yùn)動(dòng)的核心思想,整個(gè)程序其實(shí)就不難寫出來(lái)。
難點(diǎn):
wsad控制貪吃蛇上下左右移動(dòng),并清除蛇尾。
說(shuō)明:
使用單鏈表實(shí)現(xiàn)貪吃蛇的核心思想是我一開始沒(méi)有想到的,部分相關(guān)代碼我學(xué)習(xí)并借鑒了一些網(wǎng)絡(luò)上搜索到的代碼,如果有違反了相關(guān)版權(quán)協(xié)議,請(qǐng)告知我修改相關(guān)代碼。
注意:
由于編譯器原因程序中_kbhit()和_getch()函數(shù)可能在其他編譯器上編譯會(huì)出現(xiàn)錯(cuò)誤,解決辦法是去掉函數(shù)前面的“_”。
運(yùn)行效果:
代碼實(shí)現(xiàn):
#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <time.h>#include <windows.h>void HideCursor(); //光標(biāo)隱藏void gotoxy(int x, int y); //光標(biāo)定位typedef struct snake{ int x; int y; struct snake* next;}snake;#define WIDTH 100 //控制臺(tái)窗口寬度#define HEIGHT 30 //控制臺(tái)窗口高度#define SNAKEN 4 //貪吃蛇初始長(zhǎng)度#define LIFE 3 //初始生命次數(shù)#define SPEED 200 //游戲速度、循環(huán)休眠時(shí)間#define U 1 //使用宏代替需要數(shù)字代替的蛇的行動(dòng)方向#define D 2 //宏名含義是各方向英文單詞首字母#define L 3 //蛇的狀態(tài),U:上 ;D:下;L:左 R:右#define R 4 void dtxxcsh() //輸出地圖{ for (int i = 1; i < WIDTH-1; i++) //輸出上下面墻 { gotoxy(i, 26); printf("-"); gotoxy(i, 0); printf("-"); } for (int i = 0; i < HEIGHT-3; i++) //輸出左右兩面墻 { gotoxy(0, i); printf("|"); gotoxy(99, i); printf("|"); } gotoxy(24, 28); printf("得分: 0 生命: %d 時(shí)間: 0 ",LIFE); //xy 30,28可用得分?jǐn)?shù)值 14個(gè)空格}int foodx, foody; //食物位置坐標(biāo)void sjcsswhs() //隨機(jī)產(chǎn)生一個(gè)食物{ srand(time(NULL)); foodx = rand() % (WIDTH - 4) + 2; //使用宏運(yùn)算隨機(jī)數(shù)最大值需要加括號(hào) while (foodx % 2) //如果食物的x坐標(biāo)不是偶數(shù),再獲取一個(gè)x坐標(biāo) { foodx = rand() % (WIDTH - 4) + 2; //寬度 } foody = rand() % (HEIGHT - 7) + 3; //高度 gotoxy(foodx, foody); printf("★");}snake* head; //蛇頭指針void cshs() //初始化蛇的位置{ snake *tail; //蛇尾指針 int i; tail = (snake*)malloc(sizeof(snake)); tail->next = NULL; tail->x = HEIGHT-6; tail->y = 8; //貪吃蛇初始長(zhǎng)度5 SNAKEN for (i = 1; i <= SNAKEN; i++) //在蛇尾處創(chuàng)建鏈表 { head = (snake*)malloc(sizeof(snake)); head->next = tail; head->x = 24 + i * 2; //head->x這個(gè)數(shù)必須為偶數(shù),和食物坐標(biāo)偶數(shù)對(duì)應(yīng) head->y = 8; tail = head; //此時(shí)蛇尾指針指向蛇頭 } while (tail) { gotoxy(tail->x, tail->y); printf("■"); tail = tail->next; }}int status = R; //蛇前進(jìn)狀態(tài)snake* p = NULL; //工作指針snake* nexthead; //下一個(gè)蛇頭int score = 0; //得分void snakemove() //蛇前進(jìn),上U,下D,左L,右R{ nexthead = (snake*)malloc(sizeof(snake)); if (status == U) { nexthead->y = head->y - 1; //確定新蛇頭的下一個(gè)坐標(biāo) x,y nexthead->x = head->x; } if (status == D) //下 { nexthead->y = head->y + 1; nexthead->x = head->x; } if (status == L) //左 { nexthead->x = head->x - 2; nexthead->y = head->y; } if (status == R) //右 { nexthead->x = head->x + 2; nexthead->y = head->y; } nexthead->next = head; head = nexthead; p = head; if (p->x == foodx && p->y == foody) //判斷蛇頭的位置是否和食物的位置重合 { while (p) //輸出尾結(jié)點(diǎn) { gotoxy(p->x, p->y); if (p == head) printf("●"); else printf("■"); p = p->next; //因?yàn)槊看芜\(yùn)動(dòng)都是新創(chuàng)建一個(gè)頭結(jié)點(diǎn)再刪除一個(gè)尾結(jié)點(diǎn), } //所以要增加一節(jié)身體,只需要這次循環(huán)不釋放尾結(jié)點(diǎn),并輸出一次尾結(jié)點(diǎn)就好了 //sjcsswhs(); //碰到食物則再產(chǎn)生一個(gè)食物 score++; gotoxy(32, 28); printf("%d", score); } else { while (p->next->next) //不輸出尾結(jié)點(diǎn) { gotoxy(p->x, p->y); if (p == head) printf("●"); else printf("■"); p = p->next; } gotoxy(p->next->x, p->next->y); printf(" "); free(p->next); p->next = NULL; } p = head; while (p) //如果食物的坐標(biāo)刷新到了蛇身上則再產(chǎn)生一個(gè)食物 * { if (p->x == foodx && p->y == foody) sjcsswhs(); p = p->next; }}void czfxhs() //操作方向函數(shù),接收從鍵盤輸入的按鍵,控制貪吃蛇行進(jìn)方向{ char ch = _getch(); switch (ch) { case 'w': if(status != D) status = U; break; case 's': if (status != U) status = D; break; case 'a': if (status != R) status = L; break; case 'd': if (status != L) status = R; break; case ' ': _getch(); break; //空格暫停 }}int yxjstjjsmz_1() //生命掉落條件1咬自己{ snake* self = head->next; //self為蛇身上的一個(gè)結(jié)點(diǎn) while (self) { if (self->x == head->x && self->y == head->y) //head和self的成員作比較,蛇頭一直存在,這里遍歷的是蛇身 { return 1; } self = self->next; } return 0;}int yxjstjjsmz_2() //生命掉落條件2碰墻{ if (head->x <= 1 || head->x >= 98 || head->y <= 0 || head->y >= 26) return 1; return 0;}int i = LIFE - 1; //變量存儲(chǔ)生命次數(shù)void qcsytmslbhs() //清除并釋放上一條蛇留下來(lái)的痕跡,更新生命信息{ p = head; int _x_ = p->x; //用于保存死掉的蛇的蛇頭處的位置,用于輸出被蛇頭頂?shù)舻膲Ρ?int _y_ = p->y; while (head) { gotoxy(head->x, head->y); printf(" "); head = head->next; free(p); p = head; } gotoxy(52, 28); //更新生命信息 printf("%d", i); if (_y_ == 0 || _y_ == HEIGHT - 4) //用于在蛇死掉后,蛇頭的位置輸出被清除蛇頭頂替掉的墻壁 { gotoxy(_x_, _y_); printf("--"); } else if (_x_ == WIDTH - 2) { gotoxy(_x_+1, _y_); printf("|"); } else if(_x_ == 0) { gotoxy(_x_, _y_); printf("|"); }}void sbjsjmhs() //失敗結(jié)束界面{ p = head; //釋放內(nèi)存 while (head) { head = head->next; free(p); p = head; } system("cls"); gotoxy(45, 12); printf("游戲結(jié)束!"); gotoxy(44, 14); printf("最終得分:%d", score); gotoxy(0,28);}int updatetime() //獲取一次電腦現(xiàn)在的時(shí)間{ int now; SYSTEMTIME system_time; GetLocalTime(&system_time); now = system_time.wMinute * 60 + system_time.wSecond; return now;}int time_1 = updatetime(); //保存游戲剛開始的時(shí)間void gametime() //寫在每次循環(huán)之內(nèi){ int time_2 = updatetime() - time_1; //更新游戲開始后時(shí)間,用現(xiàn)在的時(shí)間減去剛開始的時(shí)間 gotoxy(72, 28); printf("%d s", time_2);}int main()//主函數(shù){ system("mode con cols=100 lines=30"); //設(shè)置控制臺(tái)大小 system("title 貪吃蛇游戲"); //設(shè)置標(biāo)題 HideCursor(); //隱藏光標(biāo) sjcsswhs(); //初始化隨機(jī)產(chǎn)生一個(gè)食物 dtxxcsh(); //初始化地圖、信息 for (; i >= 0; i--) //生命 { cshs(); //初始化蛇的位置 status = R; //初始化運(yùn)動(dòng)方向 while (1) { snakemove(); //蛇行動(dòng)動(dòng)畫,方向被控制變量控制 if (_kbhit()) { czfxhs(); //接收鍵盤按鍵,控制控制變量 } if (yxjstjjsmz_1() || yxjstjjsmz_2())//兩個(gè)掉落生命的條件 break; gametime(); //更新游戲時(shí)間 Sleep(SPEED); } qcsytmslbhs(); //清除上一條蛇留下來(lái)的痕跡,更新生命信息 } sbjsjmhs(); //失敗結(jié)束界面 return 0;}void HideCursor(){ CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);}void gotoxy(int x, int y){ COORD pos = { x,y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);}
到此,相信大家對(duì)“怎么用C語(yǔ)言寫一個(gè)貪吃蛇小游戲”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。