久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7563|回復: 5
打印 上一主題 下一主題
收起左側

基于STM32的貪吃蛇游戲設計(程序+硬件PCB文件+視頻)

  [復制鏈接]
跳轉到指定樓層
樓主
      學習嵌入式已經有兩年多了,現在準備工作了,也已經從51單片機過度到ARM的STM32單片機,就想結合自己所學的東西做一個東西出來,于是就做了這個貪吃蛇游戲。
       本貪吃蛇游戲是的硬件CPU是STM32F103C8T6、顯示液晶用的是諾基亞Nokia5510的屏幕、按鍵、電源穩壓模塊。
       為什么選擇STM32,因為STM32的主頻時鐘高達72M,說白了就是速度快,內部資源豐富和大容量的flash和動態內存。液晶不選用LCD12864,本人自己認為那個藍光屏幕看久了會眼花而且還有點笨重(純屬個人意見)。
       怎么在程序上實現貪吃蛇游戲設計呢,在這里感謝網上的個位大佬,核心程序基本上是借鑒的過來了。核心程序解決了,怎么顯示在液晶上了,第一首先寫一個畫點函數,就是輸入坐標就可以在對應的坐標點亮。nokia5510是84*48的像素點屏幕。其他的按鍵驅動函數就不在描述了。主要是本作者的表達能力不是很好,不在啰嗦了,直接上程序吧!

制作出來的貪吃蛇實物圖如下:


下面鏈接是演示視頻:
https://v.youku.com/v_show/id_XNDEzNTI4ODk0NA==.html

Altium Designer畫的PCB圖如下:(51hei附件中可下載工程文件)


