2016-03-28 58 views
8

我一直在編寫一個程序,它會播放一系列音樂文件的名稱並播放它們。我成功地做到了這一點,但是,我想要改進一些事情,並讓它更好一些。我試圖讓音樂以隨機順序播放,但在整個列表播放之前不會重複播放任何歌曲。我幾乎能夠做到這一點,但我認爲我的do-while循環有問題。該程序按照預期運行約8首歌曲,但隨後停止播放音樂,並且JVM繼續運行。我使用BlueJ,因爲我仍然是AP Comp Sci的學生,所以我意識到我可能無法完成此任務,但任何幫助將不勝感激。我有一個驅動程序「MusicDriver」,它與另外兩個類「MP3」和「Music」具有「有-A」關係。爲什麼在此Java程序中do-while循環沒有像預期的那樣運行?

我的MP3類:

import java.io.BufferedInputStream; 
import java.io.FileInputStream; 
import javazoom.jl.player.Player; 

public class MP3 { 
    String filename; 
    Player player; 

    public void stopMP3() { if (player != null) player.close(); } 

    // play the MP3 file to the sound card 
    public void playMP3(String filename) { 
    try { 
     FileInputStream fis = new FileInputStream(filename); 
     BufferedInputStream bis = new BufferedInputStream(fis); 
     player = new Player(bis); 
    } 
    catch (Exception e) { 
     System.out.println("Problem playing file " + filename); 
     System.out.println(e); 
    } 

    // run in new thread to play in background 
    new Thread() { 
     public void run() { 
      try { player.play(); } 
      catch (Exception e) { System.out.println(e); } 
     } 
    }.start(); 
} 
} 

我的音樂類:

import java.util.*; 

public class Music{ 
private ArrayList<String> music; 

public Music(){music = new ArrayList<String>();} 

public int size(){return music.size();} 

public void addSong(String song){music.add(song);} 

public String getSong(){return music.get(music.size());} 

public String getSong(int num){return music.get(num);} 

public void removeSong(String song){ 
    for(int i = 0; i < music.size(); i++){ 
     if(music.get(i).equals(song)) {music.remove(i); return;} 
    } 
} 

public String toString(){ 
    String s = ""; 
    for(int i = 0; i < music.size(); i++){ 
     s += music.get(i); 
    } 
    return s; 
} 
} 

我MusicDriver類:

import java.util.*; 
import java.io.*; 
import javazoom.jl.player.Player; 
import java.util.Random; 
import java.util.Scanner; 
import java.io.FileNotFoundException; 

public class MusicDriver{ 
public static void main(String[] args) throws FileNotFoundException{ 
    Random r = new Random(); 
    Scanner s = new Scanner(System.in); 
    String line = ""; 
    int number; 

    Music song = new Music(); 
    song.addSong("1-01-overture.mp3"); 
    song.addSong("1-03-fortune-teller-2.mp3"); 
    song.addSong("1-07-prayer.mp3"); 
    song.addSong("1-08-island-atlas.mp3"); 
    song.addSong("1-12-warren-report.mp3"); 
    song.addSong("1-13-avilla-hanya.mp3"); 
    song.addSong("1-20-war-situation.mp3"); 
    song.addSong("2-10-fog-of-phantom.mp3"); 
    song.addSong("2-12-religious-precepts.mp3"); 
    song.addSong("2-14-box-of-sentiment.mp3"); 
    song.addSong("3-02-light-everlasting.mp3"); 
    song.addSong("3-09-viking-spirits.mp3"); 
    song.addSong("3-12-unsealed.mp3"); 
    song.addSong("3-16-notice-of-death-reprise-.mp3"); 
    //14 songs 

    ArrayList<Integer> songNums = new ArrayList<Integer>(); 
    MP3 mp3 = new MP3(); 
    do{ 
     if(songNums.size() == song.size()) songNums.clear(); 

     number = r.nextInt(song.size()); 
     boolean done = false; 
     int counter = 0; 
     while(!done){ 
      for(int i = 0; i < songNums.size(); i++){ 
       if(number == songNums.get(i).intValue()) {number = r.nextInt(song.size()); counter++;} 
      } 
      if(counter == 0) done = true; 
      else done = false; 
     } 

     songNums.add(number); 
     mp3.playMP3(song.getSong(number)); 
     System.out.println("Now Playing " + song.getSong(number)); 
     System.out.println("Enter \"Stop\" to stop playing the song"); 
     System.out.println("Enter \"n\" to play the next song"); 
     line = s.nextLine(); 
     mp3.stopMP3(); 
    }while(line.equals("n")); 
    mp3.stopMP3(); 
} 
} 

我已經做了很多研究,爲什麼我的程序剛剛停止播放我的歌曲,但我一直無法找到任何東西。我做了,發現BlueJ程序沒有打開終端窗口(當你做一個「System.out.print()」時出現的東西),如果你在輸出之前詢問輸入,但我不認爲這是該計劃的考慮因素。我還確定,當我想播放下一首歌曲和第一首情侶歌曲時,我輸入了一個字符串「n」,但它在第八首歌曲後停止。我完全困惑。

+11

