最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++入門指南之貪吃蛇游戲的實(shí)現(xiàn)

 更新時(shí)間:2021年10月17日 10:45:24   作者:cqu_shuai  
這篇文章主要給大家介紹了關(guān)于C++入門指南之貪吃蛇游戲?qū)崿F(xiàn)的相關(guān)資料,文章通過(guò)示例代碼介紹的非常詳細(xì),可以讓大家能短時(shí)間內(nèi)寫出一個(gè)貪吃蛇,需要的朋友可以參考下

參考

  • 《C和C++游戲趣味編程》

貪吃蛇游戲

鍵盤控制小蛇上、下、左、右移動(dòng),遲到食物后長(zhǎng)度加1;蛇頭碰到自身或窗口邊緣,游戲失敗

程序框架

#include <graphics.h>
#include <conio.h>
#include <stdio.h>

// 全局變量定義

void startup()                       // 初始化函數(shù)
{

}

void show()                          // 繪制函數(shù)
{
	
}

void updateWithoutInput()            // 與輸入無(wú)關(guān)的更新
{


}

void updateWithInput()               // 和輸入有關(guān)的更新
{

}

int main()
{
	startup();                       // 初始化函數(shù),僅執(zhí)行一次
	while (1)
	{
		show();                      // 進(jìn)行繪制
		updateWithoutInput();        // 和輸入無(wú)關(guān)的更新
		updateWithInput();           // 和輸入有關(guān)的更新
	}
	return 0;
}

繪制游戲地圖和蛇

繪制網(wǎng)格狀的游戲地圖,使用二維數(shù)組Blocks存儲(chǔ)每個(gè)網(wǎng)格的信息。二維數(shù)組Blocks中也可以記錄蛇的信息。設(shè)定元素值為0表示空,畫出灰色的方格;元素值為1表示蛇頭,蛇頭后的蛇身依次為2、3、4、5等正整數(shù),畫出彩色的方格

int i, j;
for (i = 0; i < HEIGHT; i++)
{
	for (j = 0; j < WIDTH; j++)
	{
		if (Blocks[i][j] > 0)
		{
			setfillcolor(HSVtoRGB(Blocks[i][j] * 10, 0.9, 1));
		}
		else
		{
			setfillcolor(RGB(150, 150, 150));
		}
		fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);
	}
}

小蛇向右移動(dòng)

假設(shè)小蛇初始元素值為54321,其中1位蛇頭,5432位蛇身。首先將二維數(shù)組中所有大于0的元素加1,得到65432;然后將最大值6變成0,即去除了原來(lái)的蛇尾;最后將2右邊的元素由0變成1,即實(shí)現(xiàn)了小蛇向右移動(dòng)

void moveSnake()
{
	int i, j;
	for (i = 0; i < HEIGHT; i++)
	{
		for (j = 0; j < WIDTH; j++)
		{
			if (Blocks[i][j] > 0)
			{
				Blocks[i][j]++;
			}
		}
	}
	int oldTail_i, oldTail_j, oldHead_i, oldHead_j;
	int max = 0;
	for (i = 0; i < HEIGHT; i++)
	{
		for (j = 0; j < WIDTH; j++)
		{
			if (max < Blocks[i][j])
			{
				max = Blocks[i][j];
				oldTail_i = i;
				oldTail_j = j;
			}
			if (Blocks[i][j] == 2)
			{
				oldHead_i = i;
				oldHead_j = j;
			}
		}
	}
	int newHead_i = oldHead_i;
	int newHead_j = oldHead_j;
	newHead_j = oldHead_j + 1;
	Blocks[newHead_i][newHead_j] = 1;
	Blocks[oldTail_i][oldTail_j] = 0;
}
void updateWithoutInput()            // 與輸入無(wú)關(guān)的更新
{
	moveSnake();
	Sleep(100);
}

控制小蛇4個(gè)方向移動(dòng)

