Spielprogrammierung mit Java
HomeAufgabenDruckenJava-Online

MasterMind


MasterMind ist ein bekanntes Logikspiel. Der Computer legt zu Beginn einen vierstelligen geordneten Farbcode fest, der aus sechs Farben ausgewählt wird; eine Farbe kann auch mehrmals verwendet werden. Der Spieler versucht den Code herauszufinden, in dem er reihenweise farbige Stifte setzt. Nach jedem Zug erhällt er die Information, wie viele Stifte er in Farbe und Position richtig gesetzt hat (schwarzer Stift) und wie viele Stifte zwar die richtige Farbe haben, aber an einer falschen Position stehen (weisser Stift). Ziel ist es, den Farbcode mit möglichst wenigen Zügen zu erraten. Gelingt es dem Spieler nicht, den Farbcode in 7 Zügen zu erraten, wird die Lösung angezeigt.

In unserem MasterMind (entwickelt durch Stefan Moser) werden die Farbstifte mit linkem Masklick an der entsprechenden Position gesetzt. Erneutes Klicken bewirkt Farbwechsel. Rechtsklick holt die vorhergehende Farbe zurück. Ein Zug wird mit Klick auf Fragezeichen beendet. Ist das Spiel bendet, kann mit Klick auf das Spielbrett ein neue Spiel gestartet werden.

Programmcode für lokale Bearbeitung downloaden ( MasterMind.zip)

 

Erklärungen zum Programmcode:

reset()
for (int i = 0; i < secretCode.length; i++)
    secretCode[i] = (int)(Math.random() * Peg.NbColors)
Der Farbcode wird in der Methode reset() zufällig festgelegt. Diese wird beim Spielbeginn und bei der Spielwiederholung aufgerufen. Da in unserem Spiel 6 Farben verwendet, besitzt das Objekt Peg sechs Sprites (peg_0.png ..., peg_5.png)

loc = toLocation(mouse.getX(), mouse.getY())
addActor(new Peg(), loc)

An der Position des Mausklicks wird ein Stift erzeugt
if (mouse.getEvent() == GGMouse.lPress)
    getOneActorAt(loc).showNextSprite()
Die Stiftfarbe kann mit Mausklick geändert werden. Durch wiederholtes Klicken wird jeweils die nächste Farbe (das nächste Sprite) angezeigt
if (placedPegs == 4)
   addActor(new EvaluateButton(), new Location(1, currentRow))
Wenn 4 Stifte gesetzt sind, erscheint in der aktuellen Reihe ein Evaluationsstift
for (int i = 0; i < 4; i++)
   if (guess[i] == secretCode[i])
      blackPegs++
Falls Position und Farbe übereinstimmt, wird die Anzahl der schwarzen Stifte erhöht
for (int j = 0; j < 4; j++)
   if (color == guess[j] && !alreadyProcessed.contains(j))
      alreadyProcessed.add(j);
      whitePegs++
Falls nur die Farbe übereinstimmt, wird die Anzahl weissen Stifte erhöht

Programmcode:

// MasterMind.java

import java.awt.*;
import java.util.*;
import ch.aplu.jgamegrid.*;

public class MasterMind extends GameGrid implements GGMouseListener
{
  int[] secretCode = new int[4];
  int currentRow;
  boolean roundFinished;
  final String version = "0.2";
  ActiveRowMarker marker;
  private int placedPegs = 0;

  public MasterMind()
  {
    super(7, 10, 60, null"sprites/mastermindbg.png"false);
    this.addMouseListener(thisGGMouse.lPress | GGMouse.rPress);
    this.setTitle("MasterMind - V " + version);
    getBg().setPaintColor(Color.red);
    reset();
    show();
  }

  public boolean mouseEvent(GGMouse mouse)
  {
    if (roundFinished)
    {
      reset();
      return true;
    }

    Location loc = toLocation(mouse.getX(), mouse.getY());

    if (placedPegs == && loc.x == && loc.y == currentRow)
    { // click on evalButton -> evaluate
      int[] guess = new int[4];
      for (int = 0; i < 4; i++)
        guess[i] = getOneActorAt(new Location(+ i, currentRow)).getIdVisible();
      evaluateGuess(guess);
    }

    if (loc.y == currentRow && loc.x > && loc.x < 6)
    {
      if (getOneActorAt(loc) == null)
      {
        this.addActor(new Peg(), loc);
        placedPegs++;
        if (placedPegs == 4)
        { // show evaluate button
          addActor(new EvaluateButton(), new Location(1, currentRow));
        }
      }
      else if (mouse.getEvent() == GGMouse.lPress)
        getOneActorAt(loc).showNextSprite(); //if leftclick -> next color
      else
        getOneActorAt(loc).showPreviousSprite(); //if rightClick -> previous color
    }
    refresh();
    return true;
  }

  public void reset()
  {
    removeAllActors();
    getBg().clear();
    currentRow = this.nbVertCells - 2; 
    roundFinished = false;
    for (int = 0; i < secretCode.length; i++)
      secretCode[i] = (int)(Math.random() * Peg.NbColors);
    marker = new ActiveRowMarker();
    addActor(marker, new Location(1, currentRow));
    refresh();
  }

  private void evaluateGuess(int[] guess)
  {
    int blackPegs = 0, whitePegs = 0;
    for (int = 0; i < 4; i++)
      if (guess[i] == secretCode[i])
        blackPegs++;
    ArrayList<Integer> alreadyProcessed = new ArrayList<Integer>();
    for (int color : secretCode)
      for (int = 0; j < 4; j++)
        if (color == guess[j] && !alreadyProcessed.contains(j))
        {
          alreadyProcessed.add(j);
          whitePegs++;
          break;
        }
    whitePegs -= blackPegs;
    showTips(whitePegs, blackPegs);

    if (blackPegs == 4) // got right combination
      finishRound("Correct!");
    else
      currentRow--//go to next column for next try

    if (currentRow == 1) //no more guesses left
      finishRound("Pattern not found!");

    marker.setLocation(new Location(1, currentRow));
    placedPegs = 0;
    removeActors(EvaluateButton.class);
  }

  private void finishRound(String reason)
  {
    getBg().setFont(new Font("verdana"Font.PLAIN, 18));
    getBg().drawText(reason, new Point(10, 32));
    getBg().setFont(new Font("verdana"Font.PLAIN, 18));
    getBg().drawText("Click to play again"new Point(10, 590));
    removeActor(marker);
    showSolution();
    roundFinished = true;
  }

  private void showTips(int whitePegs, int blackPegs)
  {
    for (int = 0; i < 4; i++)
    {
      if (blackPegs > 0)
      {
        EvalPeg ep = new EvalPeg(0);
        addActor(ep, new Location(1, currentRow));
        ep.turn(90 * i);
        blackPegs--;
      }
      else if (whitePegs > 0)
      {
        EvalPeg ep = new EvalPeg(1);
        addActor(ep, new Location(1, currentRow));
        ep.turn(90 * i);
        whitePegs--;
      }
    }
  }

  private void showSolution()
  {
    int = 2;
    for (int spriteNr : secretCode)
    {
      Peg peg = new Peg();
      peg.show(spriteNr);
      addActor(peg, new Location(x, 1));
      x++;
    }
  }

  private String printArray(int[] a)
  {
    String result = "";
    for (int b : a)
      result += + ", ";
    return result;
  }

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

// -----------class ActiveRowMarker -----------
class ActiveRowMarker extends Actor
{
  public ActiveRowMarker ()
  {
    super("sprites/activeRowMarker.png");
  }
}

// ----------class EvalPeg -----------------
class EvalPeg extends Actor
{
  public EvalPeg(int sprite)
  {
    // sprite 0 = black, sprite 1 = white
    super(true"sprites/EvalPeg.png"2);
    show(sprite);
  }
}

// -----------class EvaluateButton------------
class EvaluateButton extends Actor
{
  public EvaluateButton()
  {
    super("sprites/EvaluateButton.png");
  }
}

//-------- class Peg-------------------------
class Peg extends Actor
{
  public static final int NbColors = 6;
  public Peg()
  {
    super("sprites/peg.png"NbColors);
  }
}