剛剛['Collections.shuffle()'](http://docs.oracle.com/javase/8/docs/api/java/util/Collections .html#shuffle-java.util.List-)列表並在for-each循環中逐個播放歌曲 –

+0

在do-while循環結束之前是否必須調用stopMP3?我懷疑有可能導致過早停工。 –

+0

你是否有機會獲得任何例外? –

回答

7

我認爲唯一的問題在於你用於洗牌清單的邏輯。

number = r.nextInt(song.size()); 
boolean done = false; 
int counter = 0; 
while(!done){ 
    for(int i = 0; i < songNums.size(); i++){ 
     if(number == songNums.get(i).intValue()) {number = r.nextInt(song.size()); counter++;} 
    } 
    if(counter == 0) done = true; 
    else done = false; 
} 

當生成的隨機數已經存在於songNums列表中時,您正在生成一個新的隨機數。這個新的隨機數不是用所有數量的songNums列表檢查的。以下更改應解決您的問題。

boolean done = false; 
    while(!done){ 
     number = r.nextInt(song.size()); 
     if(!songNum.contains(number)) done = true; 
    } 

或者,你可以使用Sasha的在評論中建議洗牌列表(Collections.shuffle())。

3

現有算法的實際問題是,當您發現已播放的歌曲時,您沒有重置counter。所以只要你重複一遍,你就會陷入無限循環 - done永遠不會是真的。

(事實上,它不會是無限的 - 一旦counter達到Integer.MAX_VALUE它會環繞到Integer.MIN_VALUE,最終再次達到0,所以如果你離開它足夠長的時間,將最終打另一首歌曲)

有這裏一些有益的建議已經有大約改進的代碼,我這裏就不再贅述,但最小的變化,將解決你有什麼是的counter初始化移動到0內環路:

boolean done = false; 

while(!done){ 
    int counter = 0; // reset counter every time 

    for(int i = 0; i < songNums.size(); i++){ 
     if(number == songNums.get(i).intValue()) {number = r.nextInt(song.size()); counter++;} 
    } 

    if(counter == 0) done = true; 
    else done = false; 
} 
3

Sasha在評論中表示:使用Collections.shuffle()。在實踐中,將看起來律」是這樣的:

在音樂類有一個方法來獲取所有的歌曲:

public List<String> getSongs() {return music;} 

在MusicDriver這個循環是沿着線:

List<String> songs = song.getSongs(); 
do{ 
    Collections.shuffle(songs); 
    for (String songToPly: songs) { 
     mp3.playMP3(song.getSong(number)); 
     System.out.println("Now Playing " + song.getSong(number)); 
     System.out.println("Enter \"Stop\" to stop playing the song"); 
     System.out.println("Enter \"n\" to play the next song"); 
     mp3.stopMP3(); 
     line = s.nextLine(); 
     if (!line.equals("n")) break; 
    } 
}while(line.equals("n")); 

在一個可變命名說明中,將您的Music類的實例命名爲「song」(單數)是有點令人困惑的。也許稱它爲「音樂」或至少是「歌曲」。

0

我會做的是:

public class MainClass() { 

    public static void main(String[] args) { 
     PlayerWrapper player = new PlayerWrapper(); 
    } 
} 

public class PlayerWrapper() { 
    private List<MP3> playlist; 
    private Scanner userInputReader; 
    private String currentUserInput; 

    public PlayerWrapper() { 
     userInputReader = new Scanner(System.in()); 
     System.out.println("Filepath to playlist?"); 
     String playlistFileName = userInputReader.nextLine(); 
     playlist = PlayListExtractor.extractPlaylist(playlistFileName); 
     start(); 
    } 

    public void start() { 
     playlistCopy = new ArrayList<MP3>(playlist); 
     shufflePlayList(playlistCopy); 
     Iterator<MP3> songIterator = playlistCopy.iterator(); 
     while (songIterator.hasNext()) { 
      MP3 song = songIterator.next(); 
      songIterator.remove(); 
      player = new Player(song.toStream()); 
      player.play(); 
      displayCurrentSongAndCommands(song); 
      currentUserInput = userInputReader.nextLine(); 
      if ("Stop".equals(currentUserInput)) { 
       player.close(); 
       break; 
      } else if ("n".equals(currentUserInput)) { 
       player.close(); 
       continue; 
      } 
     } 

     if("Stop".equals(currentUserInput)) { 
      System.out.println("Playlist stopped. Press q to quit or c to continue"); 
      currentUserInput = userInputReader.nextLine(); 
      if ("q".equals(currentUserInput)) { 
       System.exit(0); 
      } else if ("c".equals(currentUserInput)) { 
       start(); 
      } 
     } 
     start(); 
    } 

    private void shufflePlayList(final List<MP3> playlistToBeShuffled) { 
     long seed = System.nanoTime(); 
     Collections.shuffle(playlistToBeShuffled, new Random(seed));    
    } 

    private void displayCurrentSongAndCommands(final MP3 currentSong) { 
     System.out.println("Now Playing " + currentSong.toString()); 
     System.out.println("Enter \"Stop\" to stop playing the song"); 
     System.out.println("Enter \"n\" to play the next song"); 
    } 
} 

public static class PlayListExtractor() { 
    private PlayListExtractor(); 

    public static List<MP3> extractPlayList(final String playListFileName) { 
     List<MP3> result = new ArrayList<>(); 
     try (BufferedReader br = new BufferedReader(new FileReader(file))) { 
      String line; 
      while ((line = br.readLine()) != null) { 
       result.add(new MP3(line)); 
      } 
      return result; 
     } catch (IOException e) { 
      System.out.println("Problem parsing playlist"); 
     } 
    } 
} 

public class MP3 { 
    private String filename; 

    public MP3(final String filename) { 
     this.filename = filename; 
    } 

    public BufferedInputStream toStream() { 
     try { 
      FileInputStream fis = new FileInputStream(filename); 
      return new BufferedInputStream(fis);     
     } 
     catch (Exception e) { 
      System.out.println("Problem playing file " + filename); 
      System.out.println(e); 
     } 
    } 

    public String toString() { 
     return filename; 
    } 
} 
相關問題