我正在为我的班级制作一个项目。这就像鼹鼠游戏。我有9个imageView。当你点击它们时,它们会变成一个空洞的预定义图像,如果没有,处理程序会将它改回正常,你将失去生命。但是对于一张照片,如果它出现并且你点击它,你就会失去生命。现在我已将图像修复为后者。如果我非常快地点击它们,显示生命的textView,永远不会更新到游戏结束,任务继续,但如果我慢慢点击,它会更新到游戏结束。我试过调试,发现当我很快点击它们时,代码永远不会转到onClick监听器。
以下是代码:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import Hole;
public class MainActivity extends Activity {
final Activity mainActivityObject = this;
final int MIN_TYPES_OF_MOLES = 0;
final int TYPES_OF_MOLES_INC_INT = 1;
final int MAX_MOLE_LIFE_TIME = 3000;
final int LIFE_TIME_DECREASE_INT = 150;
final int MAX_MOLE_APPEARANCE_INT = 1000;
final int APPEARANCE_TIME_DECREASE_INT = 60;
final int SPEED_UP_TIME_INT = 20000;
final int BOMB_MOLE_ID = 3;
final int MIN_DIFFICULTY_LEVEL = 1;
private Toast toast;
final Handler handler = new Handler();
Runnable moleAliveChecker;
Runnable speedUp;
TextView lives;
TextView tView;
//private ImageView[] holeImage = new ImageView[9];
private Hole[] hole = new Hole[9];
private int totalScore = 0;
private int active = 0;
private int numberOfLives = 3;
private int appearanceInterval = MAX_MOLE_APPEARANCE_INT;
private int moleLifeTime = MAX_MOLE_LIFE_TIME;
private int typesOfMoles = MIN_TYPES_OF_MOLES;
private int speedUpTime = SPEED_UP_TIME_INT;
private int difficultyLevel = MIN_DIFFICULTY_LEVEL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// hide the title
setContentView(R.layout.activity_main);
tView = (TextView) findViewById(R.id.time_left);
lives = (TextView) findViewById(R.id.lives_left);
toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);
//set images and listener for each hole, ends game if lives < 1
for(int counter=0;counter<9;counter++)
{
int resID=getResources().getIdentifier("hole"+(counter+1),"id",getPackageName());
hole[counter] = new Hole((ImageView)findViewById(resID), this);
final int i=counter;//inside the onClickListener, index number has to be final
hole[counter].getImage().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ImageView image = hole[i].getImage();
switch ((Integer) image.getTag()) {
case R.drawable.hole:
break;
default:
if (numberOfLives < 1) {
handler.removeCallbacks(speedUp);
lives.setText("GAME OVER!!");
}
else if (hole[i].getMole().ishit()) {
changeScoreAndLives(hole[i], i);
}
break;
}
}
});
}
// gives a time delay of 3 seconds before beginning the game and updates text view
// tView every 1 second and when time approaches 0, it starts the game
final Runnable r = new Runnable() {
int t = 3;
public void run() {
if (t > 0) {
tView.setText("Game begins in : " + t-- + " Seconds");
handler.postDelayed(this, 1000);
}
else if (t == 0)
{
t--;
tView.setText("Begin!!");
handler.postDelayed(this, 300);
}
else
{
if (numberOfLives >= 1) {
playGame();
handler.postDelayed(this, appearanceInterval);
}
}
}
};
handler.postDelayed(r, 1000);
// speeds up the game after a set interval (20 seconds)
speedUp = new Runnable() {
public void run() {
appearanceInterval -= APPEARANCE_TIME_DECREASE_INT;
moleLifeTime -= LIFE_TIME_DECREASE_INT;
typesOfMoles += TYPES_OF_MOLES_INC_INT;
difficultyLevel++;
if (difficultyLevel < 6 && numberOfLives >= 1) {
handler.postDelayed(this, speedUpTime);
}
toast.setText("Difficulty Level increased");
toast.show();
}
};
handler.postDelayed(speedUp, speedUpTime);
}
// end of onCreate
// not been used yet
private void resetOneStep()
{
if (difficultyLevel > MIN_DIFFICULTY_LEVEL) {
appearanceInterval += MAX_MOLE_APPEARANCE_INT;
moleLifeTime += MAX_MOLE_LIFE_TIME;
typesOfMoles -= MIN_TYPES_OF_MOLES;
difficultyLevel--;
handler.postDelayed(speedUp, speedUpTime);
}
}
// not related to the current problem as currently not being used
public void bombMoleCredit()
{
for (int count = 0; count < hole.length; count++)
if (hole[count].getMole() !=null) {
totalScore += hole[count].getMole().getPoints();
handler.removeCallbacksAndMessages(count);
hole[count].setImage(null, mainActivityObject);
}
tView.setText("Total Score: " + totalScore);
active = 0;
}
// called by onclick listener if lives > 0 to change lives, score, and image
public void changeScoreAndLives(Hole hole, int number)
{
totalScore = totalScore + hole.getMole().getPoints();
if (hole.getMole().getPoints() < 0) {
numberOfLives--;
lives.setText("Lives Left: " + numberOfLives);
}
if (hole.getMole().getID() == BOMB_MOLE_ID) {
bombMoleCredit();
return;
}
handler.removeCallbacksAndMessages(number);
hole.setImage(null, mainActivityObject);
active--;
tView.setText("Total Score: " + totalScore);
}
// called by runnable after a set interval
public void playGame()
{
if (active == 9)
return;
final int holeNumber = (int) (Math.random() * hole.length);
if (hole[holeNumber].getMole() == null && numberOfLives >= 1) {
hole[holeNumber].setMoleFromRange(4, 4, this);
active++;
// checks if the hole has been clicked or not after a few seconds, if not, player
// looses a life
moleAliveChecker = new Runnable() {
Hole holeToBeChecked = hole[holeNumber];
public void run() {
if (holeToBeChecked.getMole() != null && numberOfLives >= 1) {
if(holeToBeChecked.getMole().getID() == 4) {
holeToBeChecked.setImage(null, mainActivityObject);
active--;
return;
}
holeToBeChecked.setImage(null, mainActivityObject);
numberOfLives--;
active--;
TextView lives = (TextView) findViewById(R.id.lives_left);
lives.setText("Lives Left: " + numberOfLives);
toast.setText("OOPS!! you lost a life. Game Reset");
toast.show();
//resetOneStep();
}
}
};
handler.sendMessageDelayed(getPostMessage(moleAliveChecker, holeNumber), moleLifeTime);
}
else
playGame(); // in case the random number choses the image which has the mole
}
// to pass object as a token in postDelayed in handler, to cancel the callbacks
private final Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain(handler, r);
m.obj = token;
return m;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
除了这个之外,所有其他课程都正常。
其他重要课程: 的 Mole.java
import android.app.Activity;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.InputStream;
public class Mole
{
public static final int DEFAULT_ID = 0; // regular mole ID
// private methods
private JSONParser parser;
private JSONObject mole;
private int ID, timesToBeHit, timesHit, points;
private String name;
private JSONArray moles;
private boolean active;
public Mole(int ID, Activity map)
{
try {
// initialize and read json and convert each object to jsonArray
parser = new JSONParser();
// tries to set the value set by user. If fails, sets the default value
if (!setMoleByID(ID, map))
setMoleByID(DEFAULT_ID, map);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// helper for constructor
private boolean setMoleByID(int ID, Activity map) throws Exception
{
InputStream is = map.getAssets().open("moles.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String json = new String(buffer, "UTF-8");
moles = (JSONArray)parser.parse(json);
// go through each object in array moles
for ( Object obj : moles)
{
// convert oobject to jsonObject
mole = (JSONObject) obj;
// if id matches it leaves the mole to be that jsonObject and exits
// the loop
if ((long)mole.get("ID") == ID)
break;
}
if ((long)mole.get("ID") != ID)
return false;
// initialize private data so that we don't have to rely on json
// anymore after this step
this.ID = (int)(long)mole.get("ID");
name = (String)mole.get("name");
timesToBeHit = (int)(long)mole.get("timesToBeHit");
timesHit = 0;
points = (int)(long)mole.get("points");
return true;
}
// get methods
public int getID() { return ID; }
public String getName() { return name; }
public int getTimesHit() { return timesHit; }
public int getTimesToBeHit() { return timesToBeHit; }
public int getPoints() { return points; }
public boolean ishit()
{
if (timesHit >= timesToBeHit - 1)
return true;
timesHit++;
return false;
}
public static int getTotalTypesOfMoles() throws Exception
{
return 5;
}
}
Hole.java
import android.app.Activity;
import android.widget.ImageView;
import com.example.phoenix.whac_a_mole03.R;
// NOT completed yet
// HOLE Class -----------------------------------------------------------------
public class Hole
{
private Mole mole;
private boolean active; // if true then mole is present
private ImageView image;
public Hole(ImageView view,final Activity map)
{
mole = null;
image = view;
setImage(mole, map);
}
// sets mole from a random value
public boolean setMoleFromRange(int minMoleID,
int maxMoleID, Activity map)
{
try {
int typesOfMoles = Mole.getTotalTypesOfMoles() - 1;
// checks for validity of data here
if (!(minMoleID >= 0 & minMoleID <= typesOfMoles))
return false;
if (!(maxMoleID >= 0 & maxMoleID <= typesOfMoles))
return false;
if (minMoleID > maxMoleID)
return false;
// chooses the random value between a range
int moleID =
(int) (Math.random() * (maxMoleID + 1 - minMoleID)) + minMoleID;
mole = new Mole(moleID, map);
setImage(mole, map);
return true;
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
private void clear()
{
mole = null;
}
public void setImage(Mole mole, Activity map)
{
if (mole == null) {
image.setImageResource(R.drawable.hole);
image.setTag(R.drawable.hole);
clear();
return;
}
int imageID = map.getResources().getIdentifier("mole" + mole.getID() , "drawable", map.getPackageName());
image.setImageResource(imageID);
image.setTag(imageID);
this.mole = mole;
}
public boolean hit(Activity map)
{
if (!mole.ishit())
return false;
setImage(mole, map);
return true;
}
// get methods
public Mole getMole() { return mole; }
public ImageView getImage() { return image;}
// REST STUFF TO BE ADDED HERE-------------
}
activity_main.xml中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="@+id/time_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/lives_left"
android:layout_alignParentRight="true"
android:text="Lives Left: 3"
android:textAlignment="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<GridLayout
android:columnCount="3"
android:rowCount="3"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/hole1"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole2"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole3"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole4"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole5"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole6"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole7"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole8"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="@+id/hole9"
android:src="@drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
</GridLayout>
<GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/life1"/>
<ImageView
android:id="@+id/life2"/>
<ImageView
android:id="@+id/life3"/>
</GridLayout>
</RelativeLayout>
任何图片都可以使用,只要它名为mole4.png,当没有mmole时就可以使用hole.png
非常感谢。我将非常感谢您的帮助