STM32單片機源程序如下:
  1. #include "lcd_5510.h"
  2. #include "Snake_Game.h"

  3. #define ElemType int
  4.         
  5. typedef struct node
  6. {
  7.     ElemType x,y;
  8.     struct node *prior;
  9.     struct node *next;
  10. } Node;

  11. Food food;                                        //全局變量//
  12. int add=10;                                        //總得分與每次吃食物得分//蛇長度計數;。

  13. u8 sleeptime=200;                //每次運行的時間間隔
  14. Snake snake;
  15. Node *Head;                                        //Node*food;//蛇頭指針,食物指針
  16. u8 endgamestatus=0; //游戲結束的情況,1:撞到墻;2:咬到自己;3:主動退出游戲。

  17. //按鍵判斷
  18. Fuct KEY_Test(void)
  19. {
  20.     Fuct sta=Null;
  21.     if(UP_ON)    sta = Up;
  22.     if(Down_ON)  sta =  Down;
  23.     if(Left_ON)  sta =  Left;
  24.     if(Right_ON) sta =  Right;
  25.     if(MODE_ON)         sta =  Puase;
  26.     if(RTN_ON)         sta =  Rtn;
  27.     return sta;
  28. }



  29. // 新建節點。成功,返回節點指針;否則,返回NULL。
  30. static Node* CreateNode()
  31. {
  32.     Node *newNode = NULL;
  33.     newNode = (Node*)malloc(sizeof(Node));
  34.     if (newNode == NULL)
  35.         return NULL;
  36.     // 初始化新建節點前置節點和后置節點都是自己
  37.     newNode->prior = newNode->next = newNode;
  38.     return newNode;
  39. }

  40. // 創建表頭  成功,返回0;否則,返回-1。
  41. int Link_Create()
  42. {
  43.     Head = CreateNode();
  44.     if (Head == NULL)
  45.         return -1;
  46.     return 0;
  47. }

  48. // 表頭插入數據
  49. Node * Link_InsertFirst(Node*head)
  50. {
  51.     Node *newNode = CreateNode();
  52.     if (newNode == NULL)
  53.         return NULL;
  54.     newNode->next = head->next;
  55.     newNode->prior = head;
  56.     head->next->prior = newNode;
  57.     head->next = newNode;
  58.     return newNode;
  59. }

  60. //刪除表尾數據
  61. Node* Link_DeleteLast(Node*head)
  62. {
  63.     Node *current = head->prior;
  64.     current->next->prior = current->prior;
  65.     current->prior->next = current->next;
  66.     return current;
  67. }



  68. //銷毀雙向循環鏈表L:
  69. void DestroyList(Node* head)
  70. {
  71.         Node* q,*p=head->next; /* p指向第一個結點 */
  72.         while(p!=head) /* p沒到表頭 */
  73.         {
  74.                 q=p->next;
  75.                 free(p);
  76.                 p=q;
  77.         }
  78.         free(head);
  79.      head=NULL;
  80. }
  81. /*=========顯示蛇身===========*/
  82. void LCD_DrawPoint_Snake(Node *head)
  83. {
  84.     Node *current=head->next;
  85.     while(current!=head)//從頭到為,輸出蛇身
  86.     {
  87.         LCD_DrawPoint(current->x,current->y,ON);
  88.         current=current->next;
  89.     }
  90. }

  91. /*=========判斷是否撞墻=============*/
  92. void cantcrosswall(Node*head)//不能穿墻
  93. {
  94.     Node *current = head->next;
  95.     if(current->x<=min_width ||current->x>=frame_width-1 ||current->y>=frame_height-1 || current->y<=min_height)
  96.     {
  97.         endgamestatus=1;//游戲結束的情況。3種情況
  98.     }
  99. }
  100. /*=========判斷是否咬到了自己=============*/

  101. void biteself(Node*head)//
  102. {
  103.     Node *current=head->next;
  104.     Node *self=current->next;
  105.     while(self!=head)
  106.     {
  107.         if(self->x==current->x && self->y==current->y)
  108.         {
  109.                                           endgamestatus=2;
  110.         }
  111.         self=self->next;
  112.     }
  113. }

  114. u8 is_alive(Node*head)//判斷是否存活
  115. {
  116.   biteself(head);//判斷是否咬到自己
  117.         cantcrosswall(head);//判斷是否到邊界
  118.         return endgamestatus;
  119. }
  120. /*=========判斷是否吃到食物=============*/
  121. FlagStatus  judgeCoordInFoods(Food *foods, Node *spot)
  122. {
  123.    Node * nextHead=spot->next;
  124.          if(nextHead->x>=foods->X[0])//如果蛇頭在食物坐標范圍內
  125.         if(nextHead->x<=foods->X[3])
  126.             if(nextHead->y>=foods->Y[0])
  127.                 if(nextHead->y<=foods->Y[3])
  128.                     return SET;//返回吃的食物
  129.     return RESET;//沒吃的到
  130. }



  131. void DrawFood(Food *foods,u8 state)//畫出食物
  132. {
  133.     for(int i=0; i<Food_Size; i++)
  134.     {
  135.         LCD_DrawPoint(foods->X[i], foods->Y[i],state);//顯示食物
  136.     }
  137. }



  138. /*========產生隨機食物=====*/
  139. void Gave_Food(Food *foods)
  140. {
  141.     do
  142.     {
  143.         foods->X[0]=(rand() % (77))+ 5;                //產生食物的范圍
  144.         foods->Y[0]=(rand() % (41))+ 5;//(x-y)Y最大值  +z 最小值  
  145.     }
  146.     while(!((foods->X[0]>5)&&(foods->X[0]<80)&&(foods->Y[0]<40)&&(foods->Y[0]>9)));                        //判斷是否在范圍內
  147.     foods->X[1] = foods->X[0] + 1;
  148.     foods->X[2] = foods->X[0];
  149.     foods->X[3] = foods->X[0] + 1;
  150.     foods->Y[1] = foods->Y[0] ;
  151.     foods->Y[2] = foods->Y[0] + 1;
  152.     foods->Y[3] = foods->Y[0] + 1;
  153.     DrawFood(foods,ON);
  154. }

  155. /*=======吃到食物處理=======*/
  156. void update_food()  //吃到食物處理
  157. {
  158.     static        u16 time=0;
  159.           Node * nextHead=Head->next;
  160.     time++;
  161.     if(judgeCoordInFoods(&food,Head))//吃到食物
  162.     {
  163.         time=0;//食物更新時間清0
  164.         snake.len++;//蛇身長度+1
  165.         DrawFood(&food,OFF);//清除當前食物
  166.         Gave_Food(&food);//獲取新食物
  167.         snake.scroe+=((snake.len+10)/10);//分數
  168.                         
  169.                                 LCD_ShowNum(10,0,snake.len,3);                                                                                        //顯示長度
  170.                                 LCD_ShowNum(3,0,snake.scroe/100,3);                                                                        //顯示
  171.                                 LCD_ShowNum(3,0,snake.scroe%100,3);                                                                        //顯示
  172.         LCD_DrawPoint(nextHead->x,nextHead->y,ON);                //顯示蛇頭
  173.     }
  174.                 else
  175.                 {
  176.         nextHead=Link_DeleteLast(Head); //刪除蛇最后一個元素
  177.                                 LCD_DrawPoint(nextHead->x,nextHead->y,OFF);//關掉蛇尾最后一個像素點
  178.         free(nextHead);//釋放最后一個鏈表
  179.     }
  180.     if(time>100)//如果跟新時間到達之前沒有吃到食物
  181.     {
  182.         time=0;//更新食物
  183.         DrawFood(&food,OFF);//關掉食物
  184.         Gave_Food(&food);//獲取新食物
  185.     }
  186. }


  187. /*=========游戲暫停==========*/
  188. void pause()
  189. {
  190.   //  Disp_CZhuitu(6,8,2,10,Pause_char);
  191.     while(1)
  192.     {
  193.     //    delay_ms(300);
  194.         if(MODE_ON)
  195.             break;
  196.     }
  197. //    Disp_CZhuitu(6,8,2,10,jie_char);
  198. }


  199. /*=========控制游戲==========*/
  200. void gamecircle()//控制游戲
  201. {
  202.     Fuct Sta=KEY_Test();

  203.     if(Sta==Up&& snake.dir!=Down)//如果上按鍵按下 且蛇運動方向不為下
  204.     {
  205.         snake.dir=Up;//蛇方向為上
  206.     }
  207.     else if(Sta==Down&& snake.dir!=Up)
  208.     {
  209.         snake.dir=Down;
  210.     }
  211.     else if(Sta==Left&& snake.dir!=Right)
  212.     {
  213.         snake.dir=Left;
  214.     }
  215.     else if( Sta==Right&& snake.dir!=Left)
  216.     {
  217.         snake.dir=Right;
  218.     }
  219.     else if(Sta==Puase)//如果暫停鍵按下
  220.     {
  221.         pause();
  222.     }
  223.     else if(Sta==Rtn)
  224.     {
  225.        endgamestatus=3;
  226.     }
  227. }



  228. /*=========蛇移動==========*/
  229. void move_snake()//蛇前進,上U,下D,左L,右R
  230. {   
  231.           Node*nextHead;
  232.     Node * currot=Head->next;
  233.     nextHead=Link_InsertFirst(Head);//在蛇頭添加一個元素
  234.     switch(snake.dir)
  235.     {
  236.         case Up:
  237.             nextHead->x=currot->x;
  238.             nextHead->y=currot->y-1;
  239.             break;
  240.         case Down:
  241.             nextHead->x=currot->x;
  242.             nextHead->y=currot->y+1;
  243.             break;
  244.         case Left:
  245.             nextHead->x=currot->x-1;
  246.             nextHead->y=currot->y;
  247.             break;
  248.         case Right:
  249.             nextHead->x=currot->x+1;
  250.             nextHead->y=currot->y;
  251.             break;
  252.     }
  253.                 LCD_DrawPoint(nextHead->x,nextHead->y,ON);//顯示添加的元素
  254. }


  255. //顯示游戲界面
  256. void game_ucos()
  257. {
  258.         LCD_prints_68(0, 0, "SC:");
  259.         LCD_prints_68(7, 0,"Ln:");
  260.         LCD_DrawLine(0,8,83,8);
  261.         LCD_DrawLine(0,8,0,47);
  262.         LCD_DrawLine(0,47,83,47);
  263.         LCD_DrawLine(83,47,83,8);
  264. }



  265. /*=========初始化游戲===========*/
  266. void init_snake(u8 grade)
  267. {
  268.     int i;
  269.           Node *list=NULL;
  270.             if(grade==2)
  271.         snake.speed=120;
  272.     else if(grade==3)
  273.         snake.speed=70;
  274.                  else if(grade==4)
  275.         snake.speed=40;

  276. //=============蛇初始化==============//               
  277.                 snake.dir=Right;
  278.                 endgamestatus=0;
  279.                 snake.len=10;
  280.     Link_Create();
  281.     for(i=0; i<snake.len; i++)
  282.     {
  283.         list=Link_InsertFirst(Head);
  284.         list->x=frame_width/2+i;
  285.         list->y=frame_height/2;
  286.     }
  287.     LCD_DrawPoint_Snake(Head);
  288. //=============界面初始化==============//
  289.                 snake.scroe=0;
  290.                
  291.                 LCD_ShowNum(10,0,snake.len,3);                                //顯示長度
  292.                 LCD_ShowNum(3,0,snake.scroe%1000,3);                                        //顯示分數
  293.                 LCD_ShowNum(3,0,snake.scroe/100,3);                                        //顯示分數
  294.                 LCD_ShowNum(3,0,snake.scroe%100,3);                                        //顯示分數
  295.                 Gave_Food(&food);
  296. }

  297. void remove_snake(Node *head)
  298. {
  299.     Node *current=head->next;
  300.     while(current!=head)//從頭到為,輸出蛇身
  301.     {
  302.         LCD_DrawPoint(current->x,current->y,OFF);
  303.         current=current->next;
  304.     }
  305. }


  306. int Play(u8 grade)
  307. {
  308.    init_snake(grade);
  309.                 game_ucos();
  310.         while(1)
  311.     {
  312.         gamecircle();        //游戲控制
  313.         move_snake(); //移動蛇身
  314.                           update_food(); //是否產生食物
  315.         delay_ms(snake.speed); //移動速度snake.speed
  316.         if(is_alive(Head)) //蛇的死活(撞墻或自食)
  317.         {  
  318.                                           DestroyList(Head);
  319.                                                 DrawFood(&food,OFF);//清除當前食物
  320.                                                 LCD_Clear_Cache();
  321.                                         while(KEY_Test()==0);
  322.                                         RLCD_vertical_vrintch(game_icon);
  323.                                         LCD_clr_scr();
  324.                                         interface();
  325.                                         return 0;
  326.         }
  327.     }
  328. }


  329. //進入難度選擇
  330. void Start_game()
  331. {
  332.         int key,num=2;
  333.         interface();
  334.         while(1)
  335.         {
  336.                 LCD_prints_68(3, 0,"Difficult");
  337.                 LCD_ShowNum(5,2,1,1);                                        //顯示分數
  338.                 LCD_ShowNum(5,3,2,1);                                        //顯示分數
  339.                 LCD_ShowNum(5,4,3,1);                                        //顯示分數
  340.                 LCD_printc_68(3, num, '>');
  341.                
  342.                 key=KEY_Test();

  343.                 switch (key)
  344.                 {
  345.                         case Up:
  346.                                                         LCD_printc_68(3, num, ' ');
  347.                                                         num ++;
  348.                                                         if(num >=5) num =2;
  349.                                                         LCD_printc_68(3, num, '>');
  350.                                                         delay_ms(100) ;break ;
  351.                         case Down:         
  352.                                                                 LCD_printc_68(3, num, ' ');
  353.                                                                 num --;
  354.                                                                 if(num <=1) num =4;
  355.                                                                 LCD_printc_68(3, num, '>');
  356.                                                                 delay_ms(100);break ;
  357.                         case Puase:
  358.                                                                         LCD_clr_scr();
  359.                                                                         Play(num);break ;
  360.                         
  361.                         default : break;
  362.                 }
  363.         }
  364. }

