溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么用C語(yǔ)言寫一個(gè)貪吃蛇小游戲

發(fā)布時(shí)間:2021-08-11 14:46:10 來(lái)源:億速云 閱讀:182 作者:chen 欄目:編程語(yǔ)言

本篇內(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í)!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI