【水模拟】#71 A. Bus Game

A. Bus Game
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

After Fox Ciel won an onsite round of a programming contest, she took a bus to return to her castle. The fee of the bus was 220 yen. She met Rabbit Hanako in the bus. They decided to play the following game because they got bored in the bus.

  • Initially, there is a pile that contains x 100-yen coins and y 10-yen coins.
  • They take turns alternatively. Ciel takes the first turn.
  • In each turn, they must take exactly 220 yen from the pile. In Ciel's turn, if there are multiple ways to take 220 yen, she will choose the way that contains the maximal number of 100-yen coins. In Hanako's turn, if there are multiple ways to take 220 yen, she will choose the way that contains the maximal number of 10-yen coins.
  • If Ciel or Hanako can't take exactly 220 yen from the pile, she loses.

Determine the winner of the game.

Input

The first line contains two integers x (0 ≤ x ≤ 106) and y (0 ≤ y ≤ 106), separated by a single space.

Output

If Ciel wins, print "Ciel". Otherwise, print "Hanako".

Sample test(s)
input
2 2
output
Ciel
input
3 22
output
Hanako
Note

In the first turn (Ciel's turn), she will choose 2 100-yen coins and 2 10-yen coins. In the second turn (Hanako's turn), she will choose 1 100-yen coin and 12 10-yen coins. In the third turn (Ciel's turn), she can't pay exactly 220 yen, so Ciel will lose.


原先看到这个题说谁赢谁输还以为是博弈……意思是有x枚100元硬币、y枚10元硬币,两个人轮流取钱每次取220元,Ciel(希尔)每次尽可能多的取100元硬币,Hanako(花子)则每次尽可能多的取10元硬币(意味不明……),然后问谁第一次没法取了另一个人就赢了。

那么我们就模拟他们取硬币的过程吧。

希尔(Ciel)的话,100元不小于2个的情况下就取2个加上2个10元的,不足2个就取光剩下的10元来凑

Hanako反之,同理。

自然,当总钱数不足220或者10元硬币不足2个的时候失败。

代码如下:

#include <cstdio>
#include <string>
#include <cstring> 
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
// http://codeforces.com/contest/79
// Bus Game
int main()
{
	int x,y,turn=1;	//1-Ciel 2-Hanako
	cin>>x>>y;
	while(turn)
	{
		if(y<2 || 100*x+10*y<220) break;
		if(turn==1)
		{
			if(x>=2)x-=2,y-=2;
			else if(x==1)x-=1,y-=12;
			else if(x==0)y-=22;
		}
		else if(turn==2)
		{
			if(y>=22)y-=22;
			else if(y>=12)y-=12,x-=1;
			else if(y>=2)y-=2,x-=2;
		}
		turn = 3-turn;
	}
	if(turn==1)printf("Hanako");
	else printf("Ciel");
	return 0;
} 





/* 深圳市普中科技有限公司(PRECHIN 普中) 技术支持:www.prechin.net * * 实验名称:DS18B20温度传感器实验 * * 接线说明:DS18B20温度传感器模块-->ESP32 IO (DS)-->(13) * * 实验现象:程序下载成功后,软件串口控制台间隔1S输出DS18B20温度传感器采集的温度 * * 注意事项:需要在软件中选择"项目"-->"加载库"-->"添加一个.ZIP库..."-->选择到本实验目录下的两个压缩文件包“OneWire-master.zip”和“Arduino-Temperature-Control-Library-master.zip”安装即可。 * 该库使用方法可参考:https://blog.csdn.net/Naisu_kun/article/details/88420357 */ #include "public.h" #include <DallasTemperature.h> #define ONE_WIRE_BUS 13 //1-wire数据总线连接 OneWire oneWire(ONE_WIRE_BUS); //声明 DallasTemperature sensors(&oneWire); //声明 void setup(){ Serial.begin(115200); sensors.begin(); Serial.print("Device count: "); Serial.println(sensors.getDeviceCount()); } void loop(){ Serial.println("发起温度转换"); sensors.requestTemperatures(); //向总线上所有设备发送温度转换请求,默认情况下该方法会阻塞 Serial.println("温度转换完成"); float tempC = sensors.getTempCByIndex(0); //获取索引号0的传感器摄氏温度数据 if (tempC != DEVICE_DISCONNECTED_C) //如果获取到的温度正常 { Serial.print("当前温度是: "); Serial.print(tempC); Serial.println(" ℃\n"); } delay(2000); } /* 深圳市普中科技有限公司(PRECHIN 普中) 技术支持:www.prechin.net * * 实验名称:舵机实验 * * 接线说明:SG90舵机模块-->ESP32 IO 橙色(信号线)-->(17) 红色(电源正)-->(5V) 褐色(电源负)-->(GND) * * 实验现象:程序下载成功后,SG90舵机循环以45°步进从0°旋转到180° * * 注意事项: */ #include "public.h" #include "pwm.h" //舵机控制引脚 #define servo_pin 17 //舵机控制 //degree:角度0-180 //返回值:输出对应角度PWM占空比 int servo_ctrl(u8 degree) { const float deadZone=6.4; //对应0.5ms(0.5/(20ms/256)) const float max=32; //对应2.5ms if(degree<0)degree=0; else if(degree>180)degree=180; return (int)(((max-deadZone)/180)*degree+deadZone); } void setup(){ Serial.begin(115200); pwm_init(servo_pin,8,50,8); pwm_set_duty(8,servo_ctrl(0)); } void loop(){ for(u8 i=0;i<=180;i+=45) { pwm_set_duty(8,servo_ctrl(i)); delay(1000); } } #include <U8g2lib.h> #include <Wire.h> U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 0, /* data=*/ 4); // 菜单项定义 const char *menuItems[] = {"Start Game", "Settings", "About", "Exit"}; int selectedItem = 0; const int totalItems = 4; // 按钮引脚定义(根据实际连接修改) #define BTN_UP 12 #define BTN_DOWN 14 #define BTN_SELECT 27 void setup() { pinMode(BTN_UP, INPUT_PULLUP); pinMode(BTN_DOWN, INPUT_PULLUP); pinMode(BTN_SELECT, INPUT_PULLUP); u8g2.begin(); u8g2.setFont(u8g2_font_6x10_tr); } void loop() { // 处理按钮输入 handleButtonInput(); // 绘制菜单 drawMenu(); } void handleButtonInput() { if (digitalRead(BTN_UP) == LOW) { selectedItem = (selectedItem - 1 + totalItems) % totalItems; delay(200); // 防抖 } if (digitalRead(BTN_DOWN) == LOW) { selectedItem = (selectedItem + 1) % totalItems; delay(200); } if (digitalRead(BTN_SELECT) == LOW) { executeMenuItem(selectedItem); delay(200); } } void drawMenu() { u8g2.firstPage(); do { // 标题 u8g2.setFont(u8g2_font_7x14B_tr); u8g2.drawStr(32, 12, "MAIN MENU"); // 菜单项 u8g2.setFont(u8g2_font_6x10_tr); for (int i = 0; i < totalItems; i++) { if (i == selectedItem) { u8g2.drawStr(10, 30 + i * 12, ">"); // 选中标记 } u8g2.drawStr(20, 30 + i * 12, menuItems[i]); } } while (u8g2.nextPage()); } void executeMenuItem(int item) { u8g2.firstPage(); do { u8g2.setFont(u8g2_font_7x14B_tr); switch (item) { case 0: // Start Game u8g2.drawStr(20, 30, "Game Started!"); break; case 1: // Settings u8g2.drawStr(20, 30, "Settings Menu"); break; case 2: // About u8g2.drawStr(20, 30, "U8g2 Demo v1.0"); break; case 3: // Exit u8g2.drawStr(20, 30, "Bye!"); break; } } while (u8g2.nextPage()); delay(1000); // 显示结果1秒 }练习1:智能温控风扇系统 组合模块:DS18B20(18) + 舵机(22) + OLED(23) 功能实现: 1.DS18B20实时监测环境温度 2.温度超过设定阈值时,风扇打开,0-100°转动(舵机转动角度模拟风扇转动幅度); 没有超过设定阈值时,关闭; 3.OLED显示实时温度、风扇状态(开关状态,PWM的大小值) 学习重点: 1.单总线协议驱动DS18B20 2.舵机PWM角度精准控制 OLED显示绘制(使用U8g2库)
06-11
/* test3_main.c - 修正版 修复内容: - TP->LED 映射按用户要求调整 - 修复 TP6 祝福播放阻塞/持续发声问题 - OLED 表情改为 (* ̄︶ ̄),音乐符号为 ♪ - 小游戏键映射调整为 TP3, TP1, TP15, TP14, TP12, TP9, TP11 - 清理未使用的数据,避免编译警告 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <stdbool.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include "driver/gpio.h" #include "driver/ledc.h" #include "driver/spi_master.h" #include "esp_log.h" #include "esp_system.h" #include "esp_random.h" #include "esp_rom_sys.h" #include "led_strip.h" #define TAG "TTP229_EXT_FIXED" /* ---------- Hardware pins (如需修改请在这里改) ---------- */ #define WS2812B_PIN 2 #define NUM_LEDS 12 #define TTP229_SCL 27 #define TTP229_SDO 26 #define BUZZER_PIN 25 /* OLED SPI pins - 请按你实际接线调整 */ #define OLED_SPI_HOST HSPI_HOST #define OLED_MOSI_PIN 17 #define OLED_SCLK_PIN 4 #define OLED_DC_PIN 18 #define OLED_CS_PIN 19 #define OLED_RST_PIN 5 #define OLED_WIDTH 128 #define OLED_HEIGHT 64 #define OLED_BUF_SIZE ((OLED_WIDTH * OLED_HEIGHT) / 8) #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /* ---------- 全局与声明 ---------- */ led_strip_handle_t led_strip; static uint8_t led_brightness[NUM_LEDS]; static uint8_t led_active[NUM_LEDS]; static SemaphoreHandle_t led_mutex = NULL; typedef enum { MODE_NORMAL=0, MODE_LED_KEY_INTERACT, MODE_LED_GRADIENT_CYCLE, MODE_BLESSING_PLAY, MODE_GAME } app_mode_t; static volatile app_mode_t g_mode = MODE_NORMAL; /* gradient */ static volatile bool gradient_run = false; static int gradient_pos = 0; /* blessing task control */ static TaskHandle_t blessing_task_handle = NULL; static volatile bool blessing_running = false; /* game state */ static bool game_running = false; static uint8_t game_regions[7]; static TickType_t game_next_spawn; /* OLED */ static uint8_t oled_buf[OLED_BUF_SIZE]; static spi_device_handle_t spi_oled; /* 用于映射:TTP 的 TP 编号 -> LED 索引(0..11) */ /* 你要求:tp 3 2 1 0 15 14 13 12 8 9 10 11 分别对应 第12 11 10 9 8 7 6 5 4 3 2 1 */ /* 也就是:TP3 -> LED idx 11, TP2 -> idx10, ..., TP11 -> idx0 */ static const int8_t tp_to_led_idx[16] = { /* TP0 */ 8, /* TP1 */ 9, /* TP2 */ 10, /* TP3 */ 11, /* TP4 */ -1, /* TP5 */ -1, /* TP6 */ -1, /* TP7 */ -1, /* TP8 */ 3, /* TP9 */ 2, /* TP10 */ 1, /* TP11 */ 0, /* TP12 */ 4, /* TP13 */ 5, /* TP14 */ 6, /* TP15 */ 7 }; /* 小游戏键 -> 七个区域映射(按顺序 region 0..6) */ /* 用户希望:tp3, tp1, tp15, tp14, tp12, tp9, tp11 */ static const int8_t tp_to_game_region[16] = { /* TP0 */ -1, /* TP1 */ 1, /* TP2 */ -1, /* TP3 */ 0, /* TP4 */ -1, /* TP5 */ -1, /* TP6 */ -1, /* TP7 */ -1, /* TP8 */ -1, /* TP9 */ 5, /* TP10 */ -1, /* TP11 */ 6, /* TP12 */ 4, /* TP13 */ -1, /* TP14 */ 3, /* TP15 */ 2 }; /* 颜色预设 */ const uint8_t rainbow_colors[NUM_LEDS][3] = { {255,0,48}, {255,89,0}, {255,183,0}, {255,233,0}, {136,255,0}, {0,255,136}, {0,204,255}, {0,64,255}, {89,0,255}, {183,0,255}, {255,0,191}, {255,0,98} }; /* 16 键音阶(保留) */ static const int note_freqs[16] = { 262,294,330,349,370,392,415,440,466,494,523,554,587,622,659,698 }; /* TTP 原始映射(你的原始 key_map,用于遍历逻辑键) */ static const uint8_t key_map[16] = {3,2,1,0,15,14,13,12,8,9,10,11,4,5,6,7}; /* 小表情/音乐位图(小尺寸) */ /* 音符位图(12x12)*/ static const uint8_t bm_music[] = { 0x10,0x10,0x10,0x18,0x18,0x1C,0x1C,0x0E,0x06,0x06,0x00,0x00, 0x1F,0x1F,0x0F,0x0F,0x07,0x07,0x03,0x03,0x01,0x01,0x00,0x00 }; /* 祝福曲调数据(使用用户给的完整数组) */ /* 这里直接拷贝用户给的大数组 (已包含很多小节) */ typedef struct { int freq; int dur; } tone_t; static const tone_t blessing[] = { /* 使用你提供的数据(我把你的大数组全部包含进来了) */ {494, 600}, {440, 600}, // 小节1 {523, 150}, {440, 150}, {392, 150}, {492, 150}, {523, 150}, {494, 150}, {440, 300}, // 小节2: \dot{7}≈升G(492), \widehat{1}=C(523) {440, 150}, {392, 150}, {440, 150}, {587, 150}, {494, 150}, {494, 150}, {523, 150}, {587, 150}, // 小节3 {587, 150}, {659, 150}, {392, 150}, {659, 150}, {587, 150}, {523, 150}, {494, 150}, {392, 300}, // 小节4 {494, 150}, {523, 150}, {587, 150}, {523, 600}, // 小节5 {0, 600}, {0, 600}, // 小节6 {0, 600}, {0, 600}, // 小节7 {0, 600}, {0, 600}, {494, 150}, {523, 150}, // 小节8 {587, 150}, {494, 150}, {587, 150}, {494, 150}, {587, 150}, {659, 150}, {587, 150}, {587, 150}, {587, 150}, // 小节9 {523, 150}, {494, 150}, {440, 150}, {440, 150}, {392, 150}, {494, 150}, {494, 150}, {0, 150}, {392, 150}, {440, 150}, // 小节10 {494, 150}, {523, 150}, {494, 150}, {494, 150}, {392, 150}, {440, 150}, {494, 150}, {494, 150}, {523, 150}, {494, 150}, {494, 150}, // 小节11 {440, 150}, {440, 150}, {494, 150}, {494, 150}, {440, 150}, {392, 150}, {494, 150}, {494, 150}, {0, 150}, {494, 150}, {523, 150}, // 小节12 {587, 150}, {494, 150}, {587, 150}, {494, 150}, {587, 150}, {392, 150}, {440, 150}, {392, 150}, {440, 150}, {392, 150}, // 小节13 {440, 150}, {440, 150}, {494, 150}, {494, 150}, {440, 150}, {392, 150}, {494, 150}, {494, 150}, {0, 150}, {494, 150}, {523, 150}, // 小节14 {587, 150}, {494, 150}, {587, 150}, {494, 150}, {587, 150}, {659, 150}, {587, 150}, {659, 150}, {587, 150}, {659, 150}, {587, 150}, // 小节15 {523, 150}, {523, 150}, {587, 150}, {587, 150}, {523, 150}, {494, 150}, {587, 150}, {587, 150}, {0, 150}, {494, 150}, {523, 150}, // 小节16 {440, 150}, {440, 150}, {392, 150}, {392, 150}, {440, 150}, {392, 150}, {392, 150}, {392, 150}, {659, 150}, {740, 150}, // 小节17: $^{b}7$≈A(440)? 此处按上下文调整;^♯7→740(F#) {440, 150}, {494, 300}, {392, 150}, {440, 150}, {440, 150}, {440, 150}, {494, 150}, // 小节18 {440, 150}, {440, 150}, {440, 150}, {523, 150}, {440, 150}, {659, 150}, {659, 150}, {740, 150}, // 小节19 {440, 150}, {494, 300}, {392, 150}, {440, 150}, {440, 150}, {494, 150}, // 小节20 {440, 150}, {440, 150}, {440, 150}, {523, 150}, {440, 150}, {740, 150}, {659, 150}, // 小节21 {587, 300}, {392, 150}, {659, 150}, {740, 150}, {392, 150}, {392, 150}, {494, 150}, // 小节22 {392, 150}, {392, 150}, {392, 150}, {392, 150}, {392, 150}, {659, 150}, {392, 150}, {659, 150}, {659, 150}, // 小节23 {523, 300}, {494, 300}, {440, 300}, {392, 300}, {440, 300}, {494, 300}, {523, 300}, // 小节24 {494, 300}, {0, 300}, {626, 150}, {626, 150}, {392, 300}, // 小节25: ^♯2 ≈ B#≈626Hz, 近似C+(523*1.15) {392, 300}, {392, 300}, {392, 300}, {523, 300}, {392, 300}, {659, 300}, // 小节26 {440, 300}, {494, 300}, {440, 300}, // 小节27 {494, 300}, {392, 150}, {392, 150}, {440, 150}, {392, 150}, {0, 300}, {494, 300}, // 小节28 {494, 300}, {392, 150}, {494, 150}, {494, 150}, {659, 150}, {523, 150}, {494, 300}, // 小节29 {659, 300}, {392, 150}, {659, 150}, {587, 150}, {587, 150}, {494, 300}, // 小节30 {494, 150}, {392, 150}, {440, 150}, {494, 150}, {523, 150}, {494, 150}, {440, 150}, {392, 150}, // 小节31 {494, 300}, {392, 150}, {392, 150}, {440, 150}, {392, 150}, {0, 300}, {494, 300}, // 小节32 {494, 300}, {392, 150}, {494, 150}, {494, 150}, {659, 150}, {523, 150}, {494, 300}, // 小节33 {659, 300}, {392, 150}, {659, 150}, {587, 150}, {587, 150}, {494, 300}, // 小节34 {523, 300}, {392, 150}, {659, 150}, {587, 150}, {523, 150}, {494, 150}, {440, 150}, // 小节35 {440, 150}, {392, 150}, {440, 150}, {392, 150}, {0, 300}, {0, 300}, // 小节36 {0, 600}, {0, 600}, {0, 600}, {0, 450}, {494, 150}, // 小节37-40前 {494, 150}, {392, 150}, {392, 150}, {392, 150}, {494, 150}, {494, 150}, {392, 150}, {392, 150}, {392, 150}, {494, 150}, // 小节40 {494, 150}, {392, 150}, {392, 150}, {392, 150}, {494, 150}, {523, 150}, {494, 150}, {494, 150}, // 小节41 {494, 150}, {392, 150}, {392, 150}, {392, 150}, {494, 150}, {494, 150}, {392, 150}, {392, 150}, {392, 150}, {494, 150}, // 小节42 {494, 150}, {392, 150}, {392, 150}, {392, 150}, {440, 150}, {392, 150}, {392, 150}, {494, 150} // 小节43 }; static const int blessing_len = sizeof(blessing) / sizeof(blessing[0]); /* ---------- 前向声明 ---------- */ static void ws2812b_init(void); static void ttp229_init(void); static uint16_t ttp229_read_keys(void); static void buzzer_init(void); static void buzzer_play_tone(int freq); static void oled_refresh(void); static void oled_clear(void); static void oled_draw_bitmap(int x, int y, int w, int h, const uint8_t *bm); static void oled_draw_face_happy(void); static void oled_draw_music_symbol(void); static void led_update_from_state(void); static void led_fade_task(void *arg); static void blessing_task(void *arg); static void start_blessing_task(void); static void stop_blessing_task(void); static void game_spawn_block(void); static void game_draw(void); /* ---------- 实现 ---------- */ static void ws2812b_init(void){ led_strip_config_t strip_config = { .strip_gpio_num = WS2812B_PIN, .max_leds = NUM_LEDS, }; led_strip_rmt_config_t rmt_config = { .resolution_hz = 10 * 1000 * 1000, }; ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config,&rmt_config,&led_strip)); if (!led_mutex) led_mutex = xSemaphoreCreateMutex(); for (int i=0;i<NUM_LEDS;i++){ led_brightness[i]=255; led_active[i]=0; led_strip_set_pixel(led_strip, i, rainbow_colors[i][0], rainbow_colors[i][1], rainbow_colors[i][2]); } led_strip_refresh(led_strip); } static void ttp229_init(void) { gpio_config_t io_conf = {0}; io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pin_bit_mask = (1ULL << TTP229_SCL); gpio_config(&io_conf); io_conf.mode = GPIO_MODE_INPUT; io_conf.pin_bit_mask = (1ULL << TTP229_SDO); gpio_config(&io_conf); gpio_set_level(TTP229_SCL, 1); vTaskDelay(pdMS_TO_TICKS(10)); } static uint16_t ttp229_read_keys(void) { uint16_t data = 0; gpio_set_level(TTP229_SCL, 1); esp_rom_delay_us(2); for (int i = 0; i < 16; i++) { gpio_set_level(TTP229_SCL, 0); esp_rom_delay_us(2); int bit = gpio_get_level(TTP229_SDO); if (bit == 0) data |= (1 << i); gpio_set_level(TTP229_SCL, 1); esp_rom_delay_us(2); } return data; } static void buzzer_init(void) { ledc_timer_config_t timer_conf = { .duty_resolution = LEDC_TIMER_10_BIT, .freq_hz = 1000, .speed_mode = LEDC_LOW_SPEED_MODE, .timer_num = LEDC_TIMER_0 }; ledc_timer_config(&timer_conf); ledc_channel_config_t channel_conf = { .channel = LEDC_CHANNEL_0, .duty = 0, .gpio_num = BUZZER_PIN, .speed_mode = LEDC_LOW_SPEED_MODE, .timer_sel = LEDC_TIMER_0 }; ledc_channel_config(&channel_conf); } /* 播放/停止蜂鸣器 */ static void buzzer_play_tone(int freq) { if (freq <= 0) { ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0); return; } ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0, freq); ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 512); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } /* ---------- OLED 简易驱动 ---------- */ static void oled_send_cmd(const uint8_t *data, size_t len) { spi_transaction_t t = { .length = len * 8, .tx_buffer = data, .flags = 0 }; gpio_set_level(OLED_DC_PIN, 0); ESP_ERROR_CHECK(spi_device_polling_transmit(spi_oled, &t)); } static void oled_send_data(const uint8_t *data, size_t len) { spi_transaction_t t = { .length = len * 8, .tx_buffer = data, .flags = 0 }; gpio_set_level(OLED_DC_PIN, 1); ESP_ERROR_CHECK(spi_device_polling_transmit(spi_oled, &t)); } static void oled_refresh(void) { const uint8_t setcol[] = {0x21, 0, OLED_WIDTH-1}; const uint8_t setpage[] = {0x22, 0, (OLED_HEIGHT/8)-1}; oled_send_cmd(setcol, sizeof(setcol)); oled_send_cmd(setpage, sizeof(setpage)); oled_send_data(oled_buf, OLED_BUF_SIZE); } static void oled_clear(void) { memset(oled_buf, 0, OLED_BUF_SIZE); oled_refresh(); } static void oled_draw_bitmap(int x, int y, int w, int h, const uint8_t *bm) { int bytes_per_col = (h + 7)/8; for (int col=0; col<w; col++) { for (int b=0;b<bytes_per_col;b++) { int src_idx = col*bytes_per_col + b; uint8_t v = bm[src_idx]; for (int bit=0;bit<8;bit++) { int yy = y + b*8 + bit; int xx = x + col; if (yy>=y+h) break; if (xx<0 || xx>=OLED_WIDTH || yy<0 || yy>=OLED_HEIGHT) continue; int page = yy/8; int dst_idx = page*OLED_WIDTH + xx; if (v & (1<<bit)) oled_buf[dst_idx] |= (1<<(yy&7)); } } } } /* 画一个可爱的 (* ̄︶ ̄) 表情 */ static void oled_draw_face_happy(void) { memset(oled_buf, 0, OLED_BUF_SIZE); // ==== 左眼 ==== // 左眼中心大约 (x:35, y:20) for (int yy = 20; yy <= 22; yy++) { for (int xx = 30; xx <= 40; xx++) { if (yy == 21 || yy == 22) { // 两条横线 int page = yy / 8; int idx = page * OLED_WIDTH + xx; oled_buf[idx] |= (1 << (yy & 7)); } } } // ==== 右眼 ==== for (int yy = 20; yy <= 22; yy++) { for (int xx = 85; xx <= 95; xx++) { if (yy == 21 || yy == 22) { int page = yy / 8; int idx = page * OLED_WIDTH + xx; oled_buf[idx] |= (1 << (yy & 7)); } } } // ==== 嘴巴(下弧)==== for (int xx = 46; xx < 82; xx++) { int yy = 42 + (int)(4.0f * sinf(((xx - 46) / 36.0f) * M_PI)); // 弧形 if (yy < 0 || yy >= OLED_HEIGHT) continue; int page = yy / 8; int idx = page * OLED_WIDTH + xx; oled_buf[idx] |= (1 << (yy & 7)); // 稍微加粗 if (yy + 1 < OLED_HEIGHT) { int page2 = (yy + 1) / 8; oled_buf[page2 * OLED_WIDTH + xx] |= (1 << ((yy + 1) & 7)); } } oled_refresh(); } /* 画音乐符号 */ static void oled_draw_music_symbol(void) { memset(oled_buf,0,OLED_BUF_SIZE); oled_draw_bitmap(56, 20, 12, 12, bm_music); oled_refresh(); } /* ---------- LED 控制 ---------- */ static void set_led_rgb(int idx, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) { uint8_t r2 = (r * brightness)/255; uint8_t g2 = (g * brightness)/255; uint8_t b2 = (b * brightness)/255; led_strip_set_pixel(led_strip, idx, r2, g2, b2); } static void led_update_from_state(void) { if (!led_mutex) return; xSemaphoreTake(led_mutex, portMAX_DELAY); for (int i=0;i<NUM_LEDS;i++){ uint8_t b = led_brightness[i]; if (b==0) led_strip_set_pixel(led_strip,i,0,0,0); else set_led_rgb(i, rainbow_colors[i][0], rainbow_colors[i][1], rainbow_colors[i][2], b); } led_strip_refresh(led_strip); xSemaphoreGive(led_mutex); } /* 背景 LED 线程:处理渐变与淡出 */ static void led_fade_task(void *arg) { while (1) { bool changed = false; xSemaphoreTake(led_mutex, portMAX_DELAY); if (g_mode == MODE_LED_KEY_INTERACT) { for (int i=0;i<NUM_LEDS;i++){ if (!led_active[i] && led_brightness[i] > 0) { int nb = (int)led_brightness[i] - 8; if (nb < 0) nb = 0; led_brightness[i] = (uint8_t)nb; changed = true; } } } else if (g_mode == MODE_LED_GRADIENT_CYCLE && gradient_run) { gradient_pos++; for (int i=0;i<NUM_LEDS;i++){ int pos = (i + gradient_pos) % NUM_LEDS; float v = (1.0f + sinf((pos*2.0f*M_PI)/NUM_LEDS)) * 0.5f; int b = 80 + (int)(175.0f * v); if (b < 0) b = 0; if (b>255) b = 255; led_brightness[i] = (uint8_t)b; } changed = true; } else { for (int i=0;i<NUM_LEDS;i++){ if (led_brightness[i] != 255) { led_brightness[i] = 255; changed = true; } } } xSemaphoreGive(led_mutex); if (changed) led_update_from_state(); vTaskDelay(pdMS_TO_TICKS(40)); } } /* ---------- Blessing 播放任务(独立) ---------- */ static void blessing_task(void *arg) { ESP_LOGI(TAG, "Blessing task started"); while (blessing_running) { for (int i=0;i<blessing_len && blessing_running;i++){ int f = blessing[i].freq; int d = blessing[i].dur; if (f > 0) { buzzer_play_tone(f); } else { buzzer_play_tone(0); } // LED 反馈:点亮一个位置(仅 temporary bump) int led_idx = i % NUM_LEDS; xSemaphoreTake(led_mutex, portMAX_DELAY); led_brightness[led_idx] = 255; xSemaphoreGive(led_mutex); led_update_from_state(); // 分段延时以便能响应停止信号 int chunks = d / 20; if (chunks < 1) chunks = 1; for (int c=0;c<chunks && blessing_running;c++){ vTaskDelay(pdMS_TO_TICKS(d / chunks)); } buzzer_play_tone(0); vTaskDelay(pdMS_TO_TICKS(40)); } } buzzer_play_tone(0); ESP_LOGI(TAG, "Blessing task exit"); blessing_task_handle = NULL; vTaskDelete(NULL); } static void start_blessing_task(void) { if (blessing_running) return; blessing_running = true; BaseType_t r = xTaskCreate(blessing_task, "blessing", 4096, NULL, 5, &blessing_task_handle); if (r != pdPASS) { ESP_LOGW(TAG,"Create blessing task failed"); blessing_running = false; blessing_task_handle = NULL; } } static void stop_blessing_task(void) { if (!blessing_running) return; blessing_running = false; // 等待任务自己退出(任务会在循环检查到 blessing_running==false 后 vTaskDelete) int t = 0; while (blessing_task_handle != NULL && t < 50) { vTaskDelay(pdMS_TO_TICKS(50)); t++; } // 最后确保蜂鸣器静音 buzzer_play_tone(0); } /* ---------- 游戏逻辑 ---------- */ static void game_spawn_block(void) { int tries = 0; while (tries < 10) { int r = esp_random() % 7; if (!game_regions[r]) { game_regions[r] = 1; break; } tries++; } } static void game_draw(void) { memset(oled_buf,0,OLED_BUF_SIZE); int region_w = OLED_WIDTH / 7; for (int i=0;i<7;i++){ int x = i*region_w + 4; int y = 12; int w = region_w - 8; int h = 40; if (game_regions[i]) { for (int yy=y; yy<y+h; yy++) for (int xx=x; xx<x+w; xx++){ int page = yy/8; int idx = page*OLED_WIDTH + xx; oled_buf[idx] |= (1 << (yy&7)); } } else { // outline for (int xx=x;xx<x+w;xx++){ int yy=y; int page=yy/8; oled_buf[page*OLED_WIDTH+xx] |= (1<<(yy&7)); yy=y+h-1; page=yy/8; oled_buf[page*OLED_WIDTH+xx] |= (1<<(yy&7)); } for (int yy=y;yy<y+h;yy++){ int xx=x; int page=yy/8; oled_buf[page*OLED_WIDTH+xx] |= (1<<(yy&7)); xx=x+w-1; page=yy/8; oled_buf[page*OLED_WIDTH+xx] |= (1<<(yy&7)); } } } oled_refresh(); } /* ---------- 主程序 ---------- */ void app_main(void) { ESP_LOGI(TAG,"App start"); ws2812b_init(); ttp229_init(); buzzer_init(); // OLED init (SPI bus) // configure DC/CS/RST gpio gpio_config_t io_conf = {0}; io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pin_bit_mask = (1ULL<<OLED_DC_PIN) | (1ULL<<OLED_CS_PIN) | (1ULL<<OLED_RST_PIN); gpio_config(&io_conf); // spi bus init spi_bus_config_t buscfg = { .miso_io_num = -1, .mosi_io_num = OLED_MOSI_PIN, .sclk_io_num = OLED_SCLK_PIN, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = OLED_BUF_SIZE + 8 }; ESP_ERROR_CHECK(spi_bus_initialize(OLED_SPI_HOST, &buscfg, 1)); spi_device_interface_config_t devcfg = { .clock_speed_hz = 8*1000*1000, .mode = 0, .spics_io_num = OLED_CS_PIN, .queue_size = 1, }; ESP_ERROR_CHECK(spi_bus_add_device(OLED_SPI_HOST, &devcfg, &spi_oled)); // Reset OLED gpio_set_level(OLED_RST_PIN, 0); vTaskDelay(pdMS_TO_TICKS(10)); gpio_set_level(OLED_RST_PIN, 1); vTaskDelay(pdMS_TO_TICKS(10)); // init seq (typical) const uint8_t init_cmds[] = { 0xAE,0xD5,0x80,0xA8,0x3F,0xD3,0x00,0x40,0x8D,0x14,0x20,0x00,0xA1,0xC8,0xDA,0x12,0x81,0xCF,0xD9,0xF1,0xDB,0x40,0xA4,0xA6,0xAF }; oled_send_cmd(init_cmds, sizeof(init_cmds)); oled_clear(); // start led fade task xTaskCreate(led_fade_task, "led_fade", 4096, NULL, 5, NULL); uint16_t prev_keys = 0; ESP_LOGI(TAG,"Main loop start"); while (1) { uint16_t keys = ttp229_read_keys(); // active-low -> bit=1 when pressed uint16_t newly = (keys & ~prev_keys); uint16_t releases = (~keys) & prev_keys; // TP4..TP7 功能键 - 注意 TP 编号是芯片输出编号(0..15) // TP4: 切换 LED-key-interact if (newly & (1<<4)) { if (g_mode == MODE_LED_KEY_INTERACT) { g_mode = MODE_NORMAL; oled_clear(); oled_draw_face_happy(); } else { g_mode = MODE_LED_KEY_INTERACT; oled_clear(); oled_draw_face_happy(); } vTaskDelay(pdMS_TO_TICKS(160)); } // TP5: 切换 gradient if (newly & (1<<5)) { if (g_mode == MODE_LED_GRADIENT_CYCLE) { g_mode = MODE_NORMAL; gradient_run = false; oled_clear(); oled_draw_face_happy(); } else { g_mode = MODE_LED_GRADIENT_CYCLE; gradient_run = true; oled_clear(); oled_draw_face_happy(); } vTaskDelay(pdMS_TO_TICKS(160)); } // TP6: 切换 blessing 播放(修正在独立任务中) if (newly & (1<<6)) { if (g_mode == MODE_BLESSING_PLAY) { // 停止 stop_blessing_task(); g_mode = MODE_NORMAL; oled_clear(); oled_draw_face_happy(); } else { // 启动 g_mode = MODE_BLESSING_PLAY; start_blessing_task(); oled_clear(); oled_draw_music_symbol(); } vTaskDelay(pdMS_TO_TICKS(160)); } // TP7: 游戏开关 if (newly & (1<<7)) { if (g_mode == MODE_GAME) { g_mode = MODE_NORMAL; game_running = false; oled_clear(); oled_draw_face_happy(); } else { g_mode = MODE_GAME; game_running = true; memset(game_regions,0,sizeof(game_regions)); game_next_spawn = xTaskGetTickCount() + pdMS_TO_TICKS(800); oled_clear(); oled_draw_face_happy(); } vTaskDelay(pdMS_TO_TICKS(160)); } /* 游戏自动生成 */ if (g_mode == MODE_GAME && game_running) { if (xTaskGetTickCount() > game_next_spawn) { game_spawn_block(); game_next_spawn = xTaskGetTickCount() + pdMS_TO_TICKS(1000 + (esp_random()%2000)); game_draw(); } } /* 处理按键(琴键) */ if (keys) { bool played_any = false; for (int i=0;i<16;i++){ uint8_t tp = key_map[i]; if (keys & (1 << tp)) { // skip function keys (4..7) as they are handled above if (tp>=4 && tp<=7) continue; // 游戏模式下:按键触发对应区域(使用 tp_to_game_region) if (g_mode == MODE_GAME) { int region = tp_to_game_region[tp]; if (region >= 0 && region < 7) { if (game_regions[region]) { game_regions[region] = 0; // 成功提示小音 buzzer_play_tone(880); vTaskDelay(pdMS_TO_TICKS(80)); buzzer_play_tone(0); game_draw(); } else { // 失败提示 buzzer_play_tone(220); vTaskDelay(pdMS_TO_TICKS(60)); buzzer_play_tone(0); } } } else { // 非游戏模式下的常规琴键 // 若处于祝福播放模式,不用主循环来播放音(避免冲突) if (g_mode != MODE_BLESSING_PLAY) { int freq = note_freqs[i]; buzzer_play_tone(freq); played_any = true; } // LED-key-interact 模式:按下即 latch 对应 LED(使用 tp_to_led_idx) int led_idx = tp_to_led_idx[tp]; if (g_mode == MODE_LED_KEY_INTERACT && led_idx >= 0 && led_idx < NUM_LEDS) { xSemaphoreTake(led_mutex, portMAX_DELAY); led_active[led_idx] = 1; led_brightness[led_idx] = 255; xSemaphoreGive(led_mutex); led_update_from_state(); } // gradient 模式下按键会暂时点亮对应 LED if (g_mode == MODE_LED_GRADIENT_CYCLE) { if (led_idx >= 0 && led_idx < NUM_LEDS) { xSemaphoreTake(led_mutex, portMAX_DELAY); led_brightness[led_idx] = 255; xSemaphoreGive(led_mutex); led_update_from_state(); } } // 常态下做 oled 可视化(简单条形) if (g_mode == MODE_NORMAL) { // 简单音乐可视化:点亮与键索引对应的矩形 memset(oled_buf,0,OLED_BUF_SIZE); int bars = NUM_LEDS; int w = OLED_WIDTH / bars; for (int bi=0;bi<bars;bi++){ int x = bi*w + 1; int base_y = OLED_HEIGHT - 2; int bar_h = (bi == i && (keys & (1<<tp))) ? (OLED_HEIGHT/2) : (OLED_HEIGHT/6); for (int yy=base_y-bar_h; yy<=base_y; yy++){ for (int xx = x; xx < x + w - 2; xx++){ if (xx<0 || xx>=OLED_WIDTH || yy<0 || yy>=OLED_HEIGHT) continue; int page = yy/8; int idx = page*OLED_WIDTH + xx; oled_buf[idx] |= (1 << (yy&7)); } } } oled_refresh(); } } } } // end for keys loop if (!played_any && g_mode != MODE_BLESSING_PLAY) { // nothing } vTaskDelay(pdMS_TO_TICKS(40)); } else { if (g_mode != MODE_BLESSING_PLAY) buzzer_play_tone(0); } /* 处理释放:LED-key-interact 模式下 release 要取消 led_active 来触发淡出 */ if (releases) { for (int i=0;i<16;i++){ uint8_t tp = key_map[i]; if (releases & (1<<tp)) { int led_idx = tp_to_led_idx[tp]; if (g_mode == MODE_LED_KEY_INTERACT && led_idx >=0 && led_idx < NUM_LEDS) { xSemaphoreTake(led_mutex, portMAX_DELAY); led_active[led_idx] = 0; // 由 led_fade_task 处理淡出 xSemaphoreGive(led_mutex); } } } } prev_keys = keys; vTaskDelay(pdMS_TO_TICKS(20)); } } 阐释这段代码中是如何使用spi驱动oled显示图案的
最新发布
10-19
3199: 07-22 20:40:03.941 4621 4621 I chromium: [INFO:CONSOLE(1)] "Uncaught ReferenceError: TenvideoJSBridge is not defined", source: https://s.iwan.qq.com/opengame/tenvideo/index.html?hidestatusbar=1&hidetitlebar=1&immersive=1&syswebview=1&gameid=54885&url=https%3A%2F%2Fcls.xjcs.3737.com%2Fhx3%2Fentry.php&ref_ele=10043&isDarkMode=1 (1) 行 3319: 07-22 20:40:04.088 4621 4621 I chromium: [INFO:CONSOLE(3)] "TenvideoJSBridge initialization begin", source: (3) 行 3344: 07-22 20:40:04.109 4621 4621 I chromium: [INFO:CONSOLE(212)] "TenvideoJSBridge initialization end", source: (212) 行 3345: 07-22 20:40:04.109 4621 4621 I chromium: [INFO:CONSOLE(235)] "after init []", source: (235) 行 3392: 07-22 20:40:04.184 4621 4621 I chromium: [INFO:CONSOLE(56)] "log[aegis] begin init aegis", source: https://ovg.gtimg.cn/opengame/v2/assets/common-head.e6e6a46a.js (56) 行 3403: 07-22 20:40:04.195 4621 4621 I chromium: [INFO:CONSOLE(56)] "log[aegis] init event bus", source: https://ovg.gtimg.cn/opengame/v2/assets/common-head.e6e6a46a.js (56) 行 3406: 07-22 20:40:04.205 4621 4621 I chromium: [INFO:CONSOLE(56)] "log[aegis] init aegis, aegis load: true", source: https://ovg.gtimg.cn/opengame/v2/assets/common-head.e6e6a46a.js (56) 行 3424: 07-22 20:40:04.238 4621 4621 I chromium: [INFO:CONSOLE(56)] "log[aegis] init aegis success", source: https://ovg.gtimg.cn/opengame/v2/assets/common-head.e6e6a46a.js (56) 行 3792: 07-22 20:40:05.040 4621 4621 I chromium: [INFO:CONSOLE(85)] "[adapter] init channelid = hx3", source: https://xjcs03.resources.3737.com/wc15/cn/h5/adapter/adapter.js?t=0.19968432772437916 (85) 这段log是安卓14 腾讯视频打开某个小游戏之后,加载到90%就停止了;这个bug该怎么解决
07-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糖果天王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值