變量oldHead_i、oldHead_j存儲(chǔ)移動(dòng)前的蛇頭位置,newHead_i、newHead_j存儲(chǔ)移動(dòng)后的蛇頭位置。小蛇向上移動(dòng),只需把新蛇頭的坐標(biāo)設(shè)為舊蛇頭的上方即可

newHead_i = oldHead_i - 1;

讓玩家用A、S、D、W鍵控制游戲角色移動(dòng),定義字符變量moveDirection表示小蛇運(yùn)動(dòng)方向,在moveSnake函數(shù)中對(duì)其值進(jìn)行判斷,取A向左運(yùn)動(dòng)、D向右運(yùn)動(dòng)、W向上運(yùn)動(dòng)、S向下運(yùn)動(dòng):

if (moveDirection == 'A')
{
	newHead_j = oldHead_j - 1;
}
else if (moveDirection == 'D')
{
	newHead_j = oldHead_j + 1;
}
else if (moveDirection == 'W')
{
	newHead_i = oldHead_i - 1;
}
else if (moveDirection == 'S')
{
	newHead_i = oldHead_i + 1;
}

在updateWithInput()函數(shù)中獲得用戶按鍵輸入,如果是A、S、D、W鍵之一,就更新moveDirection變量,執(zhí)行moveSnake()函數(shù)讓小蛇向?qū)?yīng)方向移動(dòng):

void updateWithInput()               // 和輸入有關(guān)的更新
{
	if (_kbhit())
	{
		char input = _getch();
		if (input == 'A' || input == 'S' || input == 'D' || input == 'W')
		{
			moveDirection = input;
			moveSnake();
		}
	}
}

時(shí)間控制的改進(jìn)

在Sleep()函數(shù)運(yùn)行時(shí),整個(gè)程序都會(huì)暫停,包括用戶輸入模塊。用戶會(huì)感覺(jué)到卡頓

利用靜態(tài)變量,將updateWithoutInput()修改如下:

void updateWithoutInput()            // 與輸入無(wú)關(guān)的更新
{
	static int waitIndex = 1;
	waitIndex++;                     // 每一幀加1
	if (waitIndex == 10)
	{
		moveSnake();
		waitIndex = 1;
	}
}

其中,updateWithoutInput()每次運(yùn)行時(shí),waitIndex加1,每隔10幀,才執(zhí)行一次移動(dòng)函數(shù)moveSnake()。這樣可在不影響用戶按鍵輸入的情況下,降低小蛇的移動(dòng)速度

失敗判斷與顯示

定義全局變量isFailure表示游戲是否失敗,初始化為0:

int isFailure = 0;

當(dāng)小蛇碰到畫面邊界時(shí),則認(rèn)為游戲失??;當(dāng)蛇頭與蛇身發(fā)生碰撞時(shí),游戲也失敗。由于每次只有蛇頭是新生成的位置,所以在moveSnake()函數(shù)中只需判斷蛇頭是否越過(guò)邊界和碰撞:

	if (newHead_i >= HEIGHT || newHead_i < 0 || newHead_j >= WIDTH || newHead_j < 0 || Blocks[newHead_i][newHead_j] > 0) 
	{
		isFailure = 1;
		return;
	}

在show()函數(shù)中添加游戲失敗后的顯示信息:
	if (isFailure)                   // 游戲失敗
	{
		setbkmode(TRANSPARENT);      // 文字字體透明
		settextcolor(RGB(255, 0, 0));
		settextstyle(80, 0, _T("宋體"));
		outtextxy(240, 220, _T("游戲失敗"));
	}

在updateWithoutInput()中添加代碼,當(dāng)isFailure為1時(shí),直接返回:

void updateWithoutInput()            // 與輸入無(wú)關(guān)的更新
{
 if (isFailure)
 {
  return;
 }
 //...
}

在updateWithInput()中,只有當(dāng)按下鍵盤且isFailure為0時(shí),才進(jìn)行相應(yīng)的處理:

void updateWithInput()               // 和輸入有關(guān)的更新
{
 if (_kbhit() && isFailure == 0)
 {
  // ...
 }
}

添加食物

添加全局變量記錄食物的位置:

int food_i, food_j;

在startup()函數(shù)中初始化食物的位置:

void startup()                       // 初始化函數(shù)
{
 food_i = rand() % (HEIGHT - 5) + 2;
 food_j = rand() % (WIDTH - 5) + 2;
}

在show()函數(shù)中在食物位置處繪制一個(gè)綠色小方塊:

setfillcolor(RGB(0, 255, 0));
fillrectangle(food_j * BLOCK_SIZE, food_i * BLOCK_SIZE, (food_j + 1) * BLOCK_SIZE, (food_i + 1) * BLOCK_SIZE);

當(dāng)新蛇頭碰到食物時(shí),只需保留原蛇尾,即可讓蛇的長(zhǎng)度加1。當(dāng)吃到食物時(shí),食物位置重新隨機(jī)出現(xiàn),蛇長(zhǎng)度加1;當(dāng)沒(méi)有遲到食物時(shí),舊蛇尾變成空白,蛇長(zhǎng)度保持不變:

Blocks[newHead_i][newHead_j] = 1;// 新蛇頭位置數(shù)值為1
if (newHead_i == food_i && newHead_j == food_j) // 如果新蛇頭碰到食物
{
 food_i = rand() % (HEIGHT - 5) + 2; // 食物重新隨機(jī)位置
 food_j = rand() % (WIDTH - 5) + 2;
}
else
{
 Blocks[oldTail_i][oldTail_j] = 0;   // 舊蛇尾變成空白
}

完整代碼

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#define BLOCK_SIZE 20                // 每個(gè)小格子的長(zhǎng)寬
#define HEIGHT 30                    // 高度上一共30個(gè)小格子
#define WIDTH 40                     // 寬度上一共40個(gè)小格子

// 全局變量定義
int Blocks[HEIGHT][WIDTH] = { 0 };
char moveDirection;
int isFailure = 0;
int food_i, food_j;                  // 食物的位置

void startup()                       // 初始化函數(shù)
{
 int i;
 Blocks[HEIGHT / 2][WIDTH / 2] = 1;  // 畫面中間畫蛇頭
 for (i = 1; i <= 4; i++)            // 向左依次4個(gè)蛇身
 {
  Blocks[HEIGHT / 2][WIDTH / 2 - i] = i + 1;
 }
 moveDirection = 'D';
 food_i = rand() % (HEIGHT - 5) + 2;
 food_j = rand() % (WIDTH - 5) + 2;
 initgraph(WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);
 setlinecolor(RGB(200, 200, 200));
 BeginBatchDraw();                   // 開(kāi)始批量繪制
}

void show()                          // 繪制函數(shù)
{
 cleardevice();
 int i, j;
 for (i = 0; i < HEIGHT; i++)
 {
  for (j = 0; j < WIDTH; j++)
  {
   if (Blocks[i][j] > 0)
   {
    setfillcolor(HSVtoRGB(Blocks[i][j] * 10, 0.9, 1));
   }
   else
   {
    setfillcolor(RGB(150, 150, 150));
   }
   fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);
  }
 }
 setfillcolor(RGB(0, 255, 0));    // 食物顏色為綠色
 fillrectangle(food_j * BLOCK_SIZE, food_i * BLOCK_SIZE, (food_j + 1) * BLOCK_SIZE, (food_i + 1) * BLOCK_SIZE);

 if (isFailure)                   // 游戲失敗
 {
  setbkmode(TRANSPARENT);      // 文字字體透明
  settextcolor(RGB(255, 0, 0));
  settextstyle(80, 0, _T("宋體"));
  outtextxy(240, 220, _T("游戲失敗"));
 }
 FlushBatchDraw();                // 批量繪制
}

