FizzBuzz is an old coding test used to make sure that interviewees are capable of solving basic coding problems.
The test is thus:
Write a program to count from 1 to 100, when it is on a multiple of 3 have it print Fizz, when it is on a multiple of 5 have it print Buzz. If it is on a multiple of both 3 and 5 have it print FizzBuzz.
The code for this in a simple C++ application is:
int main ()
{
int i = 1;
while (i<101)
{
cout<<"\n"<<i<<": "<<endl;
if (i%3==0)
cout<<"Fizz";
if (i%5==0)
cout<<"Buzz";
i++;
}
}
When I came across FizzBuzz and it’s solution I thought the same thing that I think when I see any application: How can I port this to Android?
So I decided to make a version of FizzBuzz on Android which would really Fizz and Buzz!
So here it is: FizzBuzz for Android.
Coding FizzBuzz for Android turned out to me be much more challenging than I expected:
The UI in android cannot be written to directly from an Activity’s onCreate or onResume methods, however a background function should never execute UI code.
Also when sound files are played they are played by a background service and the system for checking their completion is complicated and better suited to longer audio files. Fizz and Buzz have static lengths and I never want to play Buzz before Fizz, so a logical solution is to wait for 250ms after launching Fizz before launching Buzz.
Also in order to have the lines arrive in a steady order and not have any audio play over other audio I determined that it would be best for every line to take 1 second.
Both the wait for Buzz and the 1 second line wait require a sleep or wait, neither of these functions should be run in the UI thread.
The solution I found was to launch a Runnable as a thread.
The runnable contains the logic and launches the Fizz sound, it also uses another thread to launch the Buzz sound. When the runnable needs to output a new line to the table it uses runonuithread().
public class FizzBuzzActivity extends Activity {
private MediaPlayer fizzMP, buzzMP;
private TableLayout displayTable;
private String srowText, srowNumb;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
displayTable = (TableLayout) findViewById(R.id.table);
fizzMP = MediaPlayer.create(FizzBuzzActivity.this, R.raw.fizz);
buzzMP = MediaPlayer.create(FizzBuzzActivity.this, R.raw.buzz);
new Thread(mUpdate).start();
}
private Runnable mUpdate = new Runnable() {
public void run() {
for (int i = 1; i < 101; i++) {
srowText = "";
srowNumb = i + "|";
srowText = "";
if (i % 3 == 0) {
fizzMP.start();
srowText += "Fizz";
}
if (i % 5 == 0) {
srowText += "Buzz";
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
buzzMP.start();
}
}).start();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
TableRow newRow = new TableRow(FizzBuzzActivity.this);
TextView rowNumb = new TextView(FizzBuzzActivity.this);
TextView rowText = new TextView(FizzBuzzActivity.this);
rowNumb.setText(srowNumb);
rowText.setText(srowText);
newRow.addView(rowNumb, 0);
newRow.addView(rowText, 1);
displayTable.addView(newRow,
new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
complete(buzzMP, fizzMP);
}
void complete(MediaPlayer MP1, MediaPlayer MP2) {
MP1.release();
MP2.release();
}
};
The Audio samples I used in FizzBuzz were clipped from files on SoundBible.com and the Source Code for FizzBuzz is available on GitHub.
It’s amazing how much you can learn doing a simple little project like this one.
-Rory