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

[c]代碼庫

#include

#include

#include

#include

#include


/// 游戲活動區(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é)點

typedef?struct

{

????int?x;

????int?y;

}Node;


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

typedef?struct

{

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

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


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

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

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

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

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

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

}Data;


/// 句柄

HANDLE?g_hConsoleHandl;

Data gameData;


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

//

// 函數(shù)聲明

//

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

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

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);?// 運行游戲

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);?// 是否死亡(結(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);?// 獲取標準輸出句柄

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

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


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

}


//

// 設(shè)置光標位置

//

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

{

????COORD pos;

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

????pos.Y = y;

????// 移動到目標

????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,?"死亡J僮谩!按任意鍵返回");


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

????// 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è)置隨機種子

????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;?// 蛇長度為 1

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

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

????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,?"□提升速度:空格");

}


//

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

//

void?printGameData (Data* data)

{

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


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

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


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

}


//

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

//

Node getNewPos (Data* data)

{

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

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


????// 根據(jù)蛇頭的方向墩蔓,獲取蛇頭下一個位置的坐標

????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;?// 標記為死亡,退出游戲循環(huán)

????????return;

????}


????// 實現(xiàn)蛇的移動

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

{

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

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

????do?{

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

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

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


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

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


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

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


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

}


//

// 運行游戲

//

void?runGame (Data* data)

{

????char?key;

????clock_t?clockLast, clockNow;

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


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

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

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

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

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

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

????????}


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

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

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

????????}


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

????????// 如果時間間隔 > 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)容合作請聯(lián)系作者
  • 序言:七十年代末五慈,一起剝皮案震驚了整個濱河市纳寂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泻拦,老刑警劉巖毙芜,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異争拐,居然都是意外死亡腋粥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門架曹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來隘冲,“玉大人,你說我怎么就攤上這事绑雄≌勾牵” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵万牺,是天一觀的道長罗珍。 經(jīng)常有香客問我洽腺,道長,這世上最難降的妖魔是什么覆旱? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任蘸朋,我火速辦了婚禮,結(jié)果婚禮上扣唱,老公的妹妹穿的比我還像新娘藕坯。我一直安慰自己,他們只是感情好噪沙,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布炼彪。 她就那樣靜靜地躺著,像睡著了一般正歼。 火紅的嫁衣襯著肌膚如雪霹购。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天朋腋,我揣著相機與錄音,去河邊找鬼膜楷。 笑死旭咽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的赌厅。 我是一名探鬼主播穷绵,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼特愿!你這毒婦竟也來了仲墨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤揍障,失蹤者是張志新(化名)和其女友劉穎目养,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毒嫡,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡癌蚁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了兜畸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片努释。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖咬摇,靈堂內(nèi)的尸體忽然破棺而出伐蒂,到底是詐尸還是另有隱情,我是刑警寧澤肛鹏,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布逸邦,位于F島的核電站恩沛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏昭雌。R本人自食惡果不足惜复唤,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烛卧。 院中可真熱鬧佛纫,春花似錦、人聲如沸总放。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽局雄。三九已至甥啄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炬搭,已是汗流浹背蜈漓。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宫盔,地道東北人融虽。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像灼芭,于是被迫代替她去往敵國和親有额。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容