当前位置:   article > 正文

用C语言写一个贪吃蛇游戏_c语言贪吃蛇游戏代码

c语言贪吃蛇游戏代码

一、游戏界面

 二、代码

consfun.h

  1. /* WINDOWS命令窗口编程常用功能实现
  2. 李乾宝,2010年12月
  3. */
  4. void consinit(short x,short y);
  5. void gotoxy(int,int);
  6. void clrscr(void);
  7. void textcolor(short newcolor);
  8. void textbackground(short newcolor);
  9. void textattr(short newattr);
  10. void HideCursor();

snake.c

  1. #include"consfun.h"
  2. #include<conio.h>
  3. #include<stdio.h>
  4. #include<Windows.h>
  5. #include<time.h>
  6. #define UP 72
  7. #define DOWN 80
  8. #define LEFT 75
  9. #define RIGHT 77
  10. int i,j;
  11. int mode=0; //游戏模式
  12. int n=4; //n=1,2,3,4分别表示用户控制蛇的方向
  13. int food_sum=0; //累计吃的食物
  14. int food=0; //食物
  15. int fx=5,fy=5; //事物的坐标
  16. int score=0; //分数
  17. int top_score[3]; //最高分
  18. int speed=200; //蛇的速度
  19. int Mode=1; //是否可以穿墙,1不可穿墙,2可以
  20. #define high 28
  21. #define width 45 //围墙的高和宽
  22. int x=high/2,y=width/2; //蛇头的坐标
  23. int snake[high][width+10]={0};//用来储存蛇,围墙,食物
  24. void gx() //蛇数组元素全部归0
  25. {
  26. for(i=1;i<high-1;i++)
  27. for(j=1;j<width-1;j++)
  28. snake[i][j]=0;
  29. }
  30. void chu_shi_hua() //每次重新开始,数据数据都要初始化
  31. {
  32. n=4; //n=1,2,3,4分别表示用户控制蛇的方向
  33. food_sum=0; //累计吃的食物
  34. food=0; //食物
  35. fx=5,fy=5; //食物的坐标
  36. score=0; //分数
  37. speed=300; //蛇的速度(这个越大越慢)
  38. Mode=1; //游戏模式
  39. x=high/2,y=width/2; //蛇头的坐标
  40. switch(mode)
  41. {
  42. case 1:for(j=5;j<width-5;j++)//基本围墙已经在page_1函数初始化,所以只需初始化新增的墙壁
  43. {
  44. snake[high/2-1][j]=-1;
  45. };break;
  46. case 2:for(j=10;j<=width-10;j++)//基本围墙已经在page_1函数初始化,所以只需初始化新增的墙壁
  47. {
  48. if(j<20||j>25)
  49. {
  50. snake[high/4][j]=-1;
  51. snake[3*high/4][j]=-1;
  52. }
  53. }
  54. for(i=high/4;i<=3*high/4;i++)
  55. {
  56. if(i<high/4+5||i>3*high/4-5)
  57. {
  58. snake[i][10]=-1;
  59. snake[i][width-10]=-1;
  60. }
  61. };break;
  62. case 3:for(j=3;j<=width-3;j++)//基本围墙已经在page_1函数初始化,所以只需初始化新增的墙壁
  63. {
  64. if((j>=3&&j<=6)||(j>=width-7&&j<=width-4))//初始化四个角的四个横
  65. {
  66. snake[6][j]=-1;
  67. snake[high-7][j]=-1;
  68. }
  69. if((j>=width/4&&j<=width/4+6)||(j>=3*width/4-8&&j<=3*width/4))//初始化‘F’的第一横和‘T’的横
  70. {
  71. snake[8][j]=-1;
  72. }
  73. if((j>=width/4&&j<=width/4+6))//初始化‘F’的第二横
  74. {
  75. snake[high/2-1][j]=-1;
  76. }
  77. }
  78. for(i=3;i<=high-3;i++)
  79. {
  80. if((i>=3&&i<=6)||(i>=high-6&&i<high-3))//初始化四个角的四个竖
  81. {
  82. snake[i][6]=-1;
  83. snake[i][width-7]=-1;
  84. }
  85. if(i>=8&&i<=high-8)//初始化‘F’的竖
  86. {
  87. snake[i][width/4]=-1;
  88. }
  89. if(i>=8&&i<=high-8&&i!=high/2)//初始化‘T’的竖
  90. {
  91. snake[i][3*width/4-4]=-1;
  92. }
  93. };break;
  94. case 4:for(j=3;j<=width-3;j++)//基本围墙已经在page_1函数初始化,所以只需初始化新增的墙壁
  95. {
  96. if((j>=3&&j<=6)||(j>=width-7&&j<=width-4))//初始化四个角的四个横
  97. {
  98. snake[6][j]=-1;
  99. snake[high-7][j]=-1;
  100. }
  101. }
  102. for(i=3;i<=high-3;i++)
  103. {
  104. if((i>=3&&i<=6)||(i>=high-6&&i<high-3))//初始化四个角的四个竖
  105. {
  106. snake[i][6]=-1;
  107. snake[i][width-7]=-1;
  108. }
  109. }
  110. for(i=0;i<high;i++)
  111. for(j=0;j<width;j++)
  112. {
  113. if(i==high/2+1&&(j==width/2-2||j==width/2))//鼻子
  114. {
  115. snake[i][j]=-1;
  116. }
  117. if(i==high/2-1&&j==width/2-1)//鼻子
  118. {
  119. snake[i][j]=-1;
  120. }
  121. if(i==high/2-4&&(j==width/2-3||j==width/2+1||j==width/2-6||j==width/2+4))//眉毛
  122. {
  123. snake[i][j]=-1;
  124. }
  125. if(i==high/2-5&&(j==width/2-4||j==width/2+2))
  126. {
  127. snake[i][j]=-1;
  128. }
  129. if(i==high/2-6&&(j==width/2-5||j==width/2+3))
  130. {
  131. snake[i][j]=-1;
  132. }
  133. if(i==high/2-7&&(j==width/2-6||j==width/2+4))
  134. {
  135. snake[i][j]=-1;
  136. }
  137. if(i==high/2-8&&(j==width/2-7||j==width/2+5||j==width/2-9||j==width/2+7))
  138. {
  139. snake[i][j]=-1;
  140. }
  141. if(i==high/2-9&&(j==width/2-8||j==width/2+6))
  142. {
  143. snake[i][j]=-1;
  144. }
  145. if(i==high/2+4&&j>=width/2-4&&j<=width/2+2)//嘴巴
  146. {
  147. snake[i][j]=-1;
  148. }
  149. if(i==high/2+5&&j>=width/2-2&&j<=width/2)//嘴巴
  150. {
  151. snake[i][j]=-1;
  152. }
  153. }
  154. ;break;
  155. }
  156. snake[high/2][width/2]=1; //以下将蛇头数值设为1
  157. for(i=1;i<5+food_sum;i++) //以下将蛇身数值设为>1
  158. snake[high/2][width/2-i]=1+i;
  159. }
  160. void page_1()首页,功能选择页
  161. {
  162. char input,*p[5]={" ","简单","困难","复杂","开挂"};
  163. gx();///将数组全部元素归0,因为在选择重新开始的时候要将游戏区内容清除
  164. for(j=0;j<width+10;j++) //以下将围墙数值设为-1
  165. {
  166. snake[0][j]=-1;
  167. snake[high-1][j]=-1;
  168. }
  169. for(i=0;i<high;i++)
  170. {
  171. snake[i][0]=-1;
  172. snake[i][width-1]=-1;
  173. snake[i][width+9]=-1;
  174. }
  175. while(1)
  176. {
  177. for(i=0;i<high;i++)
  178. for(j=0;j<width+10;j++)
  179. {
  180. if(snake[i][j]==-1) //画出围墙
  181. {
  182. textbackground(3);
  183. gotoxy(i,2*j);
  184. printf(" ");
  185. }
  186. if(i==high/2-6&&j==width/2-7)
  187. {textattr(06);
  188. gotoxy(i,2*j);
  189. printf("@@");
  190. textattr(32);
  191. printf(" ");}
  192. if(i==high/2-3&&j==width/2-5)
  193. {textattr(03);
  194. gotoxy(i,2*j);
  195. printf("欢迎来到贪吃蛇游戏!");}
  196. if(i==high/2-1&&j==width/2-2)
  197. {textattr(03);
  198. gotoxy(i,2*j);
  199. printf("1.简单");}
  200. if(i==high/2&&j==width/2-2)
  201. {textattr(03);
  202. gotoxy(i,2*j);
  203. printf("2.困难");}
  204. if(i==high/2+1&&j==width/2-2)
  205. {textattr(03);
  206. gotoxy(i,2*j);
  207. printf("3.复杂");}
  208. if(i==high/2+2&&j==width/2-2)
  209. {textattr(03);
  210. gotoxy(i,2*j);
  211. printf("4.开挂");}
  212. if(i==high/2+4&&j==width/2-5)
  213. {textattr(06);
  214. gotoxy(i,2*j);
  215. printf("你选择的模式是:%s",p[mode]);}
  216. if(i==high/2+6&&j==width/2-5)
  217. {textattr(03);
  218. gotoxy(i,2*j);
  219. printf("请按回车开始游戏");}
  220. }
  221. if(kbhit())//当按键时执行
  222. {
  223. input=getch();
  224. if(input=='1')
  225. {mode=1;}
  226. if(input=='2')
  227. {mode=2;}
  228. if(input=='3')
  229. {mode=3;}
  230. if(input=='4')
  231. {mode=4;}
  232. if(input==13)13是回车的ASCII码,按回车开始游戏
  233. {break;}
  234. }
  235. }
  236. }
  237. void draw() //画围墙、蛇、食物
  238. {
  239. while(food==0&&snake[fx][fy]!=0)//当食物生成的位置不是空位置,重新生成
  240. {
  241. fx=rand()%(high-1)+1;
  242. fy=rand()%(width-2)+2;
  243. }
  244. snake[fx][fy]=-2;
  245. food=1;
  246. for(i=0;i<high;i++)
  247. for(j=0;j<width+10;j++)
  248. {
  249. if(snake[i][j]==-1) //画出围墙
  250. {
  251. textbackground(3);
  252. gotoxy(i,2*j);
  253. printf(" ");
  254. }
  255. else if(snake[i][j]==0&&j<width) //画出空白的空间
  256. {
  257. textattr(03);
  258. gotoxy(i,2*j);
  259. printf(" ");
  260. }
  261. else if(snake[i][j]==1) //画出蛇头
  262. {
  263. textattr(06);
  264. gotoxy(i,2*j);
  265. printf("@@");
  266. }
  267. else if(snake[i][j]>1) //画出蛇身
  268. {
  269. textattr(06);
  270. textbackground(2);
  271. gotoxy(i,2*j);
  272. printf(" ");
  273. }
  274. else if(snake[i][j]==-2)
  275. {
  276. textcolor(06);
  277. gotoxy(fx,2*fy);
  278. printf("●");
  279. }
  280. if(i==2&&j==width+2)
  281. {textattr(03);
  282. gotoxy(i,2*j);
  283. printf("w或↑键向上");}
  284. if(i==4&&j==width+2)
  285. {textattr(03);
  286. gotoxy(i,2*j);
  287. printf("s或↓键向下");}
  288. if(i==6&&j==width+2)
  289. {textattr(03);
  290. gotoxy(i,2*j);
  291. printf("a或←键向左");}
  292. if(i==8&&j==width+2)
  293. {textattr(03);
  294. gotoxy(i,2*j);
  295. printf("d或→键向右");}
  296. if(i==10&&j==width+2)
  297. {textattr(03);
  298. gotoxy(i,2*j);
  299. printf("空格键暂停");}
  300. if(i==12&&j==width+2)
  301. {textattr(03);
  302. gotoxy(i,2*j);
  303. printf("p键:慢");}
  304. if(i==14&&j==width+2)
  305. {textattr(03);
  306. gotoxy(i,2*j);
  307. printf("l键:中");}
  308. if(i==16&&j==width+2)
  309. {textattr(03);
  310. gotoxy(i,2*j);
  311. printf("m键:快");}
  312. if(i==18&&j==width+2)
  313. {textattr(03);
  314. gotoxy(i,2*j);
  315. printf("t键:模式1");
  316. }
  317. if(i==20&&j==width+1)
  318. {textattr(03);
  319. gotoxy(i,2*j);
  320. printf("y键:模式2(穿墙)");
  321. }
  322. if(i==22&&j==width+2)
  323. {textattr(07);
  324. gotoxy(i,2*j);
  325. printf("当前模式:%d",Mode);}
  326. if(i==24&&j==width+2)
  327. {textattr(03);
  328. gotoxy(i,2*j);
  329. printf("当前分数:");
  330. textattr(06);
  331. gotoxy(i,2*j+9);
  332. printf("%d",score);
  333. }
  334. }
  335. }
  336. void move()
  337. {
  338. FILE *fp; //文件指针,用于读取最高分和保存最高分
  339. int max=0;
  340. int oldTail_i,oldTail_j;//旧尾巴的位置
  341. int oldHead_i,oldHead_j;//旧蛇头的位置
  342. int newHead_i,newHead_j;//新蛇头的位置
  343. char input;
  344. for(i=1;i<high-1;i++) //让蛇的每一节数字加一
  345. for(j=1;j<width-1;j++)
  346. {
  347. if(snake[i][j]>0)
  348. {
  349. snake[i][j]++;
  350. if(max<snake[i][j])//让数字最大的一节变0
  351. {
  352. max=snake[i][j];
  353. //snake[i][j]=0;/
  354. oldTail_i=i;
  355. oldTail_j=j;
  356. }
  357. if(snake[i][j]==2)
  358. {
  359. oldHead_i=i;
  360. oldHead_j=j;
  361. }
  362. }
  363. }
  364. if(kbhit())//当按键时执行
  365. {
  366. input=getch();
  367. if((input=='w'||input==72)&&n!=2) //正在向上走,就不能执行向下
  368. {n=1;}
  369. if((input=='s'||input==80)&&n!=1)
  370. {n=2;}
  371. if((input=='a'||input==75)&&n!=4)
  372. {n=3;}
  373. if((input=='d'||input==77)&&n!=3)
  374. {n=4;}
  375. if(input=='p')
  376. {speed=200;}
  377. if(input=='l')
  378. {speed=100;}
  379. if(input=='m')
  380. {speed=0;}
  381. if(input=='t')
  382. {Mode=1;}
  383. if(input=='y')
  384. {Mode=2;}
  385. if(input==' ')
  386. {while(1)
  387. {
  388. if(kbhit()!=0)
  389. break;
  390. }
  391. }
  392. if(input==27)//27为Esc键的ASCII码
  393. {textattr(00);
  394. system("pause");
  395. }
  396. }
  397. if(n==1)
  398. {
  399. newHead_i=oldHead_i-1;newHead_j=oldHead_j;
  400. }
  401. if(n==2)
  402. {
  403. newHead_i=oldHead_i+1;newHead_j=oldHead_j;
  404. }
  405. if(n==3)
  406. {
  407. newHead_i=oldHead_i;newHead_j=oldHead_j-1;
  408. }
  409. if(n==4)
  410. {
  411. newHead_i=oldHead_i;newHead_j=oldHead_j+1;
  412. }
  413. if(snake[newHead_i][newHead_j]==-2) //如果没有吃到食物,蛇的最后一节变为0,否则不变(即蛇的长度+1)
  414. {
  415. food=0;
  416. food_sum++;
  417. score++;
  418. }
  419. else switch(Mode)
  420. {
  421. case 1:if(snake[newHead_i][newHead_j]>1||snake[newHead_i][newHead_j]==-1) //模式1,不能穿墙
  422. {
  423. fp=fopen("top_score.dat","wb+");
  424. fseek(fp,4*(mode-1),1);
  425. fread(&top_score[mode-1],sizeof(int),1,fp);
  426. if(score>top_score[mode-1])
  427. top_score[mode-1]=score;
  428. fwrite(&top_score[mode-1],sizeof(int),1,fp);
  429. while(1)
  430. {
  431. textattr(03);
  432. gotoxy(high/2,width-7);
  433. printf("GAME OVER!");
  434. gotoxy(high/2+1,width-8);
  435. printf("按r键重新开始");
  436. gotoxy(high/2+2,width-8);
  437. printf("按b键退出游戏");
  438. textattr(06);
  439. gotoxy(high/2+4,width-10);
  440. printf("历史最高分:%d 你的分数:%d",top_score[mode-1],score);
  441. if(kbhit())//当按键时执行
  442. {
  443. input=getch();
  444. if(input=='r')
  445. main();
  446. if(input=='b')
  447. {
  448. gotoxy(high/2+4,width-8);
  449. exit(0);
  450. }
  451. }
  452. }
  453. }
  454. else snake[oldTail_i][oldTail_j]=0;/如果没有吃到食物,蛇的最后一节变为0,否则不变(即蛇的长度+1
  455. break;
  456. case 2:if(snake[newHead_i][newHead_j]==-1&&n==1) //模式2,可以穿墙
  457. {newHead_i=high-2;}
  458. else if(snake[newHead_i][newHead_j]==-1&&n==2)
  459. {newHead_i=1;}
  460. else if(snake[newHead_i][newHead_j]==-1&&n==3)
  461. {newHead_j=width-2;}
  462. else if(snake[newHead_i][newHead_j]==-1&&n==4)
  463. {newHead_j=1;}
  464. else if(snake[newHead_i][newHead_j]>1)
  465. {
  466. fp=fopen("top_score.dat","wb+");
  467. fseek(fp,4*(mode-1),1);
  468. fread(&top_score[mode-1],sizeof(int),1,fp);
  469. if(score>top_score[mode-1])
  470. top_score[mode-1]=score;
  471. fwrite(&top_score[mode-1],sizeof(int),1,fp);
  472. while(1)
  473. {
  474. textattr(03);
  475. gotoxy(high/2,width-7);
  476. printf("GAME OVER!");
  477. gotoxy(high/2+1,width-8);
  478. printf("按r键重新开始");
  479. gotoxy(high/2+2,width-8);
  480. printf("按b键退出游戏");
  481. textattr(06);
  482. gotoxy(high/2+4,width-10);
  483. printf("最高分:%d 你的分数:%d",top_score[mode-1],score);
  484. if(kbhit())//当按键时执行
  485. {
  486. input=getch();
  487. if(input=='r')
  488. main();
  489. if(input=='b')
  490. {
  491. gotoxy(high/2+4,width-8);
  492. exit(0);
  493. }
  494. }
  495. }
  496. }
  497. else snake[oldTail_i][oldTail_j]=0;/如果没有吃到食物,蛇的最后一节变为0,否则不变(即蛇的长度+1
  498. break;
  499. }
  500. snake[newHead_i][newHead_j]=1;
  501. }
  502. int main()
  503. {
  504. system("cls");
  505. HideCursor();
  506. srand((unsigned int)time(0));
  507. system("title 贪吃蛇");
  508. system("mode con cols=110 lines=28");//设定窗口大小
  509. SetWindowLong(GetConsoleWindow(),GWL_STYLE,GetWindowLong(GetConsoleWindow(),GWL_STYLE) & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX);
  510. page_1(); //将page_1函数放在chu_shi_hua()函数前,待用户选择游戏模式再对数组进行初始化
  511. chu_shi_hua(); //数据初始化
  512. while(1)///游戏循环
  513. {
  514. Sleep(speed);
  515. draw();
  516. move();
  517. textattr(03);
  518. }
  519. return 0;
  520. }

consfun.c

  1. /* WINDOWS命令窗口编程常用功能
  2. 程序设计:李乾宝
  3. 修改时间:2010年12月--2017年1月
  4. */
  5. #include <windows.h>
  6. #include <wincon.h>
  7. /* 设置光标位置:使后续的输出从屏幕的x行y列输出
  8. 参数:x-行(从0开始)
  9. y-列(从0开始)
  10. */
  11. void gotoxy(int x, int y)
  12. {
  13. COORD Position;
  14. Position.X=y; Position.Y=x;
  15. SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),Position);
  16. }
  17. /* 功能:初始化命令窗口,设置窗口的行列数
  18. 参数:y-行数,x-列数
  19. */
  20. void consinit(short x, short y)
  21. {
  22. COORD scr={x,y};
  23. CONSOLE_SCREEN_BUFFER_INFO info;
  24. SMALL_RECT rect={0,0,x-1,y-1};
  25. HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  26. GetConsoleScreenBufferInfo(stdOut,&info); //获取命令窗口信息
  27. //如果原屏缓冲区小必须先设置新的缓冲区大小,再调整窗口大小
  28. if(info.dwSize.X*info.dwSize.Y<x*y)
  29. { SetConsoleScreenBufferSize(stdOut,scr);
  30. SetConsoleWindowInfo(stdOut,TRUE,&rect);//缓冲区比需要的小时会出错
  31. }
  32. else
  33. { SetConsoleWindowInfo(stdOut,TRUE,&rect);
  34. SetConsoleScreenBufferSize(stdOut,scr); //设置值比窗口区域需要的小时会出错
  35. }
  36. gotoxy(0,0);
  37. }
  38. /* 清屏:用当前的背景颜色清除屏幕,并将光标定位在左上角(0,0)
  39. 参数:无
  40. */
  41. void clrscr(void)
  42. {
  43. COORD scr={0,0};
  44. DWORD num;
  45. HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  46. CONSOLE_SCREEN_BUFFER_INFO info;
  47. GetConsoleScreenBufferInfo(stdOut,&info);
  48. num=info.dwMaximumWindowSize.X*info.dwMaximumWindowSize.Y;
  49. FillConsoleOutputAttribute(stdOut,(WORD)info.wAttributes,num,scr,&num);
  50. FillConsoleOutputCharacter(stdOut,' ',num,scr,&num);
  51. gotoxy(0,0);
  52. }
  53. /* 设置字体颜色:使以后的输出字体前景颜色改为给定值
  54. 参数:newcolor-新的颜色值
  55. 颜色取值范围为:0x00 ~ 0x0f
  56. */
  57. void textcolor(short newcolor)
  58. {
  59. HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  60. CONSOLE_SCREEN_BUFFER_INFO info;
  61. GetConsoleScreenBufferInfo(stdOut,&info);
  62. SetConsoleTextAttribute(stdOut, (WORD)(newcolor|info.wAttributes & 0xF0));
  63. }
  64. /* 设置背景颜色:使以后的输出的背景颜色改为给定值
  65. 参数:newcolor-新的颜色值
  66. 颜色取值范围为:0x00 ~ 0x0f
  67. */
  68. void textbackground( short newcolor)
  69. {
  70. HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  71. CONSOLE_SCREEN_BUFFER_INFO info;
  72. GetConsoleScreenBufferInfo(stdOut,&info);
  73. SetConsoleTextAttribute(stdOut,(WORD)((newcolor<<4)|(info.wAttributes&0x0F)));
  74. }
  75. /* 设置文本属性:同时设定前景和背景颜色
  76. 参数:newattr-新的属性值
  77. 颜色取值范围为:0x00 ~ 0xff,低4位为前景颜色,高4位为背景颜色
  78. */
  79. void textattr(short newattr)
  80. {
  81. HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  82. SetConsoleTextAttribute(stdOut,newattr);
  83. }
  84. void HideCursor() //隐藏光标的函数,网上搜的,需加头文件<windows.h>
  85. {CONSOLE_CURSOR_INFO cursor_info={1,0};
  86. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
  87. }

        上面的头函数和窗口编程代码系汕大李乾宝老师所编写,我写的是snake.c 。snake.c 是大一期末熬一个通宵码的代码,比较冗长,不过勉强可以玩一下,我懒得改啦~,哈哈哈感兴趣的小伙伴可以对代码进行模块化以及相应的删改优化。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/372575
推荐阅读
相关标签
  

闽ICP备14008679号