C語言實現(xiàn)貪吃蛇小黑窗
本文實例為大家分享了C語言實現(xiàn)貪吃蛇小黑窗的具體代碼,供大家參考,具體內容如下
思路:
1.利用整型二維數(shù)組保存顯示數(shù)據(jù),小蛇每移動一次清屏并便利數(shù)組做到動態(tài)效果。每次移動(清屏)的間隔時間控制了游戲難度,這個時間應不斷縮減,直到游戲結束。
2.需要保存小蛇移動的方向,然后寫一個函數(shù)通過小蛇的移動方向去處理二維數(shù)組中的數(shù)據(jù),達到移動小蛇的目的。
3.小蛇的移動可分解為兩個過程:頭部像前方生長一格然后尾部消去一格。如果蛇頭吃到食物,尾部無需消去,此時應立即隨機生成一個新的食物。
4.游戲開始時小蛇應隨機生成在地圖某一位置,此時小蛇的默認移動方向也應該是隨機的。
5每次移動前應接收玩家由鍵盤輸入的移動方向,如果接收到后,判斷合法后將其設為小蛇的默認移動方向,如果玩家未進行任何輸入,小蛇應按照默認方向移動。
個人難點:
1.小蛇移動
該函數(shù)需要拿到蛇頭當時所在的位置坐標和小蛇的移動方向。隨后可由蛇頭位置往移動方向往前生長一格,即將二維數(shù)組中目標移動位置的數(shù)據(jù)設置為小蛇的數(shù)據(jù)。消去蛇尾另寫一個函數(shù),調用前需先判斷是否吃到食物,是否撞到墻壁或者是自身,然后決定是否削去尾部。消去蛇尾需獲得蛇尾的位置,所以我們在該函數(shù)內加入遞歸搜索蛇尾的算法:進入函數(shù)后先判斷此時的位置是否為蛇尾,若不是就將自身位置往后移動一格(將蛇身往后一格的坐標輸入給DeleteTail函數(shù),然后繼續(xù)此過程),直到遇到蛇尾,然后將其消去(置零)。
具體代碼實現(xiàn)如下:
int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t) { ?? ?int ret = 1;//默認前進成功 ?? ?//printf("trend=%d\n", trend); ?? ?switch (trend) { ?? ?case 1:*py -= 1; break;//向上 ?? ?case 2:*px -= 1; break;//向左 ?? ?case 3:*py += 1; break;//向下 ?? ?case 4:*px += 1; break;//向右 ?? ?}//找到即將前進的坐標 ?? ?if (data[*py][*px] == 6) { ?? ??? ?data[*py][*px] = trend; ?? ??? ?CreatFood(data); ?? ??? ?*t *= 0.9; ?? ?}//如果蛇頭要前進的格子是食物,向前長一格,尾部不變; ?? ?else if (data[*py][*px] == 0) { ?? ??? ?data[*py][*px] = trend;//向前長一格 ?? ??? ?DeleteTail(*px, *py, data);//消去最后的尾巴 ?? ?} ?? ?else { ?? ??? ?ret = 0; ?? ??? ?printf("前進失敗\n"); ?? ?}//前進失敗 ?? ?return ret; } ? int DeleteTail(int x, int y, int data[ROW][COL]) { ?? ?//PrintTest(data); ?? ?if (data[y][x] <= 4 && data[y][x] >= 1) { ?? ??? ?switch (data[y][x]) { ?? ??? ?case 1: ?? ??? ??? ?if (DeleteTail(x, y + 1, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 2: ?? ??? ??? ?if (DeleteTail(x + 1, y, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 3: ?? ??? ??? ?if (DeleteTail(x, y - 1, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 4: ?? ??? ??? ?if (DeleteTail(x - 1, y, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?return 1; ?? ?} ?? ?else { ?? ??? ?return 0; ?? ?} }
2.輸入
在實際代碼實現(xiàn)的過程中,我發(fā)現(xiàn)scanf函數(shù)無法實現(xiàn)需求,理由是程序執(zhí)行到scanf語句時,會停留在該位置,直到scanf函數(shù)掃描到輸入后,程序才會繼續(xù)進行。經(jīng)學習查閱,決定使用kbhit函數(shù)掃描此時鍵盤緩沖區(qū)中是否有數(shù)據(jù):如果有就讀取第一個數(shù)據(jù),并將后面的數(shù)據(jù)清空,避免后面使用該數(shù)據(jù),若沒有數(shù)據(jù),緩沖區(qū)不做任何處理,程序也應當繼續(xù)執(zhí)行。
使用kbhit函數(shù)前應“#include<conio.h>”。清理緩沖區(qū)運用的是getch()循環(huán)。代碼如下:
int Input() { ?? ?int trend = 0; ?? ?if (kbhit()) { ?? ??? ?char trend_ = getch(); ?? ??? ?while (kbhit()) { ?? ??? ??? ?getch(); ?? ??? ?}//清空緩沖區(qū) ?? ??? ?//printf("已接收到%c ", trend_); ?? ??? ?switch (trend_) { ?? ??? ?case 'w':trend = 1; break; ?? ??? ?case 'a':trend = 2; break; ?? ??? ?case 's':trend = 3; break; ?? ??? ?case 'd':trend = 4; break; ?? ??? ?default:printf("請輸入w,a,s,d以控制前進方向!!\n"); ?? ??? ??? ?break; ?? ??? ?} ?? ?} ?? ?else { ?? ??? ?printf("請輸入w,a,s,d以控制前進方向!!\n"); ?? ?} ?? ?return trend; }
完整源代碼:
#pragma once #pragma warning(disable : 4996) #include<stdio.h> #include<time.h> #include<stdlib.h> #include<Windows.h> #include<conio.h> #define ROW 30 #define COL 30 #define TIME 300 int Game(); int Menu(); int Input(); int CreatHead(int* px, int* py, int data[ROW][COL]); void CreatFood(int data[ROW][COL]); int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t); int DeleteTail(int x, int y, int data[ROW][COL]); void PrintShow(int data[ROW][COL]); int GameOver(int score); void PrintTest(int data[ROW][COL]);
#include"main.h" int main() { ?? ?int ret = 1; ?? ?while (ret) { ?? ??? ?int choose = Menu(); ?? ??? ?int score = 0; ?? ??? ?switch (choose) { ?? ??? ?case 1: ?? ??? ??? ?score = Game(); ?? ??? ??? ?ret = GameOver(score); ?? ??? ??? ?break; ?? ??? ?case 2: ?? ??? ??? ?system("cls"); ?? ??? ??? ?printf("==========================================================\n"); ?? ??? ??? ?printf(" ? ? ? ? ? ? ? ? ? ? ?游戲說明 ? ? ? ? ? ? ? ? ? ? ? ? ? ?\n"); ?? ??? ??? ?printf(" ?1.輸入‘w'‘a(chǎn)'‘s'‘d'以控制小蛇的移動。\n"); ?? ??? ??? ?printf(" ?2.小蛇在固定時間內只移動一次,如一個時間段內輸入多個方向\n則以第一次輸入為準。\n"); ?? ??? ??? ?printf(" ?3.不能撞到墻壁或者是自身。\n"); ?? ??? ??? ?printf(" ?4.小蛇移動速度會在吃到食物后加快,直到游戲結束。\n"); ?? ??? ??? ?printf(" ?輸入“1”繼續(xù)...........\n"); ?? ??? ??? ?printf("==========================================================\n"); ?? ??? ??? ?int ok = 0; ?? ??? ??? ?scanf("%d", &ok); ?? ??? ??? ?if (ok) { ?? ??? ??? ??? ?system("cls"); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ?case 3: ?? ??? ??? ?ret = 0; ?? ??? ??? ?break; ?? ??? ?} ?? ?} }
#include"main.h" int Game() { ?? ?int data[ROW][COL] = { 0 }; ?? ?int time_ = TIME; ?? ?for (int i = 0; i < COL; i++) { ?? ??? ?for (int j = 0; j < ROW; j++) { ?? ??? ??? ?if (i == 0 || i == COL - 1) { ?? ??? ??? ??? ?data[i][j] = 5;//邊界墻 ?? ??? ??? ?} ?? ??? ??? ?if (j == 0 || j == ROW - 1) { ?? ??? ??? ??? ?data[i][j] = 5;//邊界墻 ?? ??? ??? ?} ?? ??? ?} ?? ?}//初始化數(shù)據(jù)存儲數(shù)組 ?? ?//PrintShow(data); ?? ?int x = 0, y = 0; ?? ?int trend = CreatHead(&x, &y, data); ?? ?//生成蛇頭 ?? ?CreatFood(data);//生成食物 ?? ?int ret = 1; ?? ?while (ret) { ?? ??? ?system("cls"); ?? ??? ?PrintShow(data); ?? ??? ?Sleep(time_); ?? ??? ?int trend_ = Input(); ?? ??? ?if (trend_ != 0) { ?? ??? ??? ?trend = trend_; ?? ??? ?} ?? ??? ?ret = MoveSnake(trend, &x, &y, data, &time_); ?? ?} ?? ?int score = 0; ?? ?for (int i = 0; i < ROW; i++) { ?? ??? ?for (int j = 0; j < COL; j++) { ?? ??? ??? ?if (data[i][j] <= 4 && data[i][j] >= 1) { ?? ??? ??? ??? ?score++; ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?return score; } int Menu() { ?? ?int choose = 0; ?? ?while (1) { ?? ??? ?printf("==========================\n"); ?? ??? ?printf("===歡迎進入貪吃蛇游戲!===\n"); ?? ??? ?printf("=== ? 1、經(jīng)典模式 ? ? ?===\n"); ?? ??? ?printf("=== ? 2、游戲說明 ? ? ?===\n"); ?? ??? ?printf("=== ? 3、退出游戲 ? ? ?===\n"); ?? ??? ?printf("=== 請輸入您的選項... ?===\n"); ?? ??? ?printf("==========================\n"); ?? ??? ?scanf("%d", &choose); ?? ??? ?if (choose == 1 || choose == 2 || choose == 3) { ?? ??? ??? ?break; ?? ??? ?} ?? ?} ?? ?return choose; } int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t) { ?? ?int ret = 1;//默認前進成功 ?? ?//printf("trend=%d\n", trend); ?? ?switch (trend) { ?? ?case 1:*py -= 1; break;//向上 ?? ?case 2:*px -= 1; break;//向左 ?? ?case 3:*py += 1; break;//向下 ?? ?case 4:*px += 1; break;//向右 ?? ?}//找到即將前進的坐標 ?? ?if (data[*py][*px] == 6) { ?? ??? ?data[*py][*px] = trend; ?? ??? ?CreatFood(data); ?? ??? ?*t *= 0.9; ?? ?}//如果蛇頭要前進的格子是食物,向前長一格,尾部不變; ?? ?else if (data[*py][*px] == 0) { ?? ??? ?data[*py][*px] = trend;//向前長一格 ?? ??? ?DeleteTail(*px, *py, data);//消去最后的尾巴 ?? ?} ?? ?else { ?? ??? ?ret = 0; ?? ??? ?printf("前進失敗\n"); ?? ?}//前進失敗 ?? ?return ret; } void CreatFood(int data[ROW][COL]) { ?? ?srand(time(NULL)); ?? ?while (1) { ?? ??? ?int x = rand() % (COL - 2) + 1; ?? ??? ?int y = rand() % (ROW - 2) + 1; ?? ??? ?if (data[y][x] == 0) { ?? ??? ??? ?data[y][x] = 6; ?? ??? ??? ?break; ?? ??? ?} ?? ?} } ? int DeleteTail(int x, int y, int data[ROW][COL]) { ?? ?//PrintTest(data); ?? ?if (data[y][x] <= 4 && data[y][x] >= 1) { ?? ??? ?switch (data[y][x]) { ?? ??? ?case 1: ?? ??? ??? ?if (DeleteTail(x, y + 1, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 2: ?? ??? ??? ?if (DeleteTail(x + 1, y, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 3: ?? ??? ??? ?if (DeleteTail(x, y - 1, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 4: ?? ??? ??? ?if (DeleteTail(x - 1, y, data) == 0) { ?? ??? ??? ??? ?data[y][x] = 0; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?return 1; ?? ?} ?? ?else { ?? ??? ?return 0; ?? ?} } int Input() { ?? ?int trend = 0; ?? ?if (kbhit()) { ?? ??? ?char trend_ = getch(); ?? ??? ?while (kbhit()) { ?? ??? ??? ?getch(); ?? ??? ?}//清空緩沖區(qū) ?? ??? ?//printf("已接收到%c ", trend_); ?? ??? ?switch (trend_) { ?? ??? ?case 'w':trend = 1; break; ?? ??? ?case 'a':trend = 2; break; ?? ??? ?case 's':trend = 3; break; ?? ??? ?case 'd':trend = 4; break; ?? ??? ?default:printf("請輸入w,a,s,d以控制前進方向!!\n"); ?? ??? ??? ?break; ?? ??? ?} ?? ?} ?? ?else { ?? ??? ?printf("請輸入w,a,s,d以控制前進方向!!\n"); ?? ?} ?? ?return trend; } ? void PrintShow(int data[ROW][COL]) { ?? ?for (int i = 0; i < ROW; i++) { ?? ??? ?for (int j = 0; j < COL; j++) { ?? ??? ??? ?if (data[i][j] == 0) { ?? ??? ??? ??? ?printf(" ?"); ?? ??? ??? ?} ?? ??? ??? ?if (data[i][j] == 5) { ?? ??? ??? ??? ?printf("■"); ?? ??? ??? ?} ?? ??? ??? ?if (data[i][j] >= 1 && data[i][j] <= 4) { ?? ??? ??? ??? ?printf("□"); ?? ??? ??? ?} ?? ??? ??? ?if (data[i][j] == 6) { ?? ??? ??? ??? ?printf("●"); ?? ??? ??? ?} ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} } ? int CreatHead(int* px, int* py, int data[ROW][COL]) { ?? ?srand(time(NULL)); ?? ?while (1) { ?? ??? ?*px = rand() % (COL - 8) + 4; ?? ??? ?*py = rand() % (ROW - 8) + 4; ?? ??? ?if (data[*py][*px] == 0) { ?? ??? ??? ?break; ?? ??? ?} ?? ?}//蛇頭只能刷新在空格位置 ?? ?//x,y始終為蛇頭的坐標 ?? ?int trend = rand() % 4 + 1;//1:上,2:左,3:下,4:右 ?? ?data[*py][*px] = trend; ?? ?switch (trend) { ?? ?case 1:data[*py + 1][*px] = 1; ?? ??? ?data[*py + 2][*px] = 1; break; ?? ?case 2:data[*py][*px + 1] = 2; ?? ??? ?data[*py][*px + 2] = 2; break; ?? ?case 3:data[*py - 1][*px] = 3; ?? ??? ?data[*py - 2][*px] = 3; break; ?? ?case 4:data[*py][*px - 1] = 4; ?? ??? ?data[*py][*px - 2] = 4; break; ?? ?} ?? ?return trend; } void PrintTest(int data[ROW][COL]) { ?? ?printf("\n"); ?? ?for (int i = 0; i < ROW; i++) { ?? ??? ?for (int j = 0; j < COL; j++) { ?? ??? ??? ?printf("%d ", data[i][j]); ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} } ? int GameOver(int score) { ?? ?system("cls"); ?? ?printf("==============================================\n"); ?? ?printf("游戲結束,您的小蛇最終長到了%d米長...\n", score); ?? ?printf("輸入1重新開始,輸入其它退出游戲...\n"); ?? ?int ret = 0; ?? ?scanf("%d", &ret); ?? ?if (ret == 1) { ?? ??? ?return 1; ?? ?} ?? ?else { ?? ??? ?return 0; ?? ?} }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C++使用LibCurl實現(xiàn)Web隱藏目錄掃描功能
LibCurl是一個開源的免費的多協(xié)議數(shù)據(jù)傳輸開源庫,該框架具備跨平臺性,開源免費,并提供了包括HTTP、FTP、SMTP、POP3等協(xié)議的功能,本文將給大家介紹C++使用LibCurl實現(xiàn)Web隱藏目錄掃描功能2023-11-11