貪吃蛇?
沒錯,就是貪吃蛇,這個你不會不知道吧。那你肯定會疑問了,還能用代碼寫貪吃蛇?當然啦,今天我就教大家寫一個屬於自己的貪吃蛇!
你所需要準備的是:一定的鏈表知識,電腦集成編譯環境CodeBlocks(最好使用該軟件,否則可能會不成功),點個贊,關注一波~~後續有好東西,我會繼續分享的!
設計思路
首先,要先將背景打印出來,這裏需要的函數下面會介紹。然後隨機生成蛇頭,根據蛇頭生成蛇身,並將整個蛇打印出來,然後生成食物(確保不和蛇重合),這樣,第一步就完成了。接下來,到了最主要的步驟了,蛇身移動及吃食。這裏我採用的是先清除蛇身,再打印到移動後的位置,吃食同理。而蛇的方向控制需要鍵盤控制。
調用函數
void Menu(); //初始化菜單
void Gotoxy(int x, int y); //光標定位
void GotoChange(int x, int y); //將■改爲空格
void GotoPrint(int x, int y); //轉至(x,y)打印■
void CreatWall(); //生成圍牆
void CreatSnake(); //初始化生成蛇
void PrintBody(); //打印蛇身
void Initialization(); //初始化界面
void CreatFood(); //生成隨機食物
int Control(); //控制蛇
int Judge(); //評判結束
void MovingBody(); //移動蛇身
void ChangeBody(int x, int y); //改變蛇身
void Eating(); //蛇“進食”
void End(); //結束頁面
其中比較難理解且重要的函數可見:
gotoxy()函數——>傳送門
Control()裏的_kbhit()——>傳送門
Control()裏的_getch()——>傳送門
未列出的變色函數SetConsoleTextAttribute——>傳送門
代碼實現:
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<time.h>
#include<conio.h>
#define up 'w'
#define down 's'
#define left 'a'
#define right 'd'
#define stop 'p'
typedef struct snake
{
int x, y;
struct snake *next;
}SNAKE;
void Menu(); //初始化菜單
void Gotoxy(int x, int y); //光標定位
void GotoChange(int x, int y); //將■改爲空格
void GotoPrint(int x, int y); //轉至(x,y)打印■
void CreatWall(); //生成圍牆
void CreatSnake(); //初始化生成蛇
void PrintBody(); //打印蛇身
void Initialization(); //初始化界面
void CreatFood(); //生成隨機食物
int Control(); //控制蛇
int Judge(); //評判結束
void MovingBody(); //移動蛇身
void ChangeBody(int x, int y); //改變蛇身
void Eating(); //蛇“進食”
void End(); //結束頁面
char name[66];
int speed = 50, score = 0, co;
SNAKE *head, *tail;
int food_x, food_y;
char input = 1;
int main()
{
Menu();
CreatWall();
CreatSnake();
Initialization();
CreatFood();
if(Control() == 0)
return 0;
return 0;
}
void Menu()
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
| FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
Gotoxy(40, 16);
printf("歡迎打開貪吃蛇遊戲~~~\n");
Gotoxy(40, 17);
printf("請輸入您的用戶名:");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
scanf("%s", name);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
| FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
Gotoxy(40, 19);
printf("請您選擇遊戲難度:\n\
\t\t\t\t\t1:小白模式\n\
\t\t\t\t\t2:普通模式(推薦)\n\
\t\t\t\t\t3:困難模式\n\
\t\t\t\t\t4:極限模式\n\
\t\t\t\t\t5:變態模式\n\
\t\t\t\t\t6:冒險模式\n\t\t\t\t\t");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
scanf("%d", &co);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
if(co > 0 && co < 6)
speed *= (6-co);
else
speed = 300;
system("cls");
Gotoxy(42, 14);
printf("正在加載中~~~\n");
Gotoxy(20, 16);
printf("提示:\n");
Gotoxy(24, 18);
printf("請在英文輸入法中操作,反向移動等同於吃到自己,wasd控制p暫停\n");
Gotoxy(36, 20);
printf("\t全屏遊戲效果更佳喲~~~");
Sleep(3000);
system("cls");
}
void Gotoxy(int x, int y)
{
COORD pos = {x, y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 獲取標準輸出設備句柄
SetConsoleCursorPosition(hOut, pos); //兩個參數分別是指定哪個窗體,具體位置
}
void GotoPrint(int x, int y)
{
Gotoxy(x, y);
printf("■");
}
void GotoChange(int x, int y)
{
Gotoxy(x, y);
printf(" ");
}
void CreatWall()
{
int i, j;
for (i = 0; i < 36; i++)
{
for(j = 0; j < 72; j += 2)
{
if(i == 0 || i == 35 || j == 0 || j == 70)
printf("■");
else
printf(" ");
}
printf("\n");
}
}
void CreatSnake()
{
srand((unsigned)time(NULL));
head = (SNAKE*)malloc(sizeof(SNAKE));
head->x = rand()%30+3;
if(head->x % 2 != 0)
{
head->x++;
}
head->y = rand()%30+3;
tail = (SNAKE*)malloc(sizeof(SNAKE));
SNAKE *p = (SNAKE*)malloc(sizeof(SNAKE));
SNAKE *q = (SNAKE*)malloc(sizeof(SNAKE));
p->x = head->x;
p->y = head->y+1;
q->x = head->x;
q->y = head->y+2;
head->next = p;
p->next = q;
q->next = tail;
tail->next = NULL;
}
void PrintBody()
{
SNAKE *t = head;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
GotoPrint(t->x, t->y);
t = t->next;
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
while(t->next != NULL)
{
GotoPrint(t->x, t->y);
t = t->next;
}
Gotoxy(0, 36);
}
void Initialization()
{
PrintBody();
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
Gotoxy(128, 2);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("p:(開始/暫停)");
Gotoxy(120, 3);
printf("如果蛇在移動過程中,撞到牆壁或身體");
Gotoxy(120, 4);
printf("交叉(蛇頭撞到自己的身體)遊戲結束");
Gotoxy(100, 12);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("%s", name);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf(",加油加油喀~~~");
Gotoxy(100, 18);
printf("您目前的分數爲:");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
Gotoxy(116, 18);
printf("%d", score);
Gotoxy(100, 24);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("小遊戲作者:");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("ChrisPhantom");
}
void CreatFood()
{
lable:
food_y = rand()%(34) + 1;
food_x = rand()%(67) + 2;
if (food_x % 2 != 0)
{
food_x = food_x + 1;
}
SNAKE *t = head;
while(1) //遍歷排除蛇身重複
{
if(t->next == NULL)
break;
if(food_x == t->x && food_y == t->y)
{
goto lable;
}
t = t->next;
}
Gotoxy(food_x, food_y);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("⊙");
}
int Control()
{
while (1)
{
if (Judge() == 0)
return 0;
if (_kbhit())
{
input = _getch();
}
MovingBody();
Eating();
}
return 1;
}
int Judge()
{
if (head->x == 0 || head->x == 70 || head->y == 0 || head->y == 35) //撞到牆壁
{
End();
return 0;
}
SNAKE *p = head->next;
while (1)
{
if (p->next == NULL)
break;
if (head->x == p->x && head->y == p->y) //身體交叉
{
End();
return 0;
}
p = p->next;
}
return 1;
}
void MovingBody() //通過先清空後打印實現動畫效果
{
int x = head->x, y = head->y;
SNAKE *p = head;
while (1)
{
if (p->next == NULL)
break;
GotoChange(p->x, p->y);
p = p->next;
}
switch (input)
{
case up:
head->y -= 1;
ChangeBody(x, y);
break;
case down:
head->y += 1;
ChangeBody(x, y);
break;
case left:
head->x -= 2;
ChangeBody(x, y);
break;
case right:
head->x += 2;
ChangeBody(x, y);
break;
case stop:
break;
}
PrintBody();
Sleep(speed);
}
void ChangeBody(int x, int y)
{
SNAKE *p = head->next;
int mid1, mid2, tmid1, tmid2;
mid1 = p->x;
mid2 = p->y;
while (1)
{
if (p->next->next == NULL)
break;
tmid1 = p->next->x;
tmid2 = p->next->y;
p->next->x = mid1;
p->next->y = mid2;
mid1 = tmid1;
mid2 = tmid2;
p = p->next;
}
p = head->next;
//if (p->next!= NULL)
{
p->x = x;
p->y = y;
}
}
void Eating()
{
if (head->x == food_x && head->y == food_y)
{
printf("\a");
CreatFood();
SNAKE *t = (SNAKE*)malloc(sizeof(SNAKE));
SNAKE *p;
p = head;
while (1)
{
if (p->next->next == NULL)
break;
p = p->next;
}
p->next = t;
t->next = tail;
score += 10;
if(co == 6 && speed > 40)
{
speed -= 20;
}
Gotoxy(116, 18);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("%d", score);
}
}
void End()
{
system("cls");
Gotoxy(56, 14);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("%s,", name);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("您的得分爲:");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("%d", score);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
Gotoxy(56, 16);
if(score <= 30)
printf("不要氣餒,繼續加油啊 ~_~");
else if(score <= 70)
printf("你已經很不錯啦,是不是還可以更厲害呢 @_@");
else if(score <=120)
printf("你真是超級厲害啊,已經超過大多數人啦 ^_^");
else
printf("難道你...你就是傳說中的dalao !_!");
Gotoxy(48, 19);
printf("小遊戲作者:");
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("ChrisPhantom(沒錯就是我ChrisPhantom本人了,手動滑稽)");
Gotoxy(48, 20);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("如果喜歡的話,就給我點個贊吧~~~");
Gotoxy(48, 22);
system("pause");
}
參考資料
https://blog.csdn.net/qq_40935723/article/details/86553391
https://blog.csdn.net/qq_40953281/article/details/79315254
https://mbd.baidu.com/newspage/data/error
由於其中部分代碼的註釋未詳盡的解釋,不明白的可以私信諮詢。喜歡的話麻煩點個贊分享一下啦。
如果覺得本碼足夠規整而又不清楚規範,可查看另一帖子《C語言代碼規範》–>傳送門
感謝師傅來訪,技術不精,請勿吐槽,如有問題請留言。