GameGrid: Game programming with Java

Research project PHBern  
HomePrintJava-Online

MasterMind


MasterMind is a well-known logic game. At the beginning of the game, the computer defines a four-digit color code out of six different colors. It does not matter if the color code has more than one or more of the same color. The player tries to decrypt the color code by placing differntly colored pegs in a row on the board. After each guess, the player receives information about his/her code. If a peg has the correct color and is placed at the right spot, a black stick is set. If the color is correct, but the spot is not, a white stick is set. If none of these criterias are reached, no stick is placed. The goal of the game, is to decrypt the code with the least possible guesses. If the player does not find out the code after 7 guesses, the game is over and the color code is shown.

In our example (designed by Stefan Moser) the colored pegs are placed with the left mouse button. Clicking on the peg again, the color is changed. Right clicking shows the previous color. A guess is ended by clicking on the question mark. If the game is over, it can be restarted by clicking on the board.

Run this example

Edit this example in the Online-Editor

 

Download the program code (MasterMind.zip)

Explaining the program code:
reset()
for (int i = 0; i < secretCode.length; i++)
    secretCode[i] = (int)(Math.random() * Peg.NbColors)
the color code is randomly defined in the method reset(). This method is called at each start and restart of the game. Since our game uses 6 different colors, the object Peg has six Sprites (peg_0.png ..., peg_5.png)

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

at the position of the click, a peg is set
if (mouse.getEvent() == GGMouse.lPress)
    getOneActorAt(loc).showNextSprite()
the color of the peg can be changed by clicking it. This shows the next Sprite
if (placedPegs == 4)
   addActor(new EvaluateButton(), new Location(1, currentRow))
if four pegs are set in the current row, the evaluation sticks are shown
for (int i = 0; i < 4; i++)
   if (guess[i] == secretCode[i])
      blackPegs++
if position and color are correct, the number of black sticks is increased
for (int j = 0; j < 4; j++)
   if (color == guess[j] && !alreadyProcessed.contains(j))
      alreadyProcessed.add(j);
      whitePegs++
if only the color is correct, the number of white sticks is increased

Program code:

// 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);
  }
}