void moveSnake()
{
 int i, j;
 for (i = 0; i < HEIGHT; i++)
 {
  for (j = 0; j < WIDTH; j++)
  {
   if (Blocks[i][j] > 0)     // 大于0的為小蛇元素
   {
    Blocks[i][j]++;
   }
  }
 }
 int oldTail_i, oldTail_j, oldHead_i, oldHead_j; // 存儲(chǔ)舊蛇
 int max = 0;
 for (i = 0; i < HEIGHT; i++)
 {
  for (j = 0; j < WIDTH; j++)
  {
   if (max < Blocks[i][j])
   {
    max = Blocks[i][j];
    oldTail_i = i;
    oldTail_j = j;
   }
   if (Blocks[i][j] == 2)      // 舊蛇頭
   {
    oldHead_i = i;
    oldHead_j = j;
   }
  }
 }
 int newHead_i = oldHead_i;          // 設(shè)定變量存儲(chǔ)新蛇頭
 int newHead_j = oldHead_j;

 if (moveDirection == 'A')           // 根據(jù)用戶按鍵,設(shè)定新蛇頭的位置
 {
  newHead_j = oldHead_j - 1;
 }
 else if (moveDirection == 'D')
 {
  newHead_j = oldHead_j + 1;
 }
 else if (moveDirection == 'W')
 {
  newHead_i = oldHead_i - 1;
 }
 else if (moveDirection == 'S')
 {
  newHead_i = oldHead_i + 1;
 }
 
 if (newHead_i >= HEIGHT || newHead_i < 0 || newHead_j >= WIDTH || newHead_j < 0 || Blocks[newHead_i][newHead_j] > 0) // 失敗條件
 {
  isFailure = 1;
  return;
 }

 Blocks[newHead_i][newHead_j] = 1;               // 新蛇頭位置數(shù)值為1
 if (newHead_i == food_i && newHead_j == food_j) // 如果新蛇頭碰到食物
 {
  food_i = rand() % (HEIGHT - 5) + 2;         // 食物重新隨機(jī)位置
  food_j = rand() % (WIDTH - 5) + 2;
 }
 else
 {
  Blocks[oldTail_i][oldTail_j] = 0;           // 舊蛇尾變成空白
 }
}
void updateWithoutInput()                           // 與輸入無(wú)關(guān)的更新
{
 if (isFailure)
 {
  return;
 }
 static int waitIndex = 1;
 waitIndex++;                                     // 每一幀加1
 if (waitIndex == 10)
 {
  moveSnake();
  waitIndex = 1;
 }
}

void updateWithInput()                                // 和輸入有關(guān)的更新
{
 if (_kbhit() && isFailure == 0)
 {
  char input = _getch();
  if (input == 'A' || input == 'S' || input == 'D' || input == 'W')
  {
   moveDirection = input;
   moveSnake();
  }
 }
}

int main()
{
 startup();                       // 初始化函數(shù),僅執(zhí)行一次
 while (1)
 {
  show();                      // 進(jìn)行繪制
  updateWithoutInput();        // 和輸入無(wú)關(guān)的更新
  updateWithInput();           // 和輸入有關(guān)的更新
 }
 return 0;
}

總結(jié)

