Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

2 Personen Memory-Spiel mit Bluetooth Kommunikation


Zu Beginn des Spieles bauen die beiden Spieler eine Bluetooth-Verbindung auf. Der erste Computer (Bluetooth Server) wartet in einem blockierenden Zusatnd (Waiting as Server) bis am zweiten Computer (Bluetooth Client) der Bluetooth-Name des Servers eingegeben wurde. Der Client startet das Spiel.
 

Das Spiel besteht aus 8 Kartenpaare. Die Rückseiten der Karten sind grau. Der aktive Spieler kehrt jeweils mit einem Mausklick zwei Karten um. Wenn sie gleich sind, erhält er 1 Punkt und kann noch einmal spielen, sonst kommt der zweite Spieler zu Zug. Wer am Schluss mehr Punkte hat, gewinnt.

Das "Ein-Spieler"-Memory (Benutzer gegen Computer) finden Sie im Menü "Gitter-Games" - "Memory".

 

 

Programmcode:

// BtMemory.java

import javax.swing.JOptionPane;
import ch.aplu.bluetooth.BluetoothPeer;
import ch.aplu.bluetooth.BtPeerListener;
import ch.aplu.jgamegrid.*;
import ch.aplu.util.Monitor;

public class BtMemory extends GameGrid
  implements GGMouseListener, BtPeerListener, GGExitListener
{
  private boolean isReady = true;
  private MemoryCard card1;
  private MemoryCard card2;
  private int pairs;
  private int enemyPairs;
  private BluetoothPeer bp;
  private boolean isMyMove;
  private int[] sit; // Game situation

  public BtMemory()
  {
    super(44115nullnullfalse);
    sit = new int[17];
    sit[0] = -1;
    isMyMove = false;
    MemoryCard[] cards = new MemoryCard[16];
    for (int i = 0; i < 16; i++)
    {
      if (< 8)
        cards[i] = new MemoryCard(i);
      else
        cards[i] = new MemoryCard(- 8);
      cards[i].show(1);
      addActor(cards[i]getRandomEmptyLocation());
      int pos = cards[i].getY() * 4 + cards[i].getX();
      sit[pos + 1] = cards[i].getId();
    }
    show();
    doRun();
    connect();
    addExitListener(this);
    addMouseListener(this, GGMouse.lPress);
    // Application thread used to flip back cards
    while (true)
    {
      Monitor.putSleep()// Wait until there is something to do
      delay(1000);
      card1.show(1)// Flip cards back
      card2.show(1);
      isReady = true;
      setMouseEnabled(true)// Rearm mouse events
    }
  }

  private void makeSit(int[] sit)
  {
    removeAllActors();
    for (int y = 0; y < 4; y++)
    {
      for (int x = 0; x < 4; x++)
      {
        int id = sit[+ (* 4) + 1];
        MemoryCard card = new MemoryCard(id);
        card.show(1);
        addActor(card, new Location(x, y));
      }
    }
  }

  public boolean mouseEvent(GGMouse mouse)
  {
    Location location = toLocation(mouse.getX(), mouse.getY());
    MemoryCard card = (MemoryCard)getOneActorAt(location);
    if (card.getIdVisible() == 0 || !isMyMove) // Card already flipped or
      // not my turn ->no action
      return true;
    card.show(0)// Show picture
    int[] data = new int[1];

    if (isReady)
    {
      card1 = card;
      sendCard(-4, card);
      isReady = false;
    }
    else
    {
      card2 = card;
      if (card1.getId() == card2.getId()) // Pair found, let them visible
      {
        sendCard(-2, card);
        bp.sendDataBlock(data);
        pairs++;
        setTitle("Your Points: " + pairs + "  Opponent: " + enemyPairs + "   Play!");
        checkWinLose();
        isReady = true;
      }
      else
      {
        isMyMove = false;
        sendCard(-3, card);
        bp.sendDataBlock(data);
        setTitle("Your Points: " + pairs + "  Opponent: " + enemyPairs + "   Wait!");
        setMouseEnabled(false)// Disable mouse events until
        // application thread flipped back cards
        Monitor.wakeUp();
      }
    }
    return true;
  }

  private void sendCard(int state, Actor card)
  {
    int[] data = new int[3];
    data[0] = state;
    data[1] = card.getX();
    data[2] = card.getY();
    bp.sendDataBlock(data);
  }

  private void checkWinLose()
  {
    if (pairs + enemyPairs == 8)
    {
      if (pairs == enemyPairs)
        setTitle("Tie!");
      if (pairs > enemyPairs)
        setTitle("You win!");
      else
        setTitle("You lose!");
    }
  }

  public void connect()
  {
    String serverName;
    String prompt = "Enter Bluetooth Name";
    do
    {
      serverName = JOptionPane.showInputDialog(null, prompt, "");
      if (serverName == null)
        System.exit(0);
    }
    while (serverName.trim().length() == 0);

    setTitle("Connecting to " + serverName);
    bp = new BluetoothPeer(serverName, "GGmemory"thistrue);
    if (bp.isConnected())
    {
      setTitle("Client connected, it is you to play");
      bp.sendDataBlock(sit);
      isMyMove = true// Client has first move
    }
    else
      setTitle("Waiting as server");
  }

  public void notifyConnection(boolean connected)
  {
    System.out.println("Notify " + (connected ? "connected" : "connection lost"));
    if (connected)
    {
      setTitle("Server connected, wait to play");
    }
  }

  public void receiveDataBlock(int[] data)
  {
    switch (data[0])
    {
      case -1:
        makeSit(data);
        break;
      case -2:
        enemyPairs++;
        card1 = (MemoryCard)getOneActorAt(new Location(data[1], data[2]));
        card1.show(0);
        setTitle("Your Points: " + pairs + "  Opponent: " + enemyPairs + "  Wait!");
        checkWinLose();
        break;
      case -3:
        card2 = (MemoryCard)getOneActorAt(new Location(data[1], data[2]));
        card2.show(0);
        setMouseEnabled(false)// Disable mouse events until
        // application thread flipped back cards
        Monitor.wakeUp();
        isMyMove = true;
        setTitle("Your Points: " + pairs + "   Opponent: " + enemyPairs + "   Play!");
        break;
      case -4:
        System.out.println("received card info >.<");
        card1 = (MemoryCard)getOneActorAt(new Location(data[1], data[2]));
        card1.show(0);
        refresh();
        break;
    }
  }

  public boolean notifyExit()
  {
    bp.releaseConnection();
    return true;
  }

  public static void main(String[] args)
  {
    new BtMemory();
  }
}

