Advertisement
Guest User

FQG - Source_Code

a guest
Feb 3rd, 2012
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.02 KB | None | 0 0
  1. // FlagQuizGame.java
  2. // mainActivity for the Flag Quiz Game App
  3. package com.deitel.flagquizgame;
  4.  
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Random;
  13. import java.util.Set;
  14.  
  15. import android.app.Activity;
  16. import android.app.AlertDialog;
  17. import android.content.Context;
  18. import android.content.DialogInterface;
  19. import android.content.res.AssetManager;
  20. import android.graphics.drawable.Drawable;
  21. import android.os.Bundle;
  22. import android.os.Handler;
  23. import android.util.Log;
  24. import android.view.LayoutInflater;
  25. import android.view.Menu;
  26. import android.view.MenuItem;
  27. import android.view.View;
  28. import android.view.View.OnClickListener;
  29. import android.view.animation.Animation;
  30. import android.view.animation.AnimationUtils;
  31. import android.widget.Button;
  32. import android.widget.ImageView;
  33. import android.widget.TableLayout;
  34. import android.widget.TableRow;
  35. import android.widget.TextView;
  36.  
  37. public class FlagQuizGame extends Activity
  38. {
  39. // String used when logging error messages
  40. private static final String TAG = "FlagQuizGame Activity";
  41.  
  42. private List<String> fileNameList; // flag file names
  43. private List<String> quizCountriesList; // names of countries in quiz
  44. private Map<String, Boolean> regionsMap; //which regions are enabled
  45. private String correctAnswer; // correct country for the current flag
  46. private int totalGuesses; // number of guesses made
  47. private int correctAnswers; // number of correct guesses
  48. private int guessRows; // number of rows displaying choices
  49. private Random random; // random number generator
  50. private Handler handler; // used to delay loading next flag
  51. private Animation shakeAnimation; // animation for incorrect guess
  52.  
  53. private TextView answerTextView; // displays Correct! or Incorrect!
  54. private TextView questionNumberTextView; // shows current question #
  55. private ImageView flagImageView; // displays a flag
  56. private TableLayout buttonTableLayout; // table of answer Buttons
  57.  
  58. // called when the activity is first created
  59. @Override
  60. public void onCreate(Bundle savedInstanceState)
  61. {
  62. super.onCreate(savedInstanceState); // call the superclass's method
  63. setContentView(R.layout.main); // inflate the GUI
  64.  
  65. fileNameList = new ArrayList<String>(); // list of image file names
  66. quizCountriesList = new ArrayList<String>(); // flags in this quiz
  67. regionsMap = new HashMap<String, Boolean>(); // HashMap of regions
  68. guessRows = 1; // default to one row of choices
  69. random = new Random(); // initialize the random number generator
  70. handler = new Handler(); // used to perform delayed operations
  71.  
  72. // loads the shake animation that's used for incorrect answers
  73. shakeAnimation = AnimationUtils.loadAnimation(this, R.anim.incorrect_shake);
  74. shakeAnimation.setRepeatCount(3); // animation repeats 3 times
  75.  
  76. // get array of world regions from strings.xml
  77. String[] regionNames = getResources().getStringArray(R.array.regionsList);
  78.  
  79. // by default, countries are chosen from all regions
  80. for (String region : regionNames)
  81. regionsMap.put(region, true);
  82.  
  83. // get references to GUI components
  84. questionNumberTextView = (TextView) findViewById(R.id.questionNumberTextView);
  85. flagImageView = (ImageView) findViewById(R.id.flagImageView);
  86. buttonTableLayout = (TableLayout) findViewById(R.id.buttonTableLayout);
  87. answerTextView = (TextView) findViewById(R.id.answerTextView);
  88.  
  89. // set questionNumberTextView's text
  90. questionNumberTextView.setText(getResources().getString(R.string.question) + "1" + getResources().getString(R.string.of) + "10");
  91.  
  92. resetQuiz(); // start a new quiz
  93. } // end method onCreate
  94.  
  95. // set up and start the next quiz
  96. private void resetQuiz()
  97. {
  98. // use the AssetManager to get the image flag
  99. //file names for only the enabled regions
  100. AssetManager assets = getAssets(); // get the app's AssetManager
  101. fileNameList.clear(); // empty the list
  102.  
  103. try
  104. {
  105. Set<String> regions = regionsMap.keySet(); // get Set of regions
  106.  
  107. // loop through each region
  108. for (String region : regions)
  109. {
  110. if (regionsMap.get(region)) // if region is enabled
  111. {
  112. // get a list of all flag image files in this region
  113. String[] paths = assets.list(region);
  114.  
  115. for (String path : paths)
  116. fileNameList.add(path.replace(".png", ""));
  117. } // end if
  118. } // end for
  119. } // end try
  120.  
  121. catch (IOException e)
  122. {
  123. Log.e(TAG, "Error loading file image names", e);
  124. } // end catch
  125.  
  126. correctAnswers = 0; // reset the number of correct answers made
  127. totalGuesses = 0; // reset the total number of guesses the user made
  128. quizCountriesList.clear(); // clear prior list of quiz countries
  129.  
  130. // add 10 random file names to the quizCountriesList
  131. int flagCounter = 1;
  132. int numberOfFlags = fileNameList.size(); // get number of flags
  133.  
  134. while (flagCounter <= 10)
  135.  
  136. {int randomIndex = random.nextInt(numberOfFlags); // random index
  137.  
  138. // get the random file name
  139. String fileName = fileNameList.get(randomIndex);
  140.  
  141. // if the region is enabled and it hasn't already been chosen
  142. if (!quizCountriesList.contains(fileName))
  143. {
  144. quizCountriesList.add(fileName); // add the file to the list
  145. ++flagCounter;
  146. } // end if
  147. } // end while
  148.  
  149. loadNextFlag(); // start the quiz by loading the first flag
  150. } // end method resetQuiz
  151.  
  152. // after the user guesses a correct flag, load the next flag
  153. private void loadNextFlag()
  154. {
  155. // get file name of the next flag and remove it from the list
  156. String nextImageName = quizCountriesList.remove(0);
  157. correctAnswer = nextImageName; // update the correct answer
  158.  
  159. answerTextView.setText(""); // clear answerTextView
  160.  
  161. // display the number of the current question in the quiz
  162. questionNumberTextView.setText(getResources().getString(R.string.question) + "" +
  163. (correctAnswers + 1) + "" + getResources().getString(R.string.of) +"10");
  164.  
  165. // extract the region from the next image's name
  166. String region = nextImageName.substring(0, nextImageName.indexOf('-'));
  167.  
  168. //use AssetManager to load next image from assets folder
  169. AssetManager assets = getAssets(); // get app's AssetManager
  170. InputStream stream; // used to read in flag images
  171.  
  172. try
  173. {
  174. // get an InputStream to the asset representing the next flag
  175. stream = assets.open(region + "/" + nextImageName + ".png");
  176.  
  177. // load the asset as a Drawable and display on the flagImageView
  178. Drawable flag = Drawable.createFromStream(stream, nextImageName);
  179. flagImageView.setImageDrawable(flag);
  180. } // end try
  181. catch (IOException e)
  182. {
  183. Log.e(TAG, "Error loading" + nextImageName, e);
  184. } // end catch
  185.  
  186. // clear prior answer Buttons from TableRow
  187. for (int row = 0; row < buttonTableLayout.getChildCount(); ++row)
  188. ((TableRow) buttonTableLayout.getChildAt(row)).removeAllViews();
  189.  
  190. Collections.shuffle(fileNameList); // shuffle file names
  191.  
  192. //put the correct answer at the end of fileNameList
  193. int correct = fileNameList.indexOf(correctAnswer);
  194. fileNameList.add(fileNameList.remove(correct));
  195.  
  196. // get a reference to the LayoutInflater service
  197. LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  198.  
  199. //add 3, 6, or 9 answer Buttons based on the value of guessRows
  200. for (int row = 0; row < guessRows; row++)
  201. {
  202. TableRow currentTableRow = getTableRow(row);
  203.  
  204. //place Buttons in currentTableRow
  205. for (int column = 0; column < 3; column++)
  206. {
  207. // inflate guess_button.xml to create new Button
  208. Button newGuessButton = (Button) inflater.inflate(R.layout.guess_button, null);
  209.  
  210. // get country name and set it as newGuessButton's text
  211. String fileName = fileNameList.get((row * 3) + column);
  212. newGuessButton.setText(getCountryName(fileName));
  213.  
  214. // register answerButtonListener to respond to button clicks
  215. newGuessButton.setOnClickListener(guessButtonListener);
  216. currentTableRow.addView(newGuessButton);
  217. } // end for
  218. } // end for
  219.  
  220. // randomly replace one Button with the correct answer
  221. int row = random.nextInt(guessRows); // pick random row
  222. int column = random.nextInt(3); // pick random column
  223. TableRow randomTableRow = getTableRow(row); // get the TableRow
  224. String countryName = getCountryName(correctAnswer);
  225. ((Button)randomTableRow.getChildAt(column)).setText(countryName);
  226. } // end method loadNextFlag
  227.  
  228. // returns the specified TableRow
  229. private TableRow getTableRow(int row)
  230. {
  231. return (TableRow) buttonTableLayout.getChildAt(row);
  232. } // end method getTableRow
  233.  
  234. //parses the country flag file name and returns the country name
  235. private String getCountryName(String name)
  236. {
  237. return name.substring(name.indexOf('-') + 1).replace('_', ' ');
  238. } // end method getCountryName
  239.  
  240. // called when the user selects an answer
  241. private void submitGuess(Button guessButton)
  242. {
  243. String guess = guessButton.getText().toString();
  244. String answer = getCountryName(correctAnswer);
  245. ++totalGuesses; // increment the number of guesses the user has made
  246.  
  247. // if the guess is correct
  248. if (guess.equals(answer))
  249. {
  250. ++correctAnswers; // increment the number of correct answers
  251.  
  252. // display "Correct!" in green text
  253. answerTextView.setText(answer + "!");
  254. answerTextView.setTextColor(getResources().getColor(R.color.correct_answer));
  255.  
  256. disableButtons(); // disable all answer Buttons
  257.  
  258. // if the user has correctly identified 10 flags
  259. if (correctAnswers == 10)
  260. {
  261. // create a ne AlertDialog Builder
  262. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  263. builder.setTitle(R.string.reset_quiz); // title bar string
  264.  
  265. // set the AlertDialog's message to display game results
  266. builder.setMessage(String.format("%d, %s, %.02f%% %s",
  267. totalGuesses, getResources().getString(R.string.guesses),
  268. (100 / (double) totalGuesses),
  269. getResources().getString(R.string.correct)));
  270.  
  271. builder.setCancelable(false);
  272.  
  273. // add "Reset Quiz" Button
  274. builder.setPositiveButton(R.string.reset_quiz,
  275. new DialogInterface.OnClickListener()
  276. {
  277. public void onClick(DialogInterface dialog, int id)
  278. {
  279. resetQuiz();
  280. } // end method onClick
  281. } // end anonymous inner class
  282. ); // end call to setPositiveButton
  283.  
  284. // create AlertDialog from the Builder
  285. AlertDialog resetDialog = builder.create();
  286. resetDialog.show(); // display the Dialog
  287. } // end if
  288. else // answer is correct but quiz is not over
  289. {
  290. // load the next flag after a 1-second delay
  291. handler.postDelayed(new Runnable()
  292. {
  293. @Override
  294. public void run()
  295. {
  296. loadNextFlag();
  297. }
  298. }, 1000); // 100 milliseconds for 1-second delay
  299. } // end else
  300. } // end if
  301. else // guess was incorrect
  302. {
  303. //play the animation
  304. flagImageView.startAnimation(shakeAnimation);
  305.  
  306. // display "Incorrect!" in red
  307. answerTextView.setText(R.string.incorrect_answer);
  308. answerTextView.setTextColor(getResources().getColor(R.color.incorrect_answer));
  309. guessButton.setEnabled(false); // disable the incorrect answer
  310. } // end else
  311. } // end method submitGuess
  312.  
  313. // utility method that disables all answer Buttons
  314. private void disableButtons()
  315. {
  316. for (int row = 0; row < buttonTableLayout.getChildCount(); ++row)
  317. {
  318. TableRow tableRow = (TableRow) buttonTableLayout.getChildAt(row);
  319. for (int i = 0; i < tableRow.getChildCount(); ++i)
  320. tableRow.getChildAt(i).setEnabled(false);
  321. } // end outer for
  322. } // end method disableButtons
  323.  
  324. // create constants for each menu id
  325. private final int CHOICES_MENU_ID = Menu.FIRST;
  326. private final int REGIONS_MENU_ID = Menu.FIRST + 1;
  327.  
  328. // called when the user accesses the options menu
  329. @Override
  330. public boolean onCreateOptionsMenu(Menu menu)
  331. {
  332. super.onCreateOptionsMenu(menu);
  333.  
  334. // add two options to the menu - "Choices" and "Regions"
  335. menu.add(Menu.NONE, CHOICES_MENU_ID, Menu.NONE, R.string.choices);
  336. menu.add(Menu.NONE, REGIONS_MENU_ID, Menu.NONE, R.string.regions);
  337.  
  338. return true; // display the menu
  339. } // end method onCreateOptionsMenu
  340.  
  341. // called when the user selects an option from the menu
  342. @Override
  343. public boolean onOptionsItemSelected(MenuItem item)
  344. {
  345. // switch the menu id of the user-selected option
  346. switch (item.getItemId())
  347. {
  348. case CHOICES_MENU_ID:
  349. // create a list of the possible numbers of answers of choices
  350. final String[] possibleChoices = getResources().getStringArray(R.array.guessesList);
  351.  
  352. // create a new AlertDialog Builder and set its title
  353. AlertDialog.Builder choicesBuilder = new AlertDialog.Builder(this);
  354. choicesBuilder.setTitle(R.string.choices);
  355.  
  356. //add possibleChoices items to the Dialog and set the
  357. // behavior when one of the items is clicked
  358. choicesBuilder.setItems(R.array.guessesList,
  359. new DialogInterface.OnClickListener()
  360. {
  361. public void onClick(DialogInterface dialog, int item)
  362. {
  363. //update guessRows to match the user's choice
  364. guessRows = Integer.parseInt(possibleChoices[item].toString()) / 3;
  365. resetQuiz(); // reset the quiz
  366. } // end method onClick
  367. } // end anonymous inner class
  368. ); // end call to setItems
  369.  
  370. // create an AlertDialog from the Builder
  371. AlertDialog choicesDialog = choicesBuilder.create();
  372. choicesDialog.show();
  373. return true;
  374.  
  375. case REGIONS_MENU_ID:
  376. // get array of world regions
  377. final String[] regionNames = regionsMap.keySet().toArray(new String[regionsMap.size()]);
  378.  
  379. // boolean array representing whether each region is enabled
  380. boolean[] regionsEnabled = new boolean[regionsMap.size()];
  381. for (int i = 0; i < regionsEnabled.length; ++i)
  382. regionsEnabled[i] = regionsMap.get(regionNames[i]);
  383.  
  384. // create an AlertDialog Builder and set the dialog's title
  385. AlertDialog.Builder regionsBuilder = new AlertDialog.Builder(this);
  386. regionsBuilder.setTitle(R.string.regions);
  387.  
  388. // replace _ with space in region names for display purposes
  389. String[] displayNames = new String[regionNames.length];
  390. for (int i = 0; i < regionNames.length; ++i)
  391. displayNames[i] = regionNames[i].replace('_', ' ');
  392.  
  393. // add displayNames to the Dialog and set the behavior
  394. // when one of the items is clicked
  395. regionsBuilder.setMultiChoiceItems(
  396. displayNames, regionsEnabled,
  397. new DialogInterface.OnMultiChoiceClickListener()
  398. {
  399. @Override
  400. public void onClick(DialogInterface dialog, int which,
  401. boolean isChecked)
  402. {
  403. //include or exclude the clicked region
  404. // depending on whether or not it's checked
  405. regionsMap.put(regionNames[which].toString(), isChecked);
  406. } // end method onClick
  407. } // end anonymous inner class
  408. ); // end call to setMultiChoiceItems
  409.  
  410. //resets quiz when user presses the "Reset Quiz" Button
  411. regionsBuilder.setPositiveButton(R.string.reset_quiz,
  412. new DialogInterface.OnClickListener()
  413. {
  414. @Override
  415. public void onClick(DialogInterface dialog, int button)
  416. {
  417. resetQuiz(); // reset the quiz
  418. } // end method onClick
  419. } // end anonymous inner class
  420. ); // end call to method setPositiveButton
  421.  
  422. // create a dialog from the Builder
  423. AlertDialog regionsDialog = regionsBuilder.create();
  424. regionsDialog.show(); // display the Dialog
  425. return true;
  426. } // end switch
  427.  
  428. return super.onOptionsItemSelected(item);
  429. } // end method onOptionsItemSelected
  430.  
  431. // called when a guess Button is touched
  432. private OnClickListener guessButtonListener = new OnClickListener()
  433. {
  434. @Override
  435. public void onClick(View v)
  436. {
  437. submitGuess((Button) v); // pass selected Button to submitGuess
  438. } // end method onClick
  439. }; // end answerButtonListener
  440. } // end FlagQuizGame
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement