Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

Schiffe-Versenken (Battleship)


In diesem Beispiel wird eine vereinfachte Variante des Spiels Schiffe-Versenken vorgestellt, um das Prinzip verständlich zu machen (Im Anschluss daran finden Sie ein vollständiges Programm, in dem mehrere Schiffsarten verwendet werden und zu Beginn die Positionierung der Schiffe durch die Spieler vorgenommen wird).

Bei jedem Spieler werden 10 zufällig positionierte Schiffe erzeugt. Vor dem Beginn des Spieles muss eine Bluetooth-Verbindung aufgebaut werden, wie es in den vorhergehenden Beispielen beschrieben wurde. Nach der erfolgreichen Verbindungsaufnahme versuchen die Spieler abwechslungsweise die Position der Schiffe des Gegners zu erraten. Bei einem Treffer verschwindet das Schiff im gegnerischen Spielfeld und im eigenen Spielfeld wir diese Position mit einem grauen Schiff markiert. Fehlschüsse werden mit einem roten Kreuz markiert.

 

Programmcode:

// BtShipEx1.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import ch.aplu.bluetooth.*;
import javax.swing.JOptionPane;

public class BtShipEx1 extends GameGrid
  implements GGMouseListenerBtPeerListenerGGExitListener
{
  private BluetoothPeer bp;
  private boolean isMyMove;
  private int hits;
  private int enemyHits;
  private final int nbShips = 10;

  public BtShipEx1()
  {
    super(6, 6, 50, Color.red, false);
    getBg().clear();
    init();
    refresh();
    show();
    addMouseListener(thisGGMouse.lClick);
    connect();
    addExitListener(this);
  }

  public void init()
  {
    for (int = 0; i < nbShips; i++)
      addActor(new Ship(), getRandomEmptyLocation());
  }

  public boolean mouseEvent(GGMouse mouse)
  {
    if (!isMyMove)
      return true;
    Location loc = toLocationInGrid(mouse.getX(), mouse.getY());
    addActor(new Actor("sprites/check.gif"), loc);
    int[] data = new int[3];
    data[0] = -1;
    data[1] = loc.x;
    data[2] = loc.y;
    bp.sendDataBlock(data);
    refresh();
    isMyMove = false;
    updateTitle();
    return false;
  }

  private void updateTitle()
  {
    if (hits == nbShips)
      setTitle("You won");
    else
      if(enemyHits == nbShips)
      {
        setTitle("You lost");
        isMyMove = false;
      }
      else
        setTitle("Hits: " + hits + "  /  " + enemyHits + (isMyMove ? "   Play!" : "   Wait!"));
  }

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

    setTitle("Connecting to " + serverName);
    bp = new BluetoothPeer(serverName, "nim"thistrue);
    if (bp.isConnected())
    {
      setTitle("Client connected. Play");
      isMyMove = true// Client has first move
    }
    else
      setTitle("Waiting as server " + BluetoothFinder.getLocalBluetoothName());
  }

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

  public void receiveDataBlock(int[] data)
  {
    int = data[1];
    int = data[2];
    Location loc = new Location(x, y);
    switch (data[0])
    {
      case -1:
        isMyMove = true;
        Actor actor = getOneActorAt(loc, Ship.class);
        if (actor != null)
        {
          actor.removeSelf();
          data[0] = -2// hit
          bp.sendDataBlock(data);
          enemyHits++;              
        }
        break;

      case -2:
        addActor(new Actor("sprites/hit.gif"), loc);
        hits++;
        break;      
    }
    updateTitle();
    refresh();
  }

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

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

// ---------class Ship ----------
class Ship extends Actor
{
  public Ship()
  {
    super("sprites/boat.gif");
  }
}

Erklärungen zum Programmcode:
init() Bei jedem Spieler 10 Schiffe an zufälligen Positionen erzeugt

int [ ] data  = new int [ 3]
data[0]  = -1
data[1]  = loc.x
data[2]  = loc.y    bp.sendDataBlock(data)

Gesendet werden 3 Integer:
data[0] : Spiel-Status
data[1]: x-Koordinate des Mausklicks
data[2]: y-Koordinate des Mausklicks

updateTitle()

Aktualisiert die Anzeige im Titelbalken (Anzahl Treffer, Spielberechtigung, Spielende)
receiveDateBlock()
data[0] = -1
data[0] = -2

Nach jedem Mausklick wird data[0], data[1] und data[-2] empfangen. Die zwei letzten Integer geben die Koordinaten des Mausklicks zurück. Bei data[0] unterscheiden wir zwei Fälle:
-1: Die nachfolgenden Koordinaten bezeichnet die Zielposition. Gegner geprüft, ob sich an dieser Position ein Schiff befindet. Falls ja, entfernt er das Schiff im eigenen Feld und meldet mit data[0]=-2, dass das Schiff getroffen wurde
-2: Der Schuss war ein Treffer. Dies wird mit einem Bild dargestellt und die Trefferzahl hinaufgezählt

 

Vollständiges Spiel (Battleship)

Beim vollständigen Spiel werden verschiedene Schiffsarten verwendet Flugzeugträger (Carrier), Schlachtschiff (Battleship), zerstörer (Destroyer), Unterseeboot (Submarine) und Patrouillienboot (PatrolBoat). Ausserdem kann jeder Spieler seine Schiffe selbst positionieren.

 

Beispiel zeigen

Programmcode: Download Battleship.zip

 
Spieler 1
Spieler 2

Beim Aufbau der Bluetooth-Verbindung gehen Sie wie folgt vor:

Eine genauere Spielbeschreibung und Erkärungen zum Programmcode finden Sie unter www.aplu.ch/Sample Applikation 4