復制代碼



附件有源程序和PCB文件
全部資料51hei下載地址:
nokia5510.zip (1.5 MB, 下載次數: 73)
基于nolkia5510的貪吃蛇游戲設計.7z (198.81 KB, 下載次數: 65)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:336842 發表于 2019-4-13 20:23 | 只看該作者
您好,請問能上傳仿真圖嗎
回復

使用道具 舉報

板凳
ID:197252 發表于 2019-4-14 16:46 | 只看該作者
一只貓的過客 發表于 2019-4-13 20:23
您好,請問能上傳仿真圖嗎

沒有仿真的文件,直接做出硬件在線調試的。
回復

使用道具 舉報

地板
ID:446097 發表于 2019-6-10 21:49 | 只看該作者
13321764316 發表于 2019-4-14 16:46
沒有仿真的文件,直接做出硬件在線調試的。

樓主有硬件清單嗎?
回復

使用道具 舉報

5#
ID:785431 發表于 2020-6-21 14:37 | 只看該作者
矩陣是什么?

回復

使用道具 舉報

6#
ID:691090 發表于 2020-7-15 16:06 | 只看該作者
請問LCD1602顯示屏可以做不?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久精品二区 | 理伦毛片| 国产日韩一区二区三区 | 一区在线观看 | 国产精品久久久99 | 久久久精 | 中文字幕精品一区二区三区在线 | 中文字幕亚洲一区二区va在线 | 精品久久九| 国产精品视频一区二区三区 | 97中文视频| 欧美黑人激情 | 国产一区二区影院 | 亚洲视频区 | 成人av资源在线 | 日韩精品久久一区二区三区 | 日韩精品一区二区三区在线播放 | 亚洲福利一区 | 久久国产精品久久久久 | 国产一区二区三区四区在线观看 | 国产精品一区二区免费 | 蜜桃免费一区二区三区 | 亚洲婷婷六月天 | 四虎影视免费观看 | 日本一区二区三区四区 | 色天堂影院 | 欧美99久久精品乱码影视 | 四虎永久在线精品免费一区二 | 精品久久中文字幕 | jav成人av免费播放 | 久久成人一区二区三区 | 在线观看中文字幕一区二区 | 一级a爱片久久毛片 | 国产精品日韩欧美一区二区三区 | 亚洲精品免费在线观看 | av在线免费网 | 日韩天堂av| 欧美国产一区二区 | 中文字幕在线观看av | 夜夜操操操 | 亚洲一级av毛片 |