超声波测距原理
超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。(超声波在空气中的传播速度为340m/s,根据计时器记录的时间t(秒),就可以计算出发射点距障碍物的距离(s),即:s=340t/2)
超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。(超声波在空气中的传播速度为340m/s,根据计时器记录的时间t(秒),就可以计算出发射点距障碍物的距离(s),即:s=340t/2)
数字光强度检测模块:GY-30
采用IIC通讯方式,GY-30VCC接+5V,GND接地。GY-30 SDA 、SCL分别接A4、 A5
DHT11 是一款温湿度传感器,可以用来测试环境温湿度,该传感器的的温度测量范围为 0 ~ 50°C,误差为 2 °C;湿度测量范围为在 0°C时为30%-90%RH,环境温度为 25°C时,湿度测量范围为20%-90%RH,在50°C时,测量范围是20%-80%。
闲暇的时候写的小程序,从map输入数独的题目后自动计算。
#include "stdafx.h"
#include <vector>
#include <map>
#include <iostream>
#include <assert.h>
// 获取行index
std::vector<int> askRow(int index)
{
std::vector<int> rownum;
auto rowindex = index / 10;
for (int i = 0; i < 9; i++)
{
rownum.push_back(rowindex * 10 + i);
}
return rownum;
}
// 获取列index
std::vector<int> askCol(int index)
{
std::vector<int> colnum;
auto colindex = index % 10;
for (int i = 0; i < 9; i++)
{
colnum.push_back(i * 10 + colindex);
}
return colnum;
}
// 获取宫index
std::vector<int> askBlock(int index)
{
std::vector<std::vector<int>> blocknum = {
{0,1,2,10,11,12,20,21,22},
{3,4,5,13,14,15,23,24,25},
{6,7,8,16,17,18,26,27,28},
{30,31,32,40,41,42,50,51,52},
{33,34,35,43,44,45,53,54,55},
{36,37,38,46,47,48,56,57,58},
{60,61,62,70,71,72,80,81,82},
{63,64,65,73,74,75,83,84,85},
{66,67,68,76,77,78,86,87,88},
};
for (const std::vector<int>& item : blocknum)
{
if (item.end() != std::find(item.begin(), item.end(), index))
return item;
}
assert(false);
return std::vector<int>();
}
// 检查冲突(入参为格子的值,而非index)
bool check(const std::vector<char>& block)
{
char checknum[9] = { 0 };
for (auto item : block)
{
if (item == 0)
continue;
// 同一位置已经有值了
if (checknum[item - 1] == 1)
return false;
// 占位
checknum[item - 1] = 1;
}
return true;
}
// 获取一个检查数据
std::vector<char> getBlock(const std::vector<char>& table, const std::vector<int>& block)
{
assert(block.size() == 9);
std::vector<char> blockData;
for (size_t i = 0; i < block.size(); ++i)
{
blockData.push_back(table.at(block.at(i)));
}
return blockData;
}
bool calcBackup(std::vector<char>& table, std::vector<std::pair<char, std::vector<char>>>& backupmap)
{
// 侯选数
backupmap.clear();
for (int index = 0; index < 90; ++index)
{
if (index % 10 == 9)
continue;
if (table.at(index) > 0)
continue;
// 获取三种类型的数据集
auto blockRow = askRow(index);
auto blcokDataRow = getBlock(table, blockRow);
auto blockCol = askCol(index);
auto blcokDataCol = getBlock(table, blockCol);
auto block = askBlock(index);
auto blcokData = getBlock(table, block);
// 获取每个格子的候选数
std::vector<char> vec;
for (int i = 1; i < 10; i++)
{
if (blcokDataRow.end() == std::find(blcokDataRow.begin(), blcokDataRow.end(), i) &&
blcokDataCol.end() == std::find(blcokDataCol.begin(), blcokDataCol.end(), i) &&
blcokData.end() == std::find(blcokData.begin(), blcokData.end(), i))
vec.push_back(i);
}
// 如果只有一个候选数,则重算
assert(vec.size() > 0);
if (vec.size() == 1)
{
table.at(index) = vec[0];
return true;
}
backupmap.push_back(std::make_pair(index, vec));
}
return false;
}
// 递归,一个个的试
bool calc(std::vector<char>& table, const std::vector<std::pair<char, std::vector<char>>>& backupmap, int num, int index)
{
int currentIndex = backupmap.at(num).first;
table.at(currentIndex) = backupmap.at(num).second.at(index);
auto blockRow = askRow(currentIndex);
auto blockCol = askCol(currentIndex);
auto block = askBlock(currentIndex);
if (check(getBlock(table, block)) && check(getBlock(table, blockRow)) && check(getBlock(table, blockCol)))
{
if (num >= backupmap.size() - 1)
{
// 计算到最后一格,出现全部备选数据相匹配的情况
return true;
}
else
{
// 当前格子匹配正常,继续计算下一个
for (int index = 0; index < backupmap.at(num + 1).second.size(); ++index)
{
if (calc(table, backupmap, num + 1, index))
{
return true;
}
}
}
}
table.at(currentIndex) = 0;
return false;
}
void prinfTable(const std::vector<char>& table)
{
for (int row = 0; row < 9; ++row)
{
if (row % 3 == 0)
{
printf("------------------------------------------ \n");
}
printf("%4d%4d%4d | %4d%4d%4d | %4d%4d%4d \n", table[row * 10], table[row * 10 + 1], table[row * 10 + 2],
table[row * 10 + 3], table[row * 10 + 4], table[row * 10 + 5],
table[row * 10 + 6], table[row * 10 + 7], table[row * 10 + 8]);
}
}
bool fill(const std::map<char, char>& origin, std::vector<char>& table)
{
for (auto item : origin)
{
table.at(item.first) = item.second;
}
int i = 0;
std::vector<std::pair<char, std::vector<char>>> backupmap;
while (calcBackup(table, backupmap))
{
if (i++ > 90)
break;
}
if (backupmap.size() > 0)
{
for (int index = 0; index < backupmap.front().second.size(); ++index)
{
if (calc(table, backupmap, 0, index))
{
return true;
}
}
return false;
}
return true;
}
int main()
{
std::map<char, char> origin;
origin.insert(std::make_pair(12, 1));
origin.insert(std::make_pair(15, 9));
origin.insert(std::make_pair(18, 7));
origin.insert(std::make_pair(20, 7));
origin.insert(std::make_pair(22, 9));
origin.insert(std::make_pair(23, 4));
origin.insert(std::make_pair(27, 2));
origin.insert(std::make_pair(28, 3));
origin.insert(std::make_pair(32, 4));
origin.insert(std::make_pair(33, 7));
origin.insert(std::make_pair(36, 6));
origin.insert(std::make_pair(43, 1));
origin.insert(std::make_pair(44, 5));
origin.insert(std::make_pair(47, 8));
origin.insert(std::make_pair(55, 4));
origin.insert(std::make_pair(61, 2));
origin.insert(std::make_pair(66, 7));
origin.insert(std::make_pair(67, 3));
origin.insert(std::make_pair(70, 5));
origin.insert(std::make_pair(71, 8));
origin.insert(std::make_pair(74, 1));
origin.insert(std::make_pair(78, 2));
origin.insert(std::make_pair(84, 4));
origin.insert(std::make_pair(85, 3));
std::vector<char> table(90, 0);
if (fill(origin, table))
{
std::cout << "happy end" << std::endl;
prinfTable(table);
}
else
{
std::cout << "sorry" << std::endl;
}
getchar();
return 0;
}
使用 canvas 画布来操控图形或者图片的二维变化的方式一般是平移、缩放、和旋转。canvas 已相应提供了相关的 api。如:translate(), scale() 和 rotate(),但这些功能无法统一处理并且无法描述当前画布的处于某种状态。为了实现这种统一连贯性的状态描述,canvas 给我们提供了另外一种思路及方法,即使用:transform() / setTransform();因为画布上的每个对象都拥有一个当前的 3 x 3 变换矩阵,都可以使用一个 3 x 3 矩阵来描述当前状态,其实是 2 x 3 矩阵,但为了便于计算,人为添加第三行 0 0 1 变成 3 x 3 矩阵。费话不多话,下面直接看矩阵变换的已封装好的功能,为了便于读者理解,每一步都有详细解释及介绍。
b2 命令的功能强大,用起来也比较复杂,因此在使用之前,最好先查看一下该命令的帮助:
b2.exe --help
stage 表示只生成库(dll 和 lib),install 还会生成包含头文件的 include 目录。推荐使用 stage,因为 install 生成的 include 目录实际就是源码包下的 boost 目录,需要 include 的时候可以直接使用,不需要再次生成,这样可以节省大量的编译时间。
将 repo1 作为远程仓库,添加到 repo2 中,并设置别名为 other:
切换至 repo2 仓库,并执行以下命令:
今天要从GitHub上下载东西,结果突然发现GitHub只提供整项目下载,而不支持选择某一个子文件夹下载。
搜索答案,找到了一种方法如下:
如果不是GIT的master分支,则将 /tree/master/ 替换为 /branches/branchname/ 其中 branchname 为分支名
一直以来,使用C++面向对象机制,主要是为了其封装和多态特性。往往设计类时,只是为了功能的堆砌,没有考虑的更加深入。
之前也阅读过《Effective C++》,只是那时是在学生时代。如今工作了,重新阅读,有不少新的感悟。最关键的是,能从更高的视角去设计程序,之前杂乱无序的点与点,逐渐连接成一条条线。希望后续能够成面、成立体。
这里首先你要确保你已经安装了.NET Core 3.0或以上版本。在我编写这篇文章的时候, .NET Core 3.1刚刚发布,Visual Studio应该会提示你升级到最新版本。但是如果你想要在.NET Core 2.x项目中使用这个方式,应该是行不通的。