(Memoryspiel) dynamischen ImageButton in onClick ändern

  • 3 Antworten
  • Letztes Antwortdatum
S

Schwarz1603

Neues Mitglied
0
Hallo,

ich möchte ein Memoryspiel implementieren.

Funktioniert soweit auch alles ganz gut, Karten in Form von Imagebuttons werden mit einheitlichem "Rückseitenbild" versehen, welches in der onClick Methode des OnClickListeners mit den eigentlichen Bildern versehen wird, welche über eine switch Anweisung vergeben werden.

Die erste Karte wird problemlos geändert.
Bei der Auswahl der zweiten Karte wird innerhalb der onClick Methode ebenfalls geprüft, ob die Karten übereinstimmen. Falls ja, werden die Karten unsichtbar. Falls nein, wird das Rückseitenbild wieder gesetzt, so kriegt der User also nie das Bild der zweiten Karte zu sehen.

Wie kann man dass ändern, ohne dass ich erstmal die onClick Methode zweimal komplett ohne Prüfung durchlaufen lasse?

Wenn ich die Prüfung aus der onClick Methode auslagere, müsste der User einen dritten Button drücken.

Nach acht Stunden muss ich doch mal nachfragen, ob jemand eine Idee hat.

Die onTouch Methode am Ende ist noch ein Überbleibsel von meinen Versuchen, dieses Problem zu lösen.

Betroffener Code-Teil:

Code:
if (firstCard == null) {
	 firstCard = (ImageButton) v;
	 chooseCardimage(firstCard);

 } else {

         secondCard = (ImageButton) v;			
 	 chooseCardimage(secondCard);
	 num_tries++;
	   }

	checkCards();


		// for (int i = 0; i < cards.size(); i++)
		// if (!cards.get(i).isShown()) {
		if (cardcount >= num_cards) {
                Intent intent = new Intent(this, SqliteActivity.class); // create an	 Intent
		Bundle bundle = new Bundle();
		bundle.putInt("tries", num_tries);
		intent.putExtras(bundle);
		startActivity(intent); // start activity
		this.finish(); // close activity
		}
	}

private void checkCards() {
		((TextView) findViewById(R.id.tv1)).setText("Versuche: " + num_tries);
		if (secondCard != null) {
			if (firstCard.getId() == secondCard.getId()
					&& !checksamecards(firstCard, secondCard)) {
				try {
					Thread.sleep(800);
				} catch (InterruptedException e) {
					Log.i("InterruptedException e: ", e.toString());
				}

				firstCard.setVisibility(View.INVISIBLE);
				secondCard.setVisibility(View.INVISIBLE);
				cardcount++;
			} else {
				if (firstCard.getId() != secondCard.getId()
						&& !checksamecards(firstCard, secondCard)) {
					try {
						Thread.sleep(800);
					} catch (InterruptedException e) {
						Log.i("InterruptedException e: ", e.toString());
					}

					firstCard.setImageResource(R.drawable.backimage);
					secondCard.setImageResource(R.drawable.backimage);

				}
				firstCard = null;
				secondCard = null;

			}
		}
	}

Der ganze Code:

Code:
package com.VS.memorycardgame;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener,
		OnTouchListener {

	private int num_rows;
	private int num_tries;
	private int num_cards;
	private Context context;
	private ArrayList<ImageButton> cards;
	private ArrayList<TableRow> rows;
	private TableLayout tablelayout;
	private ImageButton firstCard;
	private ImageButton secondCard;
	private int cardcount;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		tablelayout = (TableLayout) findViewById(R.id.tableLayout01);
		context = tablelayout.getContext();
		num_cards = 8;
		num_rows = 4;
		num_tries = 0;
		cardcount = 0;
		cards = new ArrayList<ImageButton>();
		rows = new ArrayList<TableRow>();
		newGame();

	}

	@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;
	}

	private void randomize(ArrayList<ImageButton> a) {

		long seed = System.nanoTime();
		Collections.shuffle(a, new Random(seed));
	}

	private void newGame() {

		loadCards();
		loadCards();
		randomize(cards);
		createRows();
	}

	private void createRows() {

		try {
			for (int i = 0; i < num_rows; i++) {
				rows.add((TableRow) findViewById(R.id.class.getField(
						"tableRow" + (i + 1)).getInt(0)));
			}

			createGrid();

		} catch (Exception e) {
			Log.i("Fehler bei Hinzufügen von Rows: ", e.toString());
		}
	}

	private void createGrid() {

		int v = 0;
		int i = 0;
		for (i = i; i < 16; i++) {

			rows.get(v).addView(cards.get(i));

			if (i == 3) {
				v++;
			}
			if (i == 7) {
				v++;
			}
			if (i == 11) {
				v++;
			}
		}
	}

	private void loadCards() {
		try {
			for (int i = 0; i < num_cards; i++) {
				ImageButton button = new ImageButton(context);
				button.setId(100 + i);
				button.setImageResource(R.drawable.backimage);
				button.setOnClickListener(this);
				button.setOnTouchListener(this);
				cards.add(button);
			}

		} catch (Exception e) {
			Log.i("Fehler bei Hinzufügen von Cards: ", e.toString());
		}
	}

	@Override
	public void onClick(View v) {

//		 if (firstCard != null && secondCard != null && firstCard.getId() !=
//		 secondCard.getId()
//		 && !checksamecards(firstCard, secondCard)) {
//		 try {
//		 Thread.sleep(800);
//		 } catch (InterruptedException e) {
//		 Log.i("InterruptedException e: ", e.toString());
//		 }
//		
//		 firstCard.setImageResource(R.drawable.backimage);
//		 secondCard.setImageResource(R.drawable.backimage);
//		 firstCard = null;
//		 secondCard = null;
//		
//		 }
		if (firstCard == null) {
			 firstCard = (ImageButton) v;
			chooseCardimage(firstCard);

		} else {

			secondCard = (ImageButton) v;			
			chooseCardimage(secondCard);
			num_tries++;
		}

		checkCards();

		// for (int i = 0; i < cards.size(); i++)
		// if (!cards.get(i).isShown()) {
		if (cardcount >= num_cards) {
			Intent intent = new Intent(this, SqliteActivity.class); // create an
																	// Intent
			Bundle bundle = new Bundle();
			bundle.putInt("tries", num_tries);
			intent.putExtras(bundle);
			startActivity(intent); // start activity
			this.finish(); // close activity
		}
	}

	private void checkCards() {
		((TextView) findViewById(R.id.tv1)).setText("Versuche: " + num_tries);
		if (secondCard != null) {
			if (firstCard.getId() == secondCard.getId()
					&& !checksamecards(firstCard, secondCard)) {
				try {
					Thread.sleep(800);
				} catch (InterruptedException e) {
					Log.i("InterruptedException e: ", e.toString());
				}

				firstCard.setVisibility(View.INVISIBLE);
				secondCard.setVisibility(View.INVISIBLE);
				cardcount++;
			} else {
				if (firstCard.getId() != secondCard.getId()
						&& !checksamecards(firstCard, secondCard)) {
					try {
						Thread.sleep(800);
					} catch (InterruptedException e) {
						Log.i("InterruptedException e: ", e.toString());
					}

					firstCard.setImageResource(R.drawable.backimage);
					secondCard.setImageResource(R.drawable.backimage);

				}
				firstCard = null;
				secondCard = null;

			}
		}
	}

	private boolean checksamecards(View first, View second) {
		if (first == second) {
			Log.i("Userpressedsame: ", "User pressed same button!");
			return true; // the user pressed the same card
		}
		return false;

	}

	private void chooseCardimage(View v) {
		ImageButton b = (ImageButton) v;
		switch (b.getId()) {
		case 100:
			b.setImageResource(R.drawable.card1);
			break;
		case 101:
			b.setImageResource(R.drawable.card2);
			break;
		case 102:
			b.setImageResource(R.drawable.card3);
			break;
		case 103:
			b.setImageResource(R.drawable.card4);
			break;
		case 104:
			b.setImageResource(R.drawable.card5);
			break;
		case 105:
			b.setImageResource(R.drawable.card6);
			break;
		case 106:
			b.setImageResource(R.drawable.card7);
			break;
		case 107:
			b.setImageResource(R.drawable.card8);
			break;
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		return false;
	}

}

Danke im Voraus.
 
Grundsätzlich ist deine Idee gar nicht so falsch.
Nur würde ich nicht mit Thread.sleep arbeiten.
Stattdessen solltest du einen Timer mit einem TimerTask nutzen.

Timer | Android Developers
TimerTask | Android Developers

Eigentlich recht simple:
du baust deinen TimerTask in der Run methode

machst du einfach das hier:
firstCard.setImageResource(R.drawable.backimage);
secondCard.setImageResource(R.drawable.backimage);
cardsAreOpen = false; //Erklärung siehe unten

musst du aber im UI Thread ausführen (mit runOnUiThread z.B.).
Den Task setzt du dann im mit einem Delay von 800 millisekunden.
und setzt vorher noch
cardsAreOpen = true; //Erklärung unten

Das sollte eigentlich funktionieren.
Evtl musst du dir doch überlegen wie du Eingaben abfängst die in dieser Zeit passieren, im Zweifel durch eine einfache boolean Variable (siehe oben) die davor gesetzt wird und im TimerTask selber wieder resettet wird.
Also direkt am anfang der onClick Methode sowas wie:
if (cardsAreOpen) {
return;
}
Dann führt er weitere Clicks erst aus, wenn die Karten wieder verdeckt sind.
 
Ich glaube du musst deine Logik etwas anders aufziehen.


... huch amfa war schneller ...

Hätte auch auf die Postdelayed Variante verwiesen.

-> Karte wird angeklickt -> ist erste Karte dann ohne Verzögerung weiter

-> zweite Karte wird angeklickt -> Karte anzeigen -> alle ClickListner aus dem Spiel nehmen / disablen (siehe amfas Vorschlag -> mit einer einfachen Boolean Variable)

-> kurze Zeit (1-3 Sekunden verstreichen lassen) handler.postdelayed -> überprüfung ob Karten identisch falls nein -> alle Karten wieder schliessen -> onClickHandler Variable wieder auf Spielbetrieb umschalten und weiter geht es.
 
Vielen Dank für eure Antworten.

Ich habe das Problem inzwischen mit der Handlermethode gelöst und die Thread.sleep Methoden rausgeschmissen.

Der Handler wurde außerhalb der onClick Methode initialisiert in onCreate,

und in der onClick Methode dann mit

Code:
myHandler.postDelayed(mMyRunnable, 1000);

Das Runnable Objekt:

Code:
	private Runnable mMyRunnable = new Runnable() {
		@Override
		public synchronized void run() {
			checkCards();
		}
	};

Den Ratschlag mit den Nutzereingaben werde ich noch berücksichtigen. manchmal tritt noch ein Fehler auf, dass die Bilder offen liegen bleiben.
 
Zuletzt bearbeitet:
Zurück
Oben Unten