簡(jiǎn)易版C語(yǔ)言貪吃蛇小游戲

[c]代碼庫(kù)

#include

#include

#include

#include

#include


/// 游戲活動(dòng)區(qū)域

#define GAME_W? 20

#define GAME_H? 14


/// 方向

#define UP????? 72

#define DOWN??? 80

#define LEFT??? 75

#define RIGHT?? 77


#define gotoxyInGameAndPrint(x, y, color, ch) gotoxyAndPrint(x + 1, y + 1, color, ch)


/// 蛇結(jié)點(diǎn)

typedef?struct

{

????int?x;

????int?y;

}Node;


/// 游戲相關(guān)數(shù)據(jù)

typedef?struct

{

????int?map [GAME_H][GAME_W];?// 二維數(shù)組,用于碰撞檢測(cè)

????Node??? snake [GAME_H * GAME_W];?// 蛇身


????double?speed;?// 速度

????int?length;?// 蛇身長(zhǎng)度

????int?director;?// 蛇頭當(dāng)前方向

????Node??? food;?// 食物(坐標(biāo))

????bool?pause;?// 游戲暫停

????bool?dead;?// 是否死亡

}Data;


/// 句柄

HANDLE?g_hConsoleHandl;

Data gameData;


//-------------------------------------------------------------------

//

// 函數(shù)聲明

//

//-------------------------------------------------------------------

void?gotoxyAndPrint (int?x,?int?y, unsigned color,?char* ch);?// 設(shè)置光標(biāo)位置并打印

void?onEnter ();?// 游戲開始前的處理

void?gameMenu ();?// 游戲菜單

void?lostGame ();?// 游戲失敗


void?drawGameBorder (int?w,?int?h);?// 繪制游戲邊界

void?printPrompting ();?// 顯示提示信息

void?printGameData (Data* data);?// 顯示游戲數(shù)據(jù)

void?initGame (Data* data);?// 初始化游戲數(shù)據(jù)


void?runGame (Data* data);?// 運(yùn)行游戲

void?keyDownControl (Data* data,?char?key);?// 鍵盤按鍵控制


Node getNewPos (Data* data);

void?move (Data* data);?// 移動(dòng)蛇

void?updateMap (Data* data);?// 更新 map

void?repaint (Data* data);?// 刷新畫面


void?createFood (Data* data);?// 生成食物

bool?isEatDood (Data* data);?// 判斷前方是否有食物可吃

void?eatFood (Data* data);?// 吃食物


bool?isDead (Data* data);?// 是否死亡(結(jié)束游戲)



//-------------------------------------------------------------------

//

// 主函數(shù) main()

//

//-------------------------------------------------------------------

int?main ()

{

????onEnter ();


????while?( TRUE ) {

????????gameMenu ();


????????initGame (&gameData);


????????runGame (&gameData);


????????lostGame ();

????}


????system?("pause");

????return?0;

}


//

// 游戲開始前的處理

//

void?onEnter ()

{

????g_hConsoleHandl = GetStdHandle (STD_OUTPUT_HANDLE);?// 獲取標(biāo)準(zhǔn)輸出句柄

????CONSOLE_CURSOR_INFO cursorInfo = { 1, FALSE };?// 光標(biāo)信息

????SetConsoleCursorInfo (g_hConsoleHandl, &cursorInfo);?// 隱藏光標(biāo)


????system?("title GameSnake");?// 設(shè)置控制臺(tái)窗口標(biāo)題

}


//

// 設(shè)置光標(biāo)位置

//

void?gotoxyAndPrint (int?x,?int?y, unsigned color,?char* ch)

{

????COORD pos;

????pos.X = x << 1;

????pos.Y = y;

????// 移動(dòng)到目標(biāo)

????SetConsoleTextAttribute (g_hConsoleHandl, color);

????// 設(shè)置顏色

????SetConsoleCursorPosition (g_hConsoleHandl, pos);

????printf?("%s", ch);

}


//

// 游戲菜單

//

void?gameMenu ()

{

????gotoxyAndPrint (15, 5, 0x0F,?"┏━━━━━┓");


????gotoxyAndPrint (15, 6, 0x0F,?"");

????printf?("┃? %s? ┃",?"貪食蛇");

????gotoxyAndPrint (15, 7, 0x0F,?"┗━━━━━┛");


????gotoxyAndPrint (14, 10, 0x0F,?" 按任意鍵開始游戲 ");


????while?( _getch () ) {

????????system?("cls");

????????break;

????}

}


//

// 游戲失敗

//

void?lostGame ()

{

????gotoxyAndPrint (6, 6, 0x7,?"死亡!!按任意鍵返回");


????// pause 會(huì)顯示 按任意鍵退出?

????// pause>nul 就是將顯示的內(nèi)容重定向到nul 就是 不顯示按任意鍵退出

????system?("pause > nul");

????system?("cls");?// 清屏

}


//

// 是否死亡(結(jié)束游戲)

//

bool?isDead (Data* data)

{

????Node pos = getNewPos (data);


????return?( pos.x < 0 || pos.x > GAME_W - 1 || pos.y < 0 || pos.y > GAME_H - 1 || data->map [pos.y][pos.x] );

}


//

// 初始化游戲數(shù)據(jù)

//

void?initGame (Data* data)

{

????// 設(shè)置隨機(jī)種子

????srand?(( unsigned?int?)?time?(NULL));


????// 將 dot(游戲數(shù)據(jù)) 和 node(蛇身) 全部置0

????memset?(data, 0,?sizeof( Data ));

????memset?(data->snake, 0,?sizeof( Node ) * 50);


????// 初始化數(shù)據(jù)

????data->length = 1;?// 蛇長(zhǎng)度為 1

????data->director = RIGHT;?// 開始時(shí)方向向右

????data->dead = FALSE;?// 不暫停

????data->speed = 0.3;?// 速度


????// 創(chuàng)建蛇身

????data->snake [1].x =?rand?() % ( GAME_W - 5 );

????data->snake [1].y =?rand?() % GAME_H;

????data->snake [0] = data->snake [1];


????// 生成食物

????createFood (data);


????drawGameBorder (GAME_W, GAME_H);?// 繪制邊界

????printPrompting ();?// 顯示提示信息

????printGameData (&gameData);?// 顯示游戲數(shù)據(jù)

}


//

// 繪制游戲邊界

//

void?drawGameBorder (int?w,?int?h)

{

????int?x, y;


????// 打印上下邊界

????for?( x = 0; x < w + 1; x++ ) {

????????gotoxyAndPrint (x, 0, 0x7,?"■");


????????gotoxyAndPrint (x, h + 1, 0x7,?"■");

????}

????// 打印左右邊界

????for?( y = 0; y < h + 2; y++ ) {

????????gotoxyAndPrint (0, y, 0x7,?"■");


????????gotoxyAndPrint (w + 1, y, 0x7,?"■");

????}

}


//

// 顯示提示信息

//

void?printPrompting ()

{

????gotoxyAndPrint (GAME_W + 4, 1, 0x9,?"■游戲提示:");

????gotoxyAndPrint (GAME_W + 4, 3, 0x9,?"□向下移動(dòng):↓");

????gotoxyAndPrint (GAME_W + 4, 4, 0x9,?"□向上移動(dòng):↑");

????gotoxyAndPrint (GAME_W + 4, 5, 0x9,?"□向左移動(dòng):←");

????gotoxyAndPrint (GAME_W + 4, 6, 0x9,?"□向右移動(dòng):→");

????gotoxyAndPrint (GAME_W + 4, 7, 0x9,?"□暫停游戲:回車");

????gotoxyAndPrint (GAME_W + 4, 8, 0x9,?"□提升速度:空格");

}


//

// 顯示游戲數(shù)據(jù)

//

void?printGameData (Data* data)

{

????int?startY = 10;?// 垂直方向的起始坐標(biāo)


????// GAME_W + 4 : 右邊界在空 2 格

????gotoxyAndPrint (GAME_W + 4, startY, 0xD,?"■游戲數(shù)據(jù):");


????gotoxyAndPrint (GAME_W + 4, startY + 2, 0xD,?"");

????printf?("□移動(dòng)速度: %.2lf", data->speed);


????gotoxyAndPrint (GAME_W + 4, startY + 3, 0xD,?"");

????printf?("□蛇的長(zhǎng)度: %d", data->length);


????gotoxyAndPrint (GAME_W + 4, startY + 4, 0xD,?"");

????printf?("□食物位置:( %2d - %2d )? ", data->food.x, data->food.y);


????gotoxyAndPrint (GAME_W + 4, startY + 5, 0xD,?"");

????printf?("□蛇頭位置:( %2d - %2d )? ", data->snake [data->length].x, data->snake [data->length].y);

}


//

// 根據(jù)蛇頭的方向,獲取蛇頭下一個(gè)位置的坐標(biāo)

//

Node getNewPos (Data* data)

{

????// 獲取蛇頭的坐標(biāo)

????Node newPos = data->snake [data->length];


????// 根據(jù)蛇頭的方向,獲取蛇頭下一個(gè)位置的坐標(biāo)

????switch?( data->director ) {

????case?UP:

????????newPos.y--;

????????break;

????case?DOWN:

????????newPos.y++;

????????break;

????case?LEFT:

????????newPos.x--;

????????break;

????case?RIGHT:

????????newPos.x++;

????????break;

????}

????return?newPos;

}


//

// 移動(dòng)蛇

//

void?move (Data* data)

{

????// 判斷前方是否有食物,如果有食物,先吃掉食物,再生成新的食物

????if?( isEatDood (data) ) {

????????eatFood (data);?// 吃掉食物

????????createFood (data);?// 生成新的食物

????????return;

????}


????// 判斷是否死亡(即碰到邊界 或 自己)

????if?( isDead (data) ) {

????????data->dead = TRUE;?// 標(biāo)記為死亡,退出游戲循環(huán)

????????return;

????}


????// 實(shí)現(xiàn)蛇的移動(dòng)

????memmove?(data->snake, data->snake + 1,?sizeof( data->snake [0] ) * data->length);

????data->snake [data->length] = getNewPos (data);


????updateMap (data);?// 更新 map


????repaint (data);?// 重繪蛇

????printGameData (data);?// 刷新游戲數(shù)據(jù)

}


//

// 刷新畫面

//

void?repaint (Data* data)

{

????// 先擦除尾巴

????gotoxyInGameAndPrint (data->snake [0].x, data->snake [0].y, 0xC,?" ");


????// 新顯示蛇頭

????gotoxyInGameAndPrint (data->snake [data->length].x, data->snake [data->length].y, 0xC,?"■");

}


//

// 更新 map

//

void?updateMap (Data* data)

{

????data->map [data->snake [data->length].y][data->snake [data->length].x] = 1;

????data->map [data->snake [0].y][data->snake [0].x] = 0;

}


//

// 生成食物

//

void?createFood (Data* data)

{

????// 獲取隨機(jī)坐標(biāo)

????int?x = 0, y = 0;

????do?{

????????x =?rand?() % GAME_W;

????????y =?rand?() % GAME_H;

????}?while?( data->map [y][x] );


????// 設(shè)置食物坐標(biāo)

????data->food.x = x;

????data->food.y = y;


????// 繪制食物

????gotoxyInGameAndPrint (data->food.x, data->food.y, 0xA,?"■");

}


//

// 判斷前方是否有食物可吃

//

bool?isEatDood (Data* data)

{

????Node pos = getNewPos (data);?// 獲取蛇頭的下一個(gè)位置坐標(biāo)


????// 判斷是否和食物坐標(biāo)重合

????return?( pos.x == data->food.x && pos.y == data->food.y );

}


//

// 吃食物

//

void?eatFood (Data* data)

{

????// 增加蛇身長(zhǎng)度

????data->snake [data->length + 1] = getNewPos (data);


????data->length++;?// 蛇長(zhǎng)度 + 1


????updateMap (data);?// 更新 map


????// 繪制新的節(jié)點(diǎn)

????gotoxyInGameAndPrint (data->snake [data->length].x, data->snake [data->length].y, 0xC,?"■");


????printGameData (data);?// 刷新游戲數(shù)據(jù)

}


//

// 運(yùn)行游戲

//

void?runGame (Data* data)

{

????char?key;

????clock_t?clockLast, clockNow;

????clockLast =?clock?();?// 獲取第一次計(jì)時(shí)


????while?( !data->dead ) {

????????// 獲取鍵盤輸入

????????while?( _kbhit () ) {

????????????key = _getch ();

????????????// TODO: 相關(guān)鍵盤控制代碼

????????????keyDownControl (data, key);

????????}


????????// 暫停

????????if?( data->pause ) {

????????????continue;

????????}


????????clockNow =?clock?();?// 獲取當(dāng)前計(jì)時(shí)

????????// 如果時(shí)間間隔 > speed

????????if?( clockNow - clockLast > data->speed * CLOCKS_PER_SEC )

????????{

????????????clockLast = clockNow;

????????????// TODO: 相關(guān)游戲邏輯代碼

????????????move (data);

????????}

????}

}


//

// 鍵盤控制處理

//

void?keyDownControl (Data* data,?char?key)

{

????// 暫停

????if?( key == 13 ) {

????????data->pause = !data->pause;

????}

????// 不處理

????if?( data->pause ) {

????????return;

????}


????switch?( key ) {

????case?72:?/* 上 */

????????if?( data->director != DOWN ) {

????????????data->director = UP;

????????}

????????break;

????case?80:?/* 下 */

????????if?( data->director != UP ) {

????????????data->director = DOWN;

????????}

????????break;

????case?75:?/* 左 */

????????if?( data->director != RIGHT ) {

????????????data->director = LEFT;

????????}

????????break;

????case?77:?/* 右 */

????????if?( data->director != LEFT ) {

????????????data->director = RIGHT;

????????}

????????break;

????case?' ':

????????data->speed -= 0.05;

????????break;

????}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容