两个键之间有多少个白键?

时间:2016-02-23 14:37:48

标签: algorithm

让我们来看看这些类型:

public enum KeyTone : int
{
    C = 0, 
    Cs = 1, 
    D = 2, 
    Ds = 3, 
    E = 4, 
    F = 5, 
    Fs = 6, 
    G = 7, 
    Gs = 8, 
    A = 9, 
    As = 10, 
    H = 11
}

public class PianoKey
{
    public KeyTone Tone { get; set; }
    public int Octave { get; set; }
}

PianoKey代表了一把 - 好吧,你猜对了 - 钢琴的关键。我需要检查有多少白键(例如没有" s"后缀的那些)在两个指定的白键之间。问题是键盘不规则,E和F之间以及下一个八度音阶H和C之间没有黑键。

有一个明显的暴力解决方案 - 跳到下一个白键,直到达到所请求的第二个键。但也许有一些更简单的方法来计算它?

2 个答案:

答案 0 :(得分:2)

首先,计算给定键的基音(我假设所有键都用它们的整数表示):

if tone <= KeyTone.E
    baseTone = tone / 2
else 
    baseTone = (tone + 1) / 2

然后,添加八度音阶:

baseTone += Octave * 7

然后,您可以通过简单的减法找到白键的差异:

 diffInWhiteKeys = baseTone(key1) - baseTone(key2)

E.g。 E2和G3之间的区别是:

baseTone(E2) = 4 / 2 + 2 * 7 = 16
baseTone(G3) = (7 + 1) / 2 + 3 * 7 = 25
diff = 24 - 16 = 9

,这正是您必须从E2前进到G3的白键数。如果您对键之间的白键数感兴趣,只需减去一个。

答案 1 :(得分:1)

创建两个映射

的静态数组
  • 每个黑键到左边或右边的下一个白键,
  • 和每个白键,
  • 将白键从0编号为6。
static int[] whiteLeft  = new int[] {0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6};
static int[] whiteRight = new int[] {0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6};

然后可以计算两个键之间的白键数,就像

一样简单
public static int WhiteKeysBetween(PianoKey left, PianoKey right)
{
    int wl = whiteLeft[(int)left.Tone];
    int wr = whiteRight[(int)right.Tone];

    return (right.Octave - left.Octave) * 7 + (wr - wl - 1);
}       

编辑:这也适用于任意两个键之间的白键(白色或黑色)。我没有意识到问题陈述只要求白键之间的白键。