//----------------class Memorycard ----------------
class MemoryCard extends Actor
{
  private int id;

  public MemoryCard(int id)
  {
    super("sprites/card" + id + ".gif""sprites/cardback.gif");
    this.id = id;
  }

  public int getId()
  {
    return id;
  }
}


Erklärungen zum Programmcode:

int[] sit Im Array sit[] wird die Spielsituation gespeichert, damit sie dem Bluetooth-Partner übergeben werden kann. Die erste Stelle des Arrays sit[0] hat den Wert -1 und kennzeichnet das verschickte Paket als Spielsituation. Die Id der ersten Karte (oben links) wird als a[1], ... die Ide der letzten Karte als a[16] gespeichert
makeSit(int[] sit) Stellt nach jeder Datenübergabe die aktuelle Spielsituation dar. In jeder Gitterzelle wird eine Karte mit Id gemäss dem Wert von sit[i]

void sendCard(int state, Actor card)
data[0] = state
data[1] = card.getX()
data[2] = card.getY()

Bei jeder Spieler-Aktion werden die Koordinaten der umgedrehten Karte und ihr Status verschickt
void receiveDataBlock(int[] data)

Empfang der Daten: Wir müssen vier verschiedene Fälle unterscheiden, die aus dem ersten Wert data[0] ersichtlich sind:
-1: Der übergebene Array ist die Spielsituation, die mit der Methode makeSit() erzeugt wird
-2: Der Gegner hat einen Punkt gemacht. Die zweite Karte des Paares wurde aufgedeckt. Der Titel wird aktualisiert und es wird überprüft, ob das Spiel zu Ende ist
-3: Der Gegner hat zwei ungleichen Karten aufgedeckt. Sie werde wird zugedeckt, der Titel aktualisiert
-4: Es werden die Daten der ersten Karte des Gegner-Zuges übergeben und die entsprechende Karte aufgedeckt