C语言实现贪吃蛇(双人版本)
項目實戰合集
本專欄系列都是實戰源碼,可直接下載編譯使用;
上一篇: C語言實現學生管理系統
文章目錄
- 前言
- 一、項目介紹
- 二、項目源碼
- 總結
- 新壁紙
前言
相信很多小伙伴還不知道貪吃蛇是怎么誕生的,貪吃蛇由來介紹:
1976年,Gremlin平臺推出了一款經典街機游戲Blockade。游戲中,兩名玩家分別控制一個角色在屏幕上移動,所經之處砌起圍欄。角色只能向左、右方向90度轉彎,游戲目標保證讓對方先撞上屏幕或圍欄。
Blockade 很受歡迎,類似的游戲先后出現在 Atari 2600、TRS-80、蘋果 2 等早期游戲機、計算機上。但真正讓這種游戲形式紅遍全球的還是21年后隨諾基亞手機走向世界的貪吃蛇游戲——Snake。
一、項目介紹
該項目由C語言實現,保留了傳統貪吃蛇玩法的特色,增加了雙人對戰趣味性,代碼注釋詳細,請仔細閱讀;
二、項目源碼
/*-----------------------------------【程序說明】---------------------------- * 項目命題: 貪吃蛇之雙人版本(C語言) * 代碼所屬: 楓之劍客 * 作者: 阿甘 * 開發時間: 2019/10/02 * IDE 版 本: Visual Studio 2015 * 項目版本: 1.0.0.1 *---------------------------------------------------------------------------*/ #include <stdio.h> #include <Windows.h> #include <time.h> #include <stdlib.h> #include <conio.h> typedef struct snake { int x, y;//坐標 int direction;//移動方向 上1 左2 下3 右4 snake * next; }*Msnake; struct food { int x, y; }F; struct food2 { int x, y; }F2; struct food1 { int x, y; }F1[800]; struct food3 { int x, y; }F12[800]; int ai=0,k=0,ai2=0,k2=0,a=1,b=1; int level; //等級 int lengt = 4;//蛇長度 int lengt2 = 4;//蛇2長度 int t;//用于計時 int score = 0; //獲得成績 int score2 = 0; //2獲得成績 int l;// 用于記錄不同等級的速度 int n = 0;//吃到食物個數 int n2 = 0;//2吃到食物個數 snake * creat();//初始話蛇的位置及長度 snake * creat2();//初始話蛇2的位置及長度 void showMain();//畫出終端的大小及命名 畫出游戲界面(邊框,提示,基本成績etc) void gotoxy(int x, int y); //光標的移動 void c(int k); //顏色選擇 int time(); //用來計時 void ycgb(int k); //隱藏光標 void game(); //具體游戲運行 void draw(snake * head); //真正畫蛇 void newfood(snake * head);// //隨機產生食物并保證食物不與蛇的坐標重合 void newfood2(snake * head);// //隨機產生食物并保證食物不與蛇2的坐標重合 void newfood1(snake * head); //隨機產生障礙并保證障礙不與蛇的坐標重合 void newfood3(snake * head); //隨機產生障礙并保證障礙不與蛇2的坐標重合 int random(); //用來輸出隨機值 int direc(char ch);//方向鍵設置 int direc2(char ch);//方向鍵設置 void key(snake * head,snake*head1, snake * p,char ch); //改變蛇的方向功能的實現 void key2(snake * head,snake*head1, snake * p2,char ch); //改變蛇2的方向功能的實現 void pause(snake * head,snake*head1, snake * p,char ch); //暫停功能的實現 void cls();//清屏 void cls2();//清屏 2 int judge(int a,int b);//進行哪一方失敗判斷 int main() { ycgb(0); showMain(); game(); while (1) { cls();gotoxy(32,10);c(10); printf("按回車可重新開始游戲!"); gotoxy(34,11); printf("按Esc可離開游戲!");cls2();gotoxy(114,10); printf("按回車可重新開始游戲!"); gotoxy(116,11); printf("按Esc可離開游戲!"); char ch; ch = getch(); while (ch != 13 && ch != 27) { ch = getch(); } if (ch == 13) { showMain(); game(); } else break; } return 0; } int direc(char ch)//方向鍵設置 { if (ch == 119) return 1;if (ch == 97) return 2; if (ch == 115) return 3; if (ch == 100) return 4; return 0; } int direc2(char ch)//2方向鍵設置 { ch = getch(); if (ch == 72) return 1; if (ch == 80) return 3; if (ch == 75) return 2; if (ch == 77) return 4; return 0; } snake * creat() // 初始話蛇的位置及長度 { snake *head, *p, *q; head = (snake *) malloc (sizeof(snake)); head->x = 28; head->y = 10; head->direction = 4; head->next = NULL; p = head; for (int i = 0; i < 3; i++) { q = (snake *) malloc (sizeof(snake)); p->next = q; q->next = NULL; q->x = p->x + 2; q->y = p->y; q->direction = p->direction; p = q; } return head; } snake * creat2() // 初始話蛇2的位置及長度 { snake *head2, *p, *q; head2 = (snake *) malloc (sizeof(snake)); head2->x = 110; head2->y = 10; head2->direction = 4; head2->next = NULL; p = head2; for (int i = 0; i < 3; i++) { q = (snake *) malloc (sizeof(snake)); p->next = q; q->next = NULL; q->x = p->x + 2; q->y = p->y; q->direction = p->direction; p = q; } return head2; } void showMain()//畫出終端的大小及命名 畫出游戲界面(邊框,提示,基本成績etc) { int i; system("title 貪吃蛇.生死局雙人"); system("mode con cols=162 lines=35"); gotoxy(28, 10); c(10); printf("歡迎進入貪吃蛇的世界!!");gotoxy(108, 10); c(10); printf("歡迎進入貪吃蛇的世界!!"); gotoxy(0, 0); c(3); for (i = 0; i < 40; i++) { printf("▇"); Sleep(30); } for (i = 1; i < 25; i++) { gotoxy(78, i); printf("▇"); Sleep(30); } for (i = 39; i >= 0; i--) { gotoxy(2*i, 25); printf("▇"); Sleep(30); } for (i = 24; i >= 1; i--) { gotoxy(0, i); printf("▇"); Sleep(30); }gotoxy(82, 0); c(3); for (i = 0; i < 40; i++) { printf("▇"); Sleep(30); } for (i = 1; i < 25; i++) { gotoxy(160, i); printf("▇"); Sleep(30); } for (i = 39; i >= 0; i--) { gotoxy(2*i+82, 25); printf("▇"); Sleep(30); } for (i = 24; i >= 1; i--) { gotoxy(82, i); printf("▇"); Sleep(30); } c(10); gotoxy(30, 11); printf("請選擇難度(0~6):"); scanf("%d", &level); switch(level){case 1: l = 600;break; case 2: l = 400;break; case 3: l = 200;break; case 4: l = 150;break; case 5: l = 100;break; case 6: l = 60;break; default: l = 2333; break;} cls();cls2(); c(15); gotoxy(4, 26); printf("等級: %d", level); gotoxy(20, 26); printf("分數: %d", score); gotoxy(4, 27); printf("當前長度: %d", lengt); gotoxy(20, 27); printf("已吃食物個數: %d", n); gotoxy(45, 26); printf("移動:↑↓←→"); gotoxy(45, 27); printf("暫停or繼續:空格"); c(13); gotoxy(86, 26); printf("等級: %d", level); gotoxy(106, 26); printf("分數: %d", score); gotoxy(86, 27); printf("當前長度: %d", lengt); gotoxy(106, 27); printf("已吃食物個數: %d", n); gotoxy(127, 26); printf("移動:↑↓←→"); gotoxy(127, 27); printf("暫停or繼續:空格"); gotoxy(64,30);c(10); printf("觸碰綠色球游戲結束!黃色球能讓你的小可愛生長!");gotoxy(74,31); printf("生長到一定長度會升級哦!"); gotoxy(150, 33); printf("制作:秋志"); } void key(snake * head,snake* head1, snake * p,char ch)//改變蛇1的方向的實現 { int i, j; i = direc(ch); j = p->direction; if ((i==1&&j==3)||(i==2&&j==4)||(i==3&&j==1)||(i==4&&j==2));//判斷是否與原有方向相沖突 else p->direction = i; } void pause(snake * head,snake*head1, snake * p2,char ch)//暫停功能的實現 {int i;if(a==1){cls(); gotoxy(36,10); printf("暫停中");}if(b==1){cls2(); gotoxy(118,10); printf("暫停中");}while (1) { if (kbhit() && getch() == 32) { if(a==1){gotoxy(36,10); printf(" "); draw(head);gotoxy(F.x, F.y); c(12); printf("●");for(i=0;i<ai;i++){gotoxy(F1[i].x,F1[i].y);c(10);printf("●");}}if(b==1){gotoxy(118,10); printf(" ");draw(head1);gotoxy(F2.x, F2.y); c(12); printf("●");for(i=0;i<ai2;i++){gotoxy(F12[i].x,F12[i].y);c(10);printf("●");} }break;} } } void key2(snake * head,snake*head1, snake * p2,char ch)//改變蛇2的方向與暫停功能的實現 { int i,j; i = direc2(ch); j = p2->direction; if ((i==1&&j==3)||(i==2&&j==4)||(i==3&&j==1)||(i==4&&j==2));//判斷是否與原有方向相沖突 else p2->direction = i; } void cls() //清屏 { gotoxy(2, 1); for (int i = 1; i < 26; i++) { for (int j = 2; j < 78; j++) printf(" "); gotoxy(2, i); } } void cls2() //清屏2 { gotoxy(84, 1); for (int i = 1; i < 26; i++) { for (int j = 2; j < 78; j++) printf(" "); gotoxy(84, i); } } int random()//用來輸出隨機值 { srand(time()+rand());//將隨機數種子初始化 return rand();//返回隨機數 } void newfood(snake * head) //隨機產生食物并保證食物不與蛇的坐標重合 { int j; snake *p; p = head; int f = 1; F.x = random() % 76 + 1; if (F.x&1) F.x++; F.y = random() % 24 + 1; while (p) { if (p->x == F.x && p->y == F.y) { f = 0; break; }for(j=0;j<ai;j++){if (F1[j].x == F.x && F1[j].y == F.y) { f = 0; break; } } p = p->next; } if (f) { c(12); gotoxy(F.x, F.y); printf("●"); } else newfood(head); } void newfood2(snake * head) //隨機產生食物并保證食物不與蛇2的坐標重合 { int j; snake *p; p = head; int f = 1; F2.x = random() % 76+ 83;if(F2.x&1) F2.x++; F2.y = random() % 24 + 1; while (p) { if (p->x == F2.x && p->y == F2.y) { f = 0; break; }for(j=0;j<ai2;j++){if (F12[j].x == F2.x && F12[j].y == F2.y) { f = 0; break; } } p = p->next; } if (f) { c(12); gotoxy(F2.x, F2.y); printf("●"); } else newfood2(head); } void newfood1(snake * head) //隨機產生障礙并保證障礙不與蛇的坐標重合 { snake *p; p = head; int f = 1; F1[ai].x = random() % 76 + 1; if (F1[ai].x&1) F1[ai].x++; F1[ai].y = random() % 24 + 1; while (p) { if (p->x == F1[ai].x && p->y == F1[ai].y) { f = 0; break; } p = p->next; }if (F.x == F1[ai].x && F.y == F1[ai].y) { f = 0; } if (f) { c(10); gotoxy(F1[ai].x, F1[ai].y); printf("●"); ai++; } else newfood1(head); } void newfood3(snake * head2) //隨機產生障礙并保證障礙不與蛇2的坐標重合 { snake *p; p = head2; int f = 1; F12[ai2].x = random() % 76 + 83; if (F12[ai2].x&1)F12[ai2].x++; F12[ai2].y = random() % 24 + 1; while (p) { if (p->x == F12[ai2].x && p->y == F12[ai2].y) { f = 0; break; } p = p->next; }if (F2.x == F12[ai2].x && F2.y == F12[ai2].y) { f = 0; } if (f) { c(10); gotoxy(F12[ai2].x, F12[ai2].y); printf("●"); ai2++; } else newfood3(head2); } void draw(snake * head) //畫蛇 { gotoxy(head->x, head->y); c(12); printf("●"); c(13); head = head->next; while (head->next) { gotoxy(head->x, head->y); printf("●"); head = head->next; } c(12); gotoxy(head->x, head->y); printf("◆"); } void c(int k)//改變顏色輸出 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), k); } int time()//用來計時 { clock_t t=clock()/CLOCKS_PER_SEC; return t; } void gotoxy(int x,int y) //移動光標 { COORD coord; coord.X=x; coord.Y=y; SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord ); } void ycgb(int k)//隱藏光標 { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO cci; GetConsoleCursorInfo(hOut,&cci); cci.bVisible=k;//賦1為顯示,賦0為隱藏 SetConsoleCursorInfo(hOut,&cci); }int judge(int a,int b)//判斷失敗一方 {if(a+b==0){cls(); gotoxy(30, 10); printf("您的分數為%d", score);cls2(); gotoxy(112, 10); printf("您的分數為%d", score2);if(score>score2){gotoxy(28,11);printf("恭喜白蛇獲勝!");gotoxy(110,11);printf("恭喜白蛇獲勝!"); }if(score<score2){gotoxy(28,11);printf("恭喜粉蛇獲勝!");gotoxy(110,11);printf("恭喜粉蛇獲勝!"); }if(score==score2){gotoxy(34,11); printf("平局!");gotoxy(116,11); printf("平局!");} Sleep(2500); score = 0; n = 0;k=0; lengt = 4;score2 = 0; n2 = 0;k2=0; lengt2 = 4;return 1; }elsereturn 0; } void game() //具體游戲運行 { ai=0;ai2=0;a=b=1;int j,c1=0;char ch;snake *head, *p, *q, *s,*head2, *p2, *q2, *s2; head = creat();head2 = creat2(); s=p = head;s2=p2 = head2; while (p->next) p = p->next;while (p2->next) p2 = p2->next; draw(head);draw(head2); newfood(head);newfood2(head2); while (1) { if(a==1){q = (snake *) malloc (sizeof(snake)); p->next = q; q->direction = p->direction; q->next = NULL; switch(p->direction) { case 1: q->x = p->x; q->y = p->y - 1; break; case 2: q->x = p->x - 2; q->y = p->y; break; case 3: q->x = p->x; q->y = p->y + 1; break; case 4: q->x = p->x + 2; q->y = p->y; break; }} if(b==1){q2 = (snake *) malloc (sizeof(snake)); p2->next = q2; q2->direction = p2->direction; q2->next = NULL;switch(p2->direction) { case 1: q2->x = p2->x; q2->y = p2->y - 1; break; case 2: q2->x = p2->x - 2; q2->y = p2->y; break; case 3: q2->x = p2->x; q2->y = p2->y + 1; break; case 4: q2->x = p2->x + 2; q2->y = p2->y; break; } } if(a==1){if (q->x == F.x && q->y == F.y) //吃到食物(蛇變長并更新數據) { gotoxy(p->x, p->y); c(15); printf("●"); gotoxy(q->x, q->y); c(12); printf("◆"); p = q; score = score +level; lengt++; n++;k++;c(15); gotoxy(20, 26); printf("分數: %d", score); gotoxy(4, 27); printf("當前長度: %d", lengt); gotoxy(20, 27); printf("已吃食物個數: %d", n); if(k==8-level) {cls(); c(10); gotoxy(30, 10); printf("您的分數為%d", score);cls2(); gotoxy(112, 10); printf("您的分數為%d", score2);gotoxy(28,11);printf("恭喜白蛇獲勝!");gotoxy(110,11);printf("恭喜白蛇獲勝!");Sleep(2500);score = 0; n = 0;k=0; lengt = 4;score2 = 0; n2 = 0;k2=0; lengt2 = 4;return ;} newfood(head); }else { for(j=0;j<ai;j++)//是否撞到了障礙物 {if(F1[j].x==q->x && F1[j].y==q->y){cls(); gotoxy(30, 10); printf("您的分數為%d", score);a=0;c1=judge(a,b);if(c1)return ; }} if(a==1){gotoxy(head->x, head->y); printf(" "); head = head->next; free(s); gotoxy(head->x, head->y); c(12); printf("●"); gotoxy(p->x, p->y); c(15); printf("●"); gotoxy(q->x, q->y); c(12); printf("◆"); p = q; } }}if(b==1){if (q2->x == F2.x && q2->y == F2.y) //2吃到食物(蛇變長并更新數據) { gotoxy(p2->x, p2->y); c(13); printf("●"); gotoxy(q2->x, q2->y); c(12); printf("◆"); p2 = q2; score2 = score2 +level; lengt2++; n2++;k2++;c(13); gotoxy(106, 26); printf("分數: %d", score2); gotoxy(86, 27); printf("當前長度: %d", lengt2); gotoxy(106, 27); printf("已吃食物個數: %d", n2);if(k2==8-level) {cls();c(13); gotoxy(30, 10); printf("您的分數為%d", score);cls2(); gotoxy(112, 10); printf("您的分數為%d", score2);gotoxy(28,11);printf("恭喜粉蛇獲勝!");gotoxy(110,11);printf("恭喜粉蛇獲勝!");Sleep(2500);score = 0; n = 0;k=0; lengt = 4;score2 = 0; n2 = 0;k2=0; lengt2 = 4; return ; } newfood2(head2); }else{ for(j=0;j<ai2;j++)//2是否撞到了障礙物 {if(F12[j].x==q2->x && F12[j].y==q2->y){cls2(); gotoxy(112, 10);c(13); printf("您的分數為%d", score2);b=0; c1=judge(a,b);if(c1==1)return ;}}if(b==1){gotoxy(head2->x, head2->y); printf(" "); head2 = head2->next; free(s2); gotoxy(head2->x, head2->y); c(12); printf("●"); gotoxy(p2->x, p2->y); c(13); printf("●"); gotoxy(q2->x, q2->y); c(12); printf("◆"); p2 = q2;} }} if(a==1)newfood1(head); if(b==1)newfood3(head2); Sleep(l); if(kbhit()){ch=getch();if(ch==-32){if(b==1)key2(head2,head, q2,ch);} if(ch==115||ch==97||ch==119||ch==100){ if(a==1)key(head,head2, q,ch); }if(ch==32){pause(head,head2,q,ch);}} if(a==1){if (q->x==0||q->x==78||q->y==0||q->y==25)//碰墻結束 { cls(); gotoxy(30, 10); printf("您的分數為%d", score);a=0;c1=judge(a,b);if(c1==1)return ; }}if(a==1){s=head; while (s->next) { if (q->x == s->x && q->y == s->y)//碰自己結束 { cls(); gotoxy(30, 10); printf("您的分數為%d", score);a=0;c1=judge(a,b);if(c1==1)return ; } s = s->next; } s = head; } if(b==1){if (q2->x==82||q2->x==160||q2->y==0||q2->y==25)//2碰墻結束 { cls2(); gotoxy(112, 10); c(13); printf("您的分數為%d", score2);b=0;c1=judge(a,b);if(c1==1)return;}}if(b==1){s2=head2; while (s2->next) { if (q2->x == s2->x && q2->y == s2->y)//2碰自己結束 { cls2(); gotoxy(112, 10);c(13); printf("您的分數為%d", score2);b=0;c1=judge(a,b);if(c1==1)return ; } s2 = s2->next; } s2 = head2;} } }總結
和別的游戲不同,貪食蛇是一個悲劇性的游戲。許多電子游戲都是以操作者的勝利而告終,而貪食蛇的結局卻是死亡。不管玩得多么純熟,技術多么高超,你最終聽到的都是貪食蛇的一聲慘叫。當手機上的小蛇越長越長,積分越來越高的時候,死亡也就越來越近。那時候忙的不是為了吃豆子長身體,而是為了避免撞墻。你會發現你窮于應付,四處奔忙。貪食蛇最要命的就在一個“貪”字上。
在學習編程的過程中無疑實戰才是學習成果最好的驗證,所以要不斷的進行代碼練習以及項目實戰,本博客《項目實戰合集》專欄為各位提供了各類項目的實戰源碼,希望各位有所受益,喜歡的小伙伴記得點波關注和贊,謝謝!
新壁紙
總結
以上是生活随笔為你收集整理的C语言实现贪吃蛇(双人版本)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20180310华为面试
- 下一篇: 获取当前时间,包括农历时间