2014年7月28日 星期一

Android 小遊戲「終極密碼」

Download: gamble.apk

遊戲說明:
這是一個 Android App 數字小遊戲,開始從正整數 1~100間,會隨機產生未知亂數,玩家要從範圍裡面猜出該數數值,猜對數字時,會跳出一個提示視窗,說明該亂數數值及所猜的次數,並有兩個 Button 可以選擇「Restart」或「Close」遊戲。

在過程中發現的幾個重點要注意:
1. 產生亂數的方法。
2. 控制IO (包含顯示出來的訊息及玩家所輸入的資料),還要避免輸入空字串或錯的內容而出現 bug。
3. 資料型態轉換(text -> string > int)。
4. 跳出視窗的方法。


##ReadMore##

Step 1. 先編輯 activity_main.xml ,擺好進入 App 時的介面。

activity_main.xml Code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/keyin"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.gamble.MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="110dp"
        android:text="===== Gamble Start =====\nGuess the number ( 1~100 )" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="34dp"
        android:ems="10"
        android:inputType="number" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="79dp"
        android:onClick="buttonClick1"
        android:text="確定" />

</RelativeLayout>


Step 2. 編輯 strings.xml ,設定 Step1 之介面顯示出來的文字。
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">gamble</string>
    <string name="hello_world"></string>
    <string name="action_settings">Settings</string>

</resources>



tep3. 編輯 MainActivity.java 主程式,開始撰寫遊戲運作內容。
package com.example.gamble;

import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.Random;



public class MainActivity extends ActionBarActivity {
 // Parameter
 boolean gameWin = true;
 int max, min, Ran, gameCount, guessNum;

 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // Handle action bar item clicks here. The action bar will
  // automatically handle clicks on the Home/Up button, so long
  // as you specify a parent activity in AndroidManifest.xml.
  int id = item.getItemId();
  if (id == R.id.action_settings) {
   return true;
  }
  return super.onOptionsItemSelected(item);
 }

 // Create a random number in range min ~ max
 public int randomCreate(int max, int min){
  Random Ran = new Random();
  return (Ran.nextInt(max)+min);
 }

 // Button_Click event
 public void buttonClick1(View view) throws InterruptedException{
  // Initialize setting
  if (gameWin == true) {
   max = 100;  // Random range (Max)
   min = 1;  // Random range (Min)
   Ran = randomCreate(max, min); // Get random number
   gameCount = 0;  // Guess count
   gameWin = false; // Game win flag
  }

  // IO setting
  TextView txtOutput = (TextView) findViewById(R.id.textView1);
  EditText txtInput = (EditText) findViewById(R.id.editText1);
  Button txtButton = (Button) findViewById(R.id.button1);

  // Alert dialog setting
  AlertDialog.Builder endGame = new AlertDialog.Builder(this);
  endGame.setTitle("You've guessed right!\n");
  endGame.setMessage("Random Num. is \""+ Ran  + "\"\nGuess count: " + gameCount);
  endGame.setPositiveButton("Restart", new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int i) {
    // Reload App
    finish();
    startActivity(getIntent());
   }
  });
  endGame.setNegativeButton("Close", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int i) {
       // Close App
       finish();
      }
     });

  if ("".equals(txtInput.getText().toString().trim())) // if not any keyin
   txtOutput.setText("Error Keyin, \nPlease keyin number " + min + " ~ " + max);
  else {
   String keyinStr = txtInput.getText().toString(); // keyinStr = Get editText1's text to string
   int keyinInt = Integer.parseInt(keyinStr);   // keyinInt = keyinStr to integer
   if((keyinInt >= min) && (keyinInt <= max)){
    gameCount += 1;  // count guess number
    // Determine whether the input is equal random or not.
    if (keyinInt == Ran){
     txtOutput.setText("");
     gameWin = true;
     endGame.show();  // Show "Restart" & "Close" button
    }
    else if (keyinInt < Ran) {
     min = keyinInt;
     txtOutput.setText("Guess wrong!\nThe number is " + min + " ~ " + max + " , guess again.");
    }
    else if (keyinInt > Ran) {
     max = keyinInt;
     txtOutput.setText("Guess wrong!\nThe number is " + min + " ~ " + max + " , guess again.");
    }
    else {
     txtOutput.setText("Error");  // Other error
    }
   }
   else
     txtOutput.setText("Keyin Error, \nPlease keyin number " + min + " ~ " + max);
  }
  txtInput.setText(null);  // clear EditText "txtInput"
 }
}

遊戲執行結果: