我已经定义了一个类Note
来表示一种播放某个音符的方法(字符串乐器上的字符串和音品的两个整数),以及一个具有所有ArrayList的类Chord
那个和弦中的音符。
对于播放的每个音符,可能有多种方式播放该音符,因此我有一个Notes的ArrayList表示每种可能的方式。在一个和弦中可以有任意数量的音符,所以我有一个ArrayList的ArrayList。从这里我想创建一个和弦的ArrayList,每种方式都可以演奏和弦。
我已经定义了一个构造函数Chord(ArrayList<Note> notes)
例如: 注意A有3种播放方式,注意B 2种播放方式,我想要和弦:
[A1,B1],[A1,B2],[A2 B1],[A2 B2],[A3,B1],[A3,B2]。
我创建了一种方法,该方法在假设总是有3个音符播放的情况下工作,但无法思考如何将其扩展为未知数字
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
ArrayList<Chord> allPlayable = new ArrayList<>();
for (int i = 0; i < candidates.get(0).size(); i++)
{
Note n0 = candidates.get(0).get(i);
for (int j = 0; j < candidates.get(1).size(); j++)
{
Note n1 = candidates.get(1).get(j);
for (int k = 0; k < candidates.get(2).size(); k++)
{
Note n2 = candidates.get(1).get(k);
ArrayList<Note> chordNotes = new ArrayList<>();
chordNotes.add(n0);
chordNotes.add(n1);
chordNotes.add(n2);
allPlayable.add(new Chord(chordNotes));
}
}
}
return allPlayable;
}
答案 0 :(得分:0)
建议我使用递归 - 每个for循环都是另一个递归调用,我想出了这个答案
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
//this will be the inner ArrayList we are on
ArrayList<Note> current = new ArrayList();
//the list of chords to return
ArrayList<Chord> allPlayable = new ArrayList();
allPlayableRecurse(candidates, 0, current, allPlayable);
return allPlayable;
}
public static void allPlayableRecurse(ArrayList<ArrayList<Note>> candidates, int index, ArrayList<Note> chordNotes, ArrayList<Chord> allPlayable)
{
ArrayList<Note> current = candidates.get(index);
//for each note in the current array list of notes
for (int i = 0; i < current.size(); i++)
{
chordNotes.add(current.get(i));
//there are more notes to add
if (index < candidates.size()-1)
{
//go to the next inner ArrayList
allPlayableRecurse(candidates, index+1, chordNotes, allPlayable);
}
else//we have reached the last note
{
//add the chord to the list
allPlayable.add(new Chord((ArrayList<Note>)chordNotes.clone()));
}
//we will now replace this note
chordNotes.remove(chordNotes.size()-1);
}
}
答案 1 :(得分:0)
您可以使用递归,例如:
List<List<Note>> combine(List<List<Note>> representations) {
List<Note> options = representations.get(0);
List<List<Note>> tails;
if (representations.size()==1) {
tails = new ArrayList<>();
tails.add(Collections.emptyList());
} else {
tails = combine(representations.subList(1, representations.size()));
}
List<List<Note>> combinations = new ArrayList<>(options.size());
for (Note note : options) {
for (List<Note> tail : tails) {
List<Note> chord = new ArrayList<>();
chord.add(note);
chord.addAll(tail);
combinations.add(chord);
}
}
return combinations;
}
public List<Chord> allPlayable(List<List<Note>> candidates) {
List<List<Note>> combinations = combine(candidates);
List<Chord> chords = new ArrayList<>(combinations.size());
for (List<Note> notes : combinations) chords.add(new Chord(notes));
return chords;
}
这是旧的java7风格。使用新的Java8功能操作可以更轻松地完成它,但如果刚刚开始,则不确定它是否已经是您的事情。