到此這篇關(guān)于C++入門指南之貪吃蛇游戲?qū)崿F(xiàn)的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)貪吃蛇游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C/C++ 進(jìn)程通訊(命名管道)的實(shí)例

    C/C++ 進(jìn)程通訊(命名管道)的實(shí)例

    下面小編就為大家?guī)?lái)一篇C/C++ 進(jìn)程通訊(命名管道)的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • 一文詳解Qt中的對(duì)象樹(shù)機(jī)制

    一文詳解Qt中的對(duì)象樹(shù)機(jī)制

    Qt提供了對(duì)象樹(shù)機(jī)制,能夠自動(dòng)、有效的組織和管理繼承自QObject的Qt對(duì)象。這篇文章將通過(guò)一些示例為大家介紹一下Qt中對(duì)象樹(shù)機(jī)制的使用,需要的可以參考一下
    2023-03-03
  • 關(guān)于vs strcpy_s()和strcat_s()用法探究

    關(guān)于vs strcpy_s()和strcat_s()用法探究

    這篇文章主要介紹了關(guān)于vs strcpy_s()strcat_s()用法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Qt網(wǎng)絡(luò)編程之TCP通信及常見(jiàn)問(wèn)題

    Qt網(wǎng)絡(luò)編程之TCP通信及常見(jiàn)問(wèn)題

    這篇文章主要為大家詳細(xì)介紹了Qt網(wǎng)絡(luò)編程之TCP通信及常見(jiàn)問(wèn)題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • c++ 中vector 常見(jiàn)用法

    c++ 中vector 常見(jiàn)用法

    這篇文章主要給大家分享的是c++ 中vector 常見(jiàn)用法,,vector有兩個(gè)參數(shù),一個(gè)是size,表示當(dāng)前vector容器內(nèi)存儲(chǔ)的元素個(gè)數(shù),一個(gè)是capacity,表示當(dāng)前vector在內(nèi)存中申請(qǐng)的這片區(qū)域所能容納的元素個(gè)數(shù),下面來(lái)看看文章的詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • C語(yǔ)言基于回溯算法解決八皇后問(wèn)題的方法

    C語(yǔ)言基于回溯算法解決八皇后問(wèn)題的方法

    這篇文章主要介紹了C語(yǔ)言基于回溯算法解決八皇后問(wèn)題的方法,簡(jiǎn)單描述了八皇后問(wèn)題,并結(jié)合實(shí)例形式分析了C語(yǔ)言使用回溯算法解決八皇后問(wèn)題的相關(guān)操作技巧,需要的朋友可以參考下
    2018-06-06
  • C++選擇文件夾代碼的封裝

    C++選擇文件夾代碼的封裝

    這篇文章主要介紹了C++選擇文件夾代碼的封裝,實(shí)例展示了將選擇文件夾功能代碼封裝為一個(gè)類并對(duì)其進(jìn)行實(shí)例化調(diào)用的過(guò)程,對(duì)于學(xué)習(xí)C++程序設(shè)計(jì)有不錯(cuò)的參考價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C語(yǔ)言版約瑟夫問(wèn)題算法實(shí)現(xiàn)

    C語(yǔ)言版約瑟夫問(wèn)題算法實(shí)現(xiàn)

    大家好,本篇文章主要講的是C語(yǔ)言版約瑟夫問(wèn)題算法實(shí)現(xiàn),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你又幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C語(yǔ)言實(shí)現(xiàn)字符串拼接和拷貝

    C語(yǔ)言實(shí)現(xiàn)字符串拼接和拷貝

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)字符串拼接和拷貝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • 詳細(xì)解析C語(yǔ)言中的開(kāi)方實(shí)現(xiàn)

    詳細(xì)解析C語(yǔ)言中的開(kāi)方實(shí)現(xiàn)

    這篇文章主要介紹了詳細(xì)解析C語(yǔ)言中的開(kāi)方實(shí)現(xiàn),包括一道要求精度的整數(shù)開(kāi)方的題目,需要的朋友可以參考下
    2015-08-08

最新評(píng)論

旌德县| 固始县| 迭部县| 义马市| 交口县| 楚雄市| 微博| 休宁县| 正安县| 平昌县| 琼海市| 图片| 栾川县| 东山县| 沛县| 河津市| 图们市| 泌阳县| 全南县| 普定县| 泰和县| 酉阳| 延长县| 邳州市| 博罗县| 堆龙德庆县| 榆林市| 延津县| 龙胜| 寻甸| 鄂伦春自治旗| 罗田县| 定安县| 普兰店市| 黔江区| 尚志市| 隆昌县| 宁蒗| 惠州市| 黎平县| 伽师县|