亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語言單鏈表貪吃蛇小游戲

 更新時(shí)間:2020年02月03日 10:44:00   作者:白家名  
這篇文章主要為大家詳細(xì)介紹了C語言單鏈表貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

C語言實(shí)現(xiàn)單鏈表控制臺(tái)貪吃蛇小游戲,供大家參考。

編譯環(huán)境:vs2019

需求:

統(tǒng)計(jì)游戲開始后的時(shí)間,控制貪吃蛇;吃到食物蛇身加長,得分加一;碰墻或蛇頭碰到身體減一條生命;生命消耗完則結(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í)就不難寫出來。

難點(diǎn):

wsad控制貪吃蛇上下左右移動(dòng),并清除蛇尾。

說明:

使用單鏈表實(shí)現(xiàn)貪吃蛇的核心思想是我一開始沒有想到的,部分相關(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  //貪吃蛇初始長度
#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;

 //貪吃蛇初始長度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()   //清除并釋放上一條蛇留下來的痕跡,更新生命信息
{
 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();    //清除上一條蛇留下來的痕跡,更新生命信息
 }

 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);
}

不足之處:

因?yàn)檫@是我第一次使用鏈表做一個(gè)完整的小程序,所以對(duì)鏈表的運(yùn)用還很稚嫩,在代碼規(guī)范和嚴(yán)謹(jǐn)性上面還有很多問題。

另外關(guān)于“食物如果刷新到蛇身上則再隨機(jī)產(chǎn)生一個(gè)食物”(172行)相關(guān)代碼,我不是很確定到底完不完善。

作為一名c語言新手,我對(duì)未知的知識(shí)始終抱有學(xué)習(xí)和謙卑的態(tài)度,如有貴人能夠?qū)ξ业某绦蛱岢鼋ㄗh,我將不勝感激。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 簡(jiǎn)要說明C語言中指針函數(shù)與函數(shù)指針的區(qū)別

    簡(jiǎn)要說明C語言中指針函數(shù)與函數(shù)指針的區(qū)別

    這篇文章主要介紹了C語言中指針函數(shù)與函數(shù)指針的區(qū)別,指針函數(shù)和函數(shù)指針是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-04-04
  • C++入門筆記之std::vector容器詳解

    C++入門筆記之std::vector容器詳解

    這篇文章主要給大家介紹了關(guān)于C++之std::vector容器的相關(guān)資料,vector,一種隨機(jī)訪問的數(shù)組類型,它提供了對(duì)數(shù)組元素的快速、隨機(jī)訪問,以及在序列尾部快速、隨機(jī)的插入和刪除操作,需要的朋友可以參考下
    2021-07-07
  • 實(shí)例講解C++編程中的虛函數(shù)與虛基類

    實(shí)例講解C++編程中的虛函數(shù)與虛基類

    這篇文章主要介紹了C++編程中的虛函數(shù)與虛基類的實(shí)例講解,虛函數(shù)與虛基類的使用是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-02-02
  • C語言實(shí)現(xiàn)繪制LoveBeat愛心曲線的示例代碼

    C語言實(shí)現(xiàn)繪制LoveBeat愛心曲線的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何溧陽C語言實(shí)現(xiàn)繪制LoveBeat愛心曲線,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03
  • C語言之?dāng)?shù)組名與數(shù)組起始地址的關(guān)系解析

    C語言之?dāng)?shù)組名與數(shù)組起始地址的關(guān)系解析

    這篇文章主要介紹了C語言之?dāng)?shù)組名與數(shù)組起始地址的關(guān)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 詳解C++之類和對(duì)象(2)

    詳解C++之類和對(duì)象(2)

    類是創(chuàng)建對(duì)象的模板,一個(gè)類可以創(chuàng)建多個(gè)對(duì)象,每個(gè)對(duì)象都是類類型的一個(gè)變量;創(chuàng)建對(duì)象的過程也叫類的實(shí)例化。每個(gè)對(duì)象都是類的一個(gè)具體實(shí)例(Instance),擁有類的成員變量和成員函數(shù)
    2021-11-11
  • C語言實(shí)例實(shí)現(xiàn)二叉搜索樹詳解

    C語言實(shí)例實(shí)現(xiàn)二叉搜索樹詳解

    二叉搜索樹是以一棵二叉樹來組織的。每個(gè)節(jié)點(diǎn)是一個(gè)對(duì)象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點(diǎn)的左孩子,right指向該節(jié)點(diǎn)的右孩子,p指向該節(jié)點(diǎn)的父節(jié)點(diǎn),key是它的值
    2022-05-05
  • 數(shù)據(jù)結(jié)構(gòu)之Treap詳解

    數(shù)據(jù)結(jié)構(gòu)之Treap詳解

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)之Treap詳解,本文講解了Treap的基本知識(shí)、Treap的基本操作、Treap的高級(jí)操作技巧等,需要的朋友可以參考下
    2014-08-08
  • C++編譯錯(cuò)誤variable-sized?object?may?not?be?initiali問題

    C++編譯錯(cuò)誤variable-sized?object?may?not?be?initiali問題

    這篇文章主要介紹了C++編譯錯(cuò)誤variable-sized?object?may?not?be?initiali問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • C++實(shí)現(xiàn)簡(jiǎn)單掃雷小游戲

    C++實(shí)現(xiàn)簡(jiǎn)單掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評(píng)論