鸿蒙基于WiFi IoT套件开发的猜数字小游戏代码分享

系统
猜数字是一个很经典的小游戏,也是编程开发入门的典型,以下为基于WiFi IoT套件开发的猜数字小游戏的具体开发过程和效果。

猜数字是一个很经典的小游戏,也是编程开发入门的典型,以下为基于WiFi IoT套件开发的猜数字小游戏的具体开发过程和效果。

基本规则:

由甲方(玩家)默想一个1-99(包含)内的任意数字(整数),然后由乙方进行猜测,并询问甲方猜测的数字是大了还是小了,甲方根据实际情况进行回复,则乙方最多问6个问题,就一定能够猜中甲方默想的数字。

基本原理:

乙方问最多6次,包括最后一次说出猜中的数字,实际上乙方最多有7次猜测的机会。

而使用二分进行查找,2^7=128,则99以内的数字,完全可以覆盖,因此乙方绝对可以猜中。

实现概述:

以上的基本规则和基本原理明确了,我们要在WiFi IoT套件上实现,并且甲方需要参与,需要处理以下三个部分:

  1. 猜数字的主逻辑
  2. 使用OLED屏幕显示提示信息,让玩家进行互动操作:我们需要在屏幕上显示汉字,进行玩家当前猜测的数字,以及玩家按键后告知玩家结果
  3. 使用按键接收玩家操作(大了或者小了等):在这个实例中,我们使用了ADC方式来读取按键信息,从而获得玩家具体操作。所使用的按键为核心板上的USR按键,和OLED板上的S1,S2按键。使用ADC方式读取的时候,他们所使用的输入端口为GPIO5/ADC2,具体的按键作用如下:
  • USR:开始游戏,或者确认
  • S1:如果猜小了,则玩家按S1告知
  • S2:如果猜大了,则玩家按S2告知

原始代码修改处理:【代码基础为code-1.0.tar.gz】

  • 开启I2C:vendor/hisi/hi3861/hi3861/build/config/usr_config.mk
  1. ## BSP Settings 
  2. # CONFIG_I2C_SUPPORT is not set 
  3. CONFIG_I2C_SUPPORT=y 
  4. # CONFIG_I2S_SUPPORT is not set​ 
  •  I2C复用端口设置:vendor/hisi/hi3861/hi3861/app/wifiiot_app/init/app_io_init.c
  1. #ifdef CONFIG_I2C_SUPPORT 
  2.     /* I2C IO复用也可以选择3/4; 9/10,根据产品设计选择 */ 
  3.     // hi_io_set_func(HI_IO_NAME_GPIO_0, HI_IO_FUNC_GPIO_0_I2C1_SDA); 
  4.     // hi_io_set_func(HI_IO_NAME_GPIO_1, HI_IO_FUNC_GPIO_1_I2C1_SCL); 
  5.     hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA); 
  6.     hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL); 
  7. #endif​ 

 主逻辑代码:guess.c

  1. #include <stdio.h> 
  2. #include <unistd.h> 
  3.  
  4. #include <ohos_init.h> 
  5. #include <cmsis_os2.h> 
  6. #include <hiview_config.h> 
  7. #include <hiview_log.h> 
  8. #include <wifiiot_watchdog.h> 
  9. #include <hi_task.h> 
  10.  
  11. #include "button/button.h" 
  12. #include "oled/oled.h" 
  13.  
  14. /* 
  15. 0123456789 
  16. 请在心中默想一个1~99的整数,我能在6个问题之内猜出这个数 
  17. 想好了就按【USER】开始游戏吧,【RST】重启 
  18. 小了按【S1】,大了按【S2】,正确按【USER】 
  19. 第?个问题,是这个数吗:?? 
  20. 大了啊!那我再猜小一点 
  21. 小了啊!那我再猜大一点 
  22. 哈哈,我猜到了吧! 
  23. 按【USER】再玩一次(请先默想一个1~99的整数) 
  24. 你默想的数一定是?? 
  25.  
  26. //  开始:0,长度10 
  27. //  开始:10,长度30 
  28. //  开始:40,长度24 
  29. //  开始:64,长度25 
  30. //  开始:89,长度14 
  31. //  开始:103,长度11 
  32. //  开始:114,长度11 
  33. //  开始:125,长度9 
  34. //  开始:134,长度26 
  35. //  开始:160,长度10 
  36. */ 
  37. char *str[] = { 
  38.     "0123456789"
  39.     "请在心中默想一个1~99的整数,我能在6个问题之内猜出这个数"
  40.     "想好了就按【USER】开始游戏吧,【RST】重启"
  41.     "小了按【S1】,大了按【S2】,正确按【USER】"
  42.     "第?个问题,是这个数吗:??"
  43.     "大了啊!那我再猜小一点"
  44.     "小了啊!那我再猜大一点"
  45.     "哈哈,我猜到了吧!"
  46.     "按【USER】再玩一次(请先默想一个1~99的整数)"
  47.     "你默想的数一定是??" 
  48. }; 
  49.  
  50. int pos[][2] = { 
  51.     {0, 10}, 
  52.     {10, 30}, 
  53.     {40, 24}, 
  54.     {64, 25}, 
  55.     {89, 14}, 
  56.     {103, 11}, 
  57.     {114, 11}, 
  58.     {125, 9}, 
  59.     {134, 26}, 
  60.     {160, 10} 
  61. }; 
  62.  
  63. void display_string(int idx,int delay,int num1, int num2){ 
  64.     int start=0; 
  65.     int len=0; 
  66.  
  67.     start = pos[idx][0]; 
  68.     len = pos[idx][1]; 
  69.     if(idx==4 && num2==100) { 
  70.         len = len +1; 
  71.     } 
  72.     u8 no[len]; 
  73.     for(int i=0;i<len;i++){ 
  74.         no[i] = start+i; 
  75.     } 
  76.     // 4 "第?个问题,是这个数吗:??"
  77.     if(idx==4) { 
  78.         no[1] = num1; 
  79.         if(num2==100) { 
  80.             no[len-3] = 1; 
  81.             no[len-2] = 0; 
  82.             no[len-2] = 0; 
  83.         } else { 
  84.             no[len-2] = num2/10; 
  85.             no[len-1] = num2%10; 
  86.         } 
  87.     } 
  88.     OLED_Clear(); 
  89.     OLED_ShowChineseString(0,0,no,len,16);         
  90.     usleep(delay*1000*1000);     
  91.  
  92. // 主任务 
  93. static void *GuessTask(const char *arg){ 
  94.     (void)arg; 
  95.  
  96.     gpio_button_init(); 
  97.     oled_display_init(); 
  98.  
  99.     OLED_Clear(); 
  100.     printf("请在心中默想一个1~100的整数,我能在6个问题之内猜出这个数是什么:\n"); 
  101.     display_string(1,2,0,0); 
  102.     printf("想好了就按【USER】开始游戏吧,【RST】重启\n"); 
  103.     display_string(2,2,0,0); 
  104.     printf("小了按【S1】,大了按【S2】,正确按【USER】\n"); 
  105.     display_string(3,0,0,0); 
  106.  
  107.     key_event_t zf; //声明char类型来存放输入的字符 
  108.     char number; //电脑猜测的数字 
  109.  
  110.     while ((zf = gpio_button_get())!=KEY_EVENT_NONE) 
  111.     { 
  112.         // getchar();//忽略回车 
  113.         char min_shu = 1;   // 1是初始最小数。 
  114.         char max_shu = 100; // 100是初始最大数。 
  115.  
  116.         if (zf == KEY_EVENT_USER) 
  117.         { 
  118.             int jishu = 1; // 计数用的,6个问题以内嘛。 
  119.             while (1)   // 条件一直为真,死循环,能用break跳出循环,或用return跳出整个函数。 
  120.             { 
  121.                 number = (min_shu + max_shu) / 2; // 最小数和最大数的和除2 ,意思就是取它们的中间值。 
  122.                 printf("\n第%d个问题,是这个数吗:%d", jishu, number); 
  123.                 display_string(4,0,jishu, number); 
  124.                 zf = gpio_button_get(); 
  125.                 // getchar();//忽略回车 
  126.  
  127.                 if (zf == KEY_EVENT_S2) 
  128.                 { 
  129.                     printf("\n大了啊!那我再猜小一点\n"); 
  130.                     display_string(5,2,0,0); 
  131.                     max_shu = number - 1; //如果是大了,那最大值至少比目前的数小1。 
  132.                     jishu++;              //回答次数加1 ,如果你回答了电脑6次问题,电脑还没有猜对,那电脑就输了。 
  133.                 } 
  134.                 if (zf == KEY_EVENT_S1) 
  135.                 { 
  136.                     printf("\n小了啊!那我再猜大一点\n"); 
  137.                     display_string(6,2,0,0); 
  138.                     min_shu = number + 1; //如果是小了,那最小值至少比目前的数大1。 
  139.                     jishu++;              //同上面,计数加1 
  140.                 } 
  141.                 if (zf == KEY_EVENT_USER) 
  142.                 { 
  143.                     // printf("y\n"); 
  144.                     printf("\n哈哈,我猜到了吧!\n"); 
  145.                     display_string(7,2,0,0); 
  146.                     printf("按【USER】再玩一次(请在心中先默想一个1~100的整数),【RST】重启\n"); 
  147.                     display_string(8,0,0,0); 
  148.                     break; 
  149.                 } 
  150.                 if (jishu == 7) 
  151.                 { 
  152.                     printf("\n你默想的数一定是%d",(min_shu + max_shu) / 2); 
  153.                     display_string(9,2,0,0); 
  154.                     printf("\n按【USER】再玩一次(请在心中先默想一个1~100的整数),【RST】重启\n"); 
  155.                     display_string(8,0,0,0); 
  156.                     break; 
  157.                 } 
  158.             } 
  159.         } 
  160.         else { 
  161.             printf("\n按键无效,请重新选择(按【USER】开始,【RST】重启):"); 
  162.         } 
  163.     } 
  164.     return NULL
  165.  
  166. // 程序入口 
  167. static void GuessEntry(void) 
  168.     osThreadAttr_t attr; 
  169.     WatchDogDisable(); 
  170.     SetLogLevel(HILOG_LV_ERROR); 
  171.  
  172.     attr.name = "GuessTask"
  173.     attr.attr_bits = 0U; 
  174.     attr.cb_mem = NULL
  175.     attr.cb_size = 0U; 
  176.     attr.stack_mem = NULL
  177.     attr.stack_size = 1024; 
  178.     attr.priority = osPriorityNormal; 
  179.  
  180.     if (osThreadNew((osThreadFunc_t)GuessTask, NULL, &attr) == NULL) { 
  181.         printf("[GuessNum] Falied to create GuessTask!\n"); 
  182.     } 
  183.  
  184. SYS_RUN(GuessEntry); 

主逻辑代码说明:

因为在OLED上面显示字符(包括汉字),需要预先取得汉字的字模点阵数据;在这个实例中,会有不同的提示语出现,且未中文,为了方便处理,我将每句话的字模点阵数据单独取出,所以定义了str[],pos[][2],以及display_string(),用于显示对应的语句。其最终调用oled/oled.c中的OLED_ShowChineseString()来将汉字输出到OLED屏幕;特别的,语句4“第?个问题,是这个数吗:??”需要处理具体数字,所以进行了特殊的处理。

获取按键的部分,在button/button.c中的gpio_button_get(),代码随后展示,用于获取按键的状态

OLED部分代码:【以下为oled/oled.h,oled/oled.c和字模数据oled/oledfont.h请查看附件】

  1. #ifndef __OLED_H 
  2. #define __OLED_H 
  3.  
  4.  
  5. #define OLED_MODE 0 
  6. #define SIZE 8 
  7. #define XLevelL     0x00 
  8. #define XLevelH     0x10 
  9. #define Max_Column  128 
  10. #define Max_Row     64 
  11. #define Brightness  0xFF  
  12. #define X_WIDTH     128 
  13. #define Y_WIDTH     64       
  14.  
  15.  
  16. #define OLED_CMD  0 //写命令 
  17. #define OLED_DATA 1 //写数据 
  18.  
  19.  
  20. #define u8 unsigned char 
  21. #define u16 unsigned short 
  22. #define u32 unsigned int 
  23.  
  24. //OLED控制用函数 
  25. void delay_ms(unsigned int ms); 
  26. void OLED_ColorTurn(u8 i); 
  27. void OLED_DisplayTurn(u8 i); 
  28. void OLED_WR_Byte(u8 dat,u8 cmd); 
  29. void OLED_Set_Pos(u8 x, u8 y); 
  30. void OLED_Display_On(void); 
  31. void OLED_Display_Off(void); 
  32. void OLED_Clear(void); 
  33. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey); 
  34. u32 oled_pow(u8 m,u8 n); 
  35. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey); 
  36. void OLED_ShowString(u8 x,u8 y,char *chr,u8 sizey); 
  37. void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey); 
  38. void OLED_ShowChineseString(u8 x,u8 y,u8 no[],u8 length,u8 sizey); 
  39. void OLED_Direct_ShowString(u8 x,u8 y,char *chr,u8 sizey); 
  40. void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[]); 
  41. void OLED_Init(void); 
  42. void oled_display_init(void); 
  43. #endif 

 OLED汉字字模数据获取方式:

在OLED上面显示字符(包括汉字),本质上是描点,所以获取对应字符的点阵数据即可。

生成字模数据的工具为PCToLCD,设置为字符模式和C51格式;这个工具还可以用于取图片的点阵数据。

具体获取方式如下:

按键部分代码:【以下为button/button.h,button/button.c请查看附件】

  1. #ifndef __BUTTON_H 
  2. #define __BUTTON_H 
  3.  
  4. #include <hi_types_base.h> 
  5.  
  6. #define APP_DEMO_ADC 
  7. #define ADC_TEST_LENGTH 64 
  8. #define VLT_MIN 100 
  9. #define STATUS_LEN 4 
  10.  
  11. // 按键状态定义 
  12. typedef enum 
  13.     KEY_EVENT_NONE = 0, 
  14.     KEY_EVENT_S1, 
  15.     KEY_EVENT_S2, 
  16.     KEY_EVENT_USER 
  17. } key_event_t; 
  18.  
  19. //获取当前按键 
  20. key_event_t get_key_event(void); 
  21.  
  22. // ADC转换 
  23. hi_void convert_to_voltage(hi_u32 data_len); 
  24.  
  25. // ADC获取 
  26. void button_adc_test(void); 
  27.  
  28. // 设置 按键中断响应 
  29. void gpio_button_init(void); 
  30.  
  31. // 获取需要的按键状态 
  32. key_event_t gpio_button_get(void); 
  33.  
  34. #endif 

 按键部分代码说明:

当使用ADC方式来读取按键状态的时候,本质上,是读取了ADC输入端口的数据,这个数据进过一定的转换,能够化为对应的电压数据。而不同的按键按下后,ADC端口读取的电压是不同的,并且是在一定范围内波动的,对应按键的电压范围在上述vlt_val_scopes中进行了定义。我们获取到了对应的电压数据,然后与vlt_val_scopes每个范围数据进行对比,从而据此得到对应的按键信息。

实际结果演示:

视频地址: 链接: https://pan.baidu.com/s/1RtT8Wh3ZPbasJ-dK7x1QRg 提取码: vkyh

完整代码:

下载地址: https://pan.baidu.com/s/1RtT8Wh3ZPbasJ-dK7x1QRg 提取码: vkyh

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2020-11-10 12:08:25

开发框架

2012-01-10 12:48:52

Java

2015-09-29 09:38:50

Java程序猜大小

2020-11-12 09:44:43

鸿蒙

2020-11-13 11:53:52

4.WiFi IoT

2020-10-30 17:57:11

鸿蒙HiSpark

2019-09-23 09:11:02

Python文本编辑器操作系统

2023-01-03 15:16:27

2022-12-27 14:39:38

2023-08-07 15:18:29

游戏开发鸿蒙Arkts

2022-08-04 13:55:08

拼数字小游戏鸿蒙

2023-02-23 14:30:27

游戏Tcl

2023-02-13 08:26:28

猜数字Basic

2012-09-11 09:19:35

JavaScriptJSjQ

2020-12-21 09:57:52

OLED温湿度计hi3861

2022-07-29 14:47:34

数独Sudoku鸿蒙

2021-10-04 18:49:46

Fortran 77语言猜数字

2021-01-12 06:42:50

Lua脚本语言编程语言

2018-01-22 20:35:27

微信小游戏开发

2021-10-22 19:41:01

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号