簡易版C語言貪吃蛇小游戲

[c]代碼庫

#include

#include

#include

#include

#include


/// 游戲活動區域

#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)


/// 蛇結點

typedef?struct

{

????int?x;

????int?y;

}Node;


/// 游戲相關數據

typedef?struct

{

????int?map [GAME_H][GAME_W];?// 二維數組,用于碰撞檢測

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


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

????int?length;?// 蛇身長度

????int?director;?// 蛇頭當前方向

????Node??? food;?// 食物(坐標)

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

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

}Data;


/// 句柄

HANDLE?g_hConsoleHandl;

Data gameData;


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

//

// 函數聲明

//

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

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

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

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

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


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

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

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

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


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

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


Node getNewPos (Data* data);

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

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);?// 是否死亡(結束游戲)



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

//

// 主函數 main()

//

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

int?main ()

{

????onEnter ();


????while?( TRUE ) {

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


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


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


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

????}


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

????return?0;

}


//

// 游戲開始前的處理

//

void?onEnter ()

{

????g_hConsoleHandl = GetStdHandle (STD_OUTPUT_HANDLE);?// 獲取標準輸出句柄

????CONSOLE_CURSOR_INFO cursorInfo = { 1, FALSE };?// 光標信息

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


????system?("title GameSnake");?// 設置控制臺窗口標題

}


//

// 設置光標位置

//

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

{

????COORD pos;

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

????pos.Y = y;

????// 移動到目標

????SetConsoleTextAttribute (g_hConsoleHandl, color);

????// 設置顏色

????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,?"死亡?。“慈我怄I返回");


????// pause 會顯示 按任意鍵退出?

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

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

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

}


//

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

//

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

}


//

// 初始化游戲數據

//

void?initGame (Data* data)

{

????// 設置隨機種子

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


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

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

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


????// 初始化數據

????data->length = 1;?// 蛇長度為 1

????data->director = RIGHT;?// 開始時方向向右

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

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


????// 創建蛇身

????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);?// 顯示游戲數據

}


//

// 繪制游戲邊界

//

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,?"□向下移動:↓");

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

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

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

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

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

}


//

// 顯示游戲數據

//

void?printGameData (Data* data)

{

????int?startY = 10;?// 垂直方向的起始坐標


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

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


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

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


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

????printf?("□蛇的長度: %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);

}


//

// 根據蛇頭的方向,獲取蛇頭下一個位置的坐標

//

Node getNewPos (Data* data)

{

????// 獲取蛇頭的坐標

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


????// 根據蛇頭的方向,獲取蛇頭下一個位置的坐標

????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;

}


//

// 移動蛇

//

void?move (Data* data)

{

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

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

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

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

????????return;

????}


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

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

????????data->dead = TRUE;?// 標記為死亡,退出游戲循環

????????return;

????}


????// 實現蛇的移動

????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);?// 刷新游戲數據

}


//

// 刷新畫面

//

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)

{

????// 獲取隨機坐標

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

????do?{

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

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

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


????// 設置食物坐標

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

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


????// 繪制食物

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

}


//

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

//

bool?isEatDood (Data* data)

{

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


????// 判斷是否和食物坐標重合

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

}


//

// 吃食物

//

void?eatFood (Data* data)

{

????// 增加蛇身長度

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


????data->length++;?// 蛇長度 + 1


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


????// 繪制新的節點

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


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

}


//

// 運行游戲

//

void?runGame (Data* data)

{

????char?key;

????clock_t?clockLast, clockNow;

????clockLast =?clock?();?// 獲取第一次計時


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

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

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

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

????????????// TODO: 相關鍵盤控制代碼

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

????????}


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

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

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

????????}


????????clockNow =?clock?();?// 獲取當前計時

????????// 如果時間間隔 > speed

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

????????{

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

????????????// TODO: 相關游戲邏輯代碼

????????????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;

????}

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容