|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Feb 2008
Città: PoggibonZi
Messaggi: 140
|
[Java] Gioco memory
Ciao a tutti, vorrei farvi un paio di domande riguardo a unìapplicazione che sto cercando di sviluppare: il gioco del memory (quello con le carte girate a faccia in giù dove bisogna indovinare le coppie uguali).
Allora, per il mio giochetto ho creato un JPanel con layout GridLayout 6x6, una classe Carta che estende JButton e che ha come varaible un numero intero da 1 a 18(essendo le carte 36), e con un ciclo aggiungo tutte le 36 carte al gridlayout. L'intenzione è quella di aggiungere un actionlistener a ogni jbutton, e poi controllare se il numero della carta fonte dell'evento del primo listener è uguale a quello della seconda. In questo caso vuol dire che ho fatto una coppia. Il problema è che non so dove effettuare questo confronto, o come ridefinire il metodo actionPerformed per fare in modo che mi restituisca il valore intero della carta fonte dell'evento... Un aiuto sarebbe molto gradito, non so che pesci prendere...grazie in anticipo a chi si degnerà di rispondermi
__________________
Ho felicemente trattato con: Isomarcus, NLDomy, cipacci. Intel e2180 @ 3.1Ghz + Arctic Cooling Freezer 7 ~ MSI P35 Neo2-FR ~ Geil Black Dragon @ 970Mhz 4-4-4-12 ~ ASUS 8800GT 512Mb ~ OCZ StealthXtream 500W |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Potresti pensare a una classe GameLogic, a cui redirigere alcune informazioni che prederai nel corpo del metodo actionPerformed del tuo Listener (sarebbe meglio creare un solo ActionListener da associare a tutte le Carte-bottone).
Quando viene fatto click su una carta, il Listener la passa a GameLogic (nel metodo actionPerformed ottieni il riferimento all'istanza della Carta-bottone cliccata invocando il metodo 'getSource' sull'argomento ActionEvent, e promuovendolo (cast) al tipo di riferimento Carta-bottone). GameLogic controlla se ha già letto o no la prima carta. Se non l'ha già letta memorizza il riferimento passato dal Listener come prima Carta e stop. Altrimenti confronta il valore della prima Carta memorizzata con quello della Carta attuale passata dal Listener: - se sono uguali elimina le due carte; - se non sono uguali le "rigira". - in ogni caso, resetta il riferimento alla prima carta. Può andare bene come idea di massima?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 12-07-2010 alle 11:06. Motivo: l'italiano... |
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Feb 2008
Città: PoggibonZi
Messaggi: 140
|
Ciao, ti ringrazio della risposta, e ti confesso che ho preso un bello spunto dal sorgente di un altro utente di questo forum, in un thread di un paio di anni fa (che implementa un listener che fa proprio come dici tu).
Con qualche ritocco adesso va tutto a meraviglia, apparte il fatto che non mi mostra l'icona della seconda carta quando la giro a faccia in su, a meno che non faccia coppia....se faccio coppia seconda.uncover() mi mostra l'immagine jpg della seconda carta scoperta, altrimenti il metodo uncover() viene comunque chiamato, ma non mostra l'icona.... Allego le classi Carta e MemoryListener, così magari ci puoi dare un'occhiata... Codice:
import javax.swing.*;
import java.awt.*;
class Carta extends JButton
{
private int num;
Carta(int n)
{
super(new ImageIcon("retro.jpg"));
num = n;
}
void uncover()
{
setIcon(new ImageIcon(num+".jpg"));
System.out.println("Uncover"); // messo per vedere se eseguiva il metodo sulla seconda carta
}
void cover()
{
setIcon(new ImageIcon("retro.jpg"));
}
int getNum()
{
return num;
}
}
Codice:
import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import java.awt.event.*;
class MemoryListener implements ActionListener
{
private int giocatoreAttivo = 0;
private Carta prima = null;
private Carta seconda = null;
private int coppie = 0;
public MemoryListener()
{
super();
}
public void actionPerformed(ActionEvent e)
{
switch (giocatoreAttivo)
{
case 0:
{
Carta mem2 = (Carta) e.getSource();
if (prima == null) //1
{
prima = mem2;
mem2.uncover();
System.out.println("prima= "+prima.getNum());
}
else //1
if (seconda == null) //2
{
seconda = mem2;
seconda.uncover();
//MyMemory.aspetta();
System.out.println("seconda= "+seconda.getNum());
if (prima.getNum()==(seconda.getNum())) //3
{
prima.setBackground(Color.GREEN);
seconda.setBackground(Color.GREEN);
prima = null;
seconda = null;
coppie++;
//mem2.removeActionListener(this);
if (coppie == 18) //4
{
JOptionPane.showMessageDialog(null,"Hai trovato tutte le coppie.\nVittoria!", "Gioco terminato",JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
else //3
{
//seconda.uncover();
MyMemory.aspetta();
prima.cover();
seconda.cover();
prima=null;
seconda=null;
giocatoreAttivo = 1;
System.out.println("Non hai indovinato, clicca per far giocare la CPU");
break;
}
}
else //2
{
}
break;
}
case 1:
{
System.out.println("Turno CPU");
giocatoreAttivo=0;
break;
}
}
}
}
__________________
Ho felicemente trattato con: Isomarcus, NLDomy, cipacci. Intel e2180 @ 3.1Ghz + Arctic Cooling Freezer 7 ~ MSI P35 Neo2-FR ~ Geil Black Dragon @ 970Mhz 4-4-4-12 ~ ASUS 8800GT 512Mb ~ OCZ StealthXtream 500W |
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Feb 2008
Città: PoggibonZi
Messaggi: 140
|
Riuppo, anche per dire che il metodo uncover() non funziona neanche quando lo chiamo sulle carte che gira il giocatore cpu....
Questo è il metodo in questione, appartenente alla classe Carta che estende JButton, che trovate per intero nel post precedente... Codice:
void uncover()
{
setIcon(new ImageIcon(num+".jpg"));
}
Codice:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import java.util.*;
import java.util.ArrayList;
public class MyMemory extends JFrame implements ActionListener
{
public Container panel;
MemoryListener mem1 = new MemoryListener();
public static ArrayList<Carta> arraylist = new ArrayList<Carta>();
public MyMemory()
{
this.panel = this.getContentPane();
panel.setLayout(new BorderLayout());
setTitle("Memory");
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menuBar.add(menu);
JMenu submenu = new JMenu("Gioca una partita");
JMenuItem facile = new JMenuItem("Livello facile");
submenu.add(facile);
facile.addActionListener(this);
JMenuItem difficile = new JMenuItem("Livello difficile");
submenu.add(difficile);
difficile.addActionListener(this);
menu.add(submenu);
JMenuItem esci = new JMenuItem("Esci");
menu.add(esci);
esci.addActionListener(this);
panel.add(menuBar, BorderLayout.NORTH);
setSize(870, 950);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private int[] labels = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 1, 2,
3, 4, 5, 6, 7, 8, 9,10,11,12, 13, 14,
15, 16, 17, 18 };
private int lung = labels.length;
private int randomLabel()
{
int random = (int) (Math.random()*100);
int ran = (int) random % lung;
int ran1 = labels[ran];
for (int i = ran + 1; i < lung; i++)
{
labels[i - 1] = labels[i];
}
lung--;
return ran1;
}
public void costruisci()
{
JPanel cartePanel = new JPanel();
cartePanel.setLayout(new GridLayout(6,6,3,3));
for (int i = 0; i < 36; i++)
{
Carta c = new Carta(this.randomLabel());
cartePanel.add(c);
arraylist.add(i,c);
c.addActionListener(mem1);
panel.add(cartePanel, BorderLayout.CENTER);
setVisible(true);
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("Livello facile"))
{
costruisci();
System.out.println("FAcileeeeeeeeeee");
}
else if (e.getActionCommand().equals("Livello difficile"))
{
costruisci();
System.out.println("Difficileeeeeeeeeee");
}
else System.exit(0);
}
public static void aspetta()
{
long t0,t1;
t0=System.currentTimeMillis();
do{
t1=System.currentTimeMillis();
}
while (t1-t0<1000);
}
public static void main(String[] args) throws Exception
{
MyMemory m = new MyMemory();
}
}
Sto affogando in un bicchier d'acqua?
__________________
Ho felicemente trattato con: Isomarcus, NLDomy, cipacci. Intel e2180 @ 3.1Ghz + Arctic Cooling Freezer 7 ~ MSI P35 Neo2-FR ~ Geil Black Dragon @ 970Mhz 4-4-4-12 ~ ASUS 8800GT 512Mb ~ OCZ StealthXtream 500W Ultima modifica di m0linas : 13-07-2010 alle 16:05. Motivo: Avevo scritto tutto dentro il code... |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Ciao, ho realizzato un piccolo esempio sulla base dei suggerimenti che ti ho dato poco sopra (ignora il fatto che la finestra e' trasparente, stavo provando io una cosa):
![]() Ti posto le classi relative (circa il tuo problema prova a guardare come sono gestite le cose nell'implementazione dell'ActionListener che è collegato a ciascuna carta-bottone. C'è una questione relativa all'uso dei thread e al fatto che Swing è single-threaded). Game.java Codice:
package banryu79.mymemory;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
/**
*
* @author francesco
*/
public class Game
{
public static void main(String[] argv) {
// Load images for all cards
CardStore store = new CardStore();
store.load();
// build interface
final JFrame FRAME = new JFrame("MyMemory");
FRAME.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// buld moves counter:
GuessCounter guessCounter = new GuessCounter();
FRAME.add(guessCounter, BorderLayout.NORTH);
// build CardListener
CardListener cardLogic = new CardListener(FRAME);
cardLogic.bindToGuessCounter(guessCounter);
// build game field:
JPanel gameField = new JPanel(new GridLayout(0, 4));
List<CardButton> deck = store.getNewDeck();
for (CardButton card : deck) {
card.addActionListener(cardLogic);
Box b = Box.createHorizontalBox();
b.add(Box.createHorizontalGlue());
b.add(card);
b.add(Box.createHorizontalGlue());
gameField.add(b);
}
FRAME.add(gameField, BorderLayout.CENTER);
// show UI!
SwingUtilities.invokeLater(new Runnable() {
public void run() {
FRAME.pack();
FRAME.setLocationRelativeTo(null);
FRAME.setVisible(true);
}
});
for (CardButton card : deck)
System.out.println(card);
}
static class CardListener implements ActionListener
{
JFrame parent;
GuessCounter counter;
CardButton firstCard;
boolean freeForEvents;
final int PAUSE;
CardListener(JFrame parent) {
this.parent = parent;
freeForEvents = true;
PAUSE = 1200;
}
public void actionPerformed(ActionEvent e) {
if (freeForEvents) {
freeForEvents = false;
CardButton card = (CardButton) e.getSource();
if (isChosingFirstCard()) {
firstCardChosen(card);
}
else {
if (isChosingSecondCard(card))
secondCardChosen(card);
else
rechosingFirstCard();
}
}
}
boolean isChosingFirstCard() {
return firstCard == null;
}
boolean isChosingSecondCard(CardButton card) {
return !card.isShowingFrontCover();
}
// Giro la carta e stop.
void firstCardChosen(CardButton card) {
System.out.println("First card chosen: "+ card);
card.swapIcons();
firstCard = card;
freeForEvents = true;
}
// Non faccio nulla, a parte resettare il flag degli eventi
void rechosingFirstCard() {
System.out.println("First rechosed.");
freeForEvents = true;
}
void secondCardChosen(CardButton card) {
counter.incrementGuessAttempt();
if (card.equals(firstCard))
succesfullMatch(card);
else
failedMatch(card);
}
// Giro la carta, mostro JOptionPane, disabilito le due carte e stop.
void succesfullMatch(CardButton card) {
System.out.println("Second card chosen: they match!");
counter.incrementMatch();
card.swapIcons();
JOptionPane.showMessageDialog(parent, "Hai indovinato!");
firstCard.resetIcon();
firstCard.setEnabled(false);
card.resetIcon();
card.setEnabled(false);
parent.repaint();
firstCard = null;
freeForEvents = true;
}
// se non matcha, giro la carta, aspetto un po', e rigiro entrambe le carte.
void failedMatch(final CardButton card) {
System.out.println("Second card chosen: mismatch.");
counter.incrementError();
card.swapIcons();
// launch UI updating task in worker thread, after the pause.
SwingWorker<Void, Void> failedMatchUpdater = new SwingWorker<Void, Void>() {
@Override protected Void doInBackground() throws Exception {
try {
Thread.sleep(PAUSE);
} catch (InterruptedException ignored) {}
return null;
}
@Override protected void done() {
firstCard.swapIcons();
card.swapIcons();
firstCard = null;
freeForEvents = true;
}
};
failedMatchUpdater.execute();
}
private void bindToGuessCounter(GuessCounter guessCounter) {
counter = guessCounter;
}
}
static class GuessCounter extends JPanel
{
final Box BOX;
final JLabel LB_TENTATIVI;
final JLabel LB_ERRORI;
final JLabel LB_MATCH;
int numTentativi = 0;
int numErrori = 0;
int numMatch = 0;
GuessCounter() {
setLayout(new FlowLayout(FlowLayout.LEFT));
LB_TENTATIVI = new JLabel("0");
LB_ERRORI = new JLabel("0");
LB_MATCH = new JLabel("0");
BOX = Box.createHorizontalBox();
BOX.add(Box.createHorizontalStrut(15));
BOX.add(new JLabel("Tentativi eseguiti: "));
BOX.add(LB_TENTATIVI);
BOX.add(Box.createHorizontalStrut(50));
BOX.add(new JLabel("Match: "));
BOX.add(LB_MATCH);
BOX.add(Box.createHorizontalStrut(15));
BOX.add(new JLabel("Errori: "));
BOX.add(LB_ERRORI);
BOX.add(Box.createHorizontalGlue());
add(BOX);
}
void incrementGuessAttempt() {
numTentativi++;
LB_TENTATIVI.setText(String.valueOf(numTentativi));
}
void incrementError() {
numErrori++;
LB_ERRORI.setText(String.valueOf(numErrori));
}
void incrementMatch() {
numMatch++;
LB_MATCH.setText(String.valueOf(numMatch));
}
}
}
CardStore.java Codice:
package banryu79.mymemory;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import static java.lang.Math.random;
/**
* A simple collections of loaded images to use for Cards.
* @author francesco
*/
public class CardStore
{
public static final int DECK_SIZE = 12;
private final String IMAGES_PATH = "/banryu79/mymemory/images/";
private final String IMAGES_FRONT_NAME = "cardfront";
private final String IMAGE_RETRO_NAME = "cardback.jpg";
private Map<Integer, Icon> cards;
public CardStore() {
cards = new HashMap();
}
/**
* Load the deck from disk
*/
public void load() {
// Load "back-cover" image
int index = 0;
storeInMap(index, IMAGES_PATH+IMAGE_RETRO_NAME);
// Load "front-cover" images
index = 1;
String path = IMAGES_PATH + IMAGES_FRONT_NAME;
while (index <= DECK_SIZE) {
storeInMap(index, path+index+".jpg");
index++;
}
}
public List<CardButton> getNewDeck() {
// choose only DECK_SIZE/2 random unique images:
final int NUM = DECK_SIZE/2;
Set<Icon> chosen = new HashSet<Icon>(NUM);
while (chosen.size() != NUM) {
int index = (int) (random() * DECK_SIZE) + 1;
chosen.add(cards.get(index));
}
List<CardButton> deck =
new ArrayList<CardButton>(DECK_SIZE);
Icon backCover = cards.get(0);
for (Icon frontCover : chosen) {
CardButton card1 = new CardButton(frontCover, backCover);
CardButton card2 = new CardButton(frontCover, backCover);
deck.add(card1);
deck.add(card2);
}
Collections.shuffle(deck);
return deck;
}
private void storeInMap(int index, String imagePath) {
System.out.println("loading "+imagePath);
URL imgURL = getClass().getResource(imagePath);
if (imgURL == null)
throw new RuntimeException("Cannot find: "+imagePath);
ImageIcon icon = new ImageIcon(imgURL);
cards.put(index, icon);
}
public Map<Integer, Icon> getAll() {
return cards;
}
}
CardButton.java Codice:
package banryu79.mymemory;
import java.awt.Insets;
import javax.swing.Icon;
import javax.swing.JButton;
/**
* Basic Memory CardButton, implemented as a JButton.
* it has a common back-cover, and a specific front-cover, ad a unique identity.
*
* @author francesco
*/
public class CardButton extends JButton
{
private static final Insets NO_MARGINS = new Insets(0,0,0,0);
private Icon frontCover;
private Icon backCover;
private boolean showingFrontCover;
public CardButton(Icon front, Icon back) {
if (front == null)
throw new IllegalArgumentException("Front cover icon cannot be null.");
if (back == null)
throw new IllegalArgumentException("Back cover icon cannot be null.");
super.setMargin(NO_MARGINS);
super.setIcon(back);
showingFrontCover = false;
frontCover = front;
backCover = back;
}
/**
* Called by the EDT
*/
public void swapIcons() {
if (showingFrontCover) {
setIcon(backCover);
showingFrontCover = false;
}
else {
setIcon(frontCover);
showingFrontCover = true;
}
}
public boolean isShowingFrontCover() {
return showingFrontCover;
}
public void resetIcon() {
setIcon(null);
}
@Override
public boolean equals(Object o) {
if (o instanceof CardButton) {
CardButton other = (CardButton) o;
return backCover == other.backCover &&
frontCover == other.frontCover;
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 53 * hash + (frontCover != null ? frontCover.hashCode() : 0);
hash = 53 * hash + (backCover != null ? backCover.hashCode() : 0);
return hash;
}
@Override
public String toString() {
return "CardButton_" + (frontCover.hashCode()+backCover.hashCode()/1000);
}
}
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 14-07-2010 alle 13:46. Motivo: corretto un bug, evidenziato codice interessante |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 05:23.




















