|
MasterMindModel.java
Created with JBuilder |
package mastermind;
/**
* MasterMindModel -
* Enthält das ganze Spielbrett mit den Regeln, dem Code und einer Test Routine.
*
* Mind Blowing Master Mind ein klein Projekt des Informatik Unterrichts Programmieren II
* Authors Pascal Naef; Fabian Heusser
* Teacher: H. J. Diethlem
* School: hta.fhz.ch, Horw;
* Project Homepage: http://www.w3p.ch/mastermind/
*
* supported features:
* OYOAHA Look and feel;
* Transparen Pictures;
* Drag & Drop;
* Copy & Paste;
*
*
* LEGAL NOTICE
* THIS PROJECT AND ITS FILES ARE COPYRIGHTED BY THE AUTHORS
* THIS PROJECT CAN BE COPIED, MODIFIED AND DISTRIBUTED
* UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENCE
* WITH THE RESTRICTION OF SENDING US A MAIL WITH THE MODIFIED
* SOURCODE IF THE PROJECT IS MODIEFIED.
*
* if you like this progi feel free to send us something (beer, chips, playmates, houses....).
*
*
* @author Fabian Heusser
* @author Pascal Naef
* @version 1.0 $Date: 2001/12/05 14:46:53 $ $Revision: 1.1.1.1 $
* @(#) MasterMindView.java
*/
// 2001-11-16 hef getScore() improved
public class MasterMindModel {
private int[][] playGround;
private String code;
private int width, height, colors, currentRow;
private static final int maxColor = 10; //Maximale anzahl Farben
private static final boolean blockInactiveRows = false; //soll man auch auf reihen setzten können die nicht aktiv sind?
private static final boolean allowCheating = false;
/**
* Der Konstruktor generiert den CODE und definiert die Grösse.
* @param width int, Anzahl der Code Stellen. 1 - ...
* @param height int, Anzahl der Maximalen Versuchen 1 - ...
* @param colors int, number of different colors 1 - 10 are valid arguments
*/
public MasterMindModel(int width, int height, int colors) throws IllegalArgumentException {
//check params an assign them
if (colors > maxColor || colors < 0) throw new IllegalArgumentException("color is not in a valid range");
if (width < 1) throw new IllegalArgumentException("width is not in a valid range");
if (height < 1) throw new IllegalArgumentException("height is not in a valid range");
this.width = width;
this.height = height;
this.colors = colors;
//creating random Code
code = "";
for(int i=1; i<=width; i++){
code += (int) (Math.random() * (double) this.colors) + 1;
}
//code = "1244";
//System.out.println(code);
//setting up the PlayGround itself
playGround = new int[this.width][this.height];
currentRow = 0;
runSelfTest();
}
/**
* Setzt an einer Position eine Farbe
* @param x int, Position auf der Akutellen Linie dessen Farbe gesetzt werden Soll. 0 - ...
* @param color int Farbe die der Stift erhalten soll
*/
public void setTack(int x, int color) throws IllegalArgumentException{
if (color > this.colors || color < 0) throw new IllegalArgumentException("color is not in a valid range");
if (x < 0 || x > this.width-1) throw new IllegalArgumentException("x is not in a valid range");
playGround[x][currentRow] = color;
}
/**
* Setzt an einer Position eine Farbe
* @param x int, Position auf der Linie dessen Farbe gesetzt werden Soll. 0 - ...
* @param y int, Position in der Höhe dessen Farbe gesetzt werden Soll. 0 - ...
* @param color int Farbe die der Stift erhalten soll
*/
public void setTack(int x, int y, int color) throws IllegalArgumentException{
if (blockInactiveRows && y != currentRow) return;
if (!allowCheating && y < currentRow) return;
if (color > this.colors || color < 0) throw new IllegalArgumentException("color is not in a valid range");
if (x < 0 || x > this.width-1) throw new IllegalArgumentException("x is not in a valid range");
playGround[x][y] = color;
}
/**
* Lifert die Farbe eines Stiftes zurück
* @param x int, Lage des Stiftes in der Horizontalen
* @param y int, Lage des Stiftes in der Vertikalen
* @return int, farbe in Form einer Nummer
*/
public int getTack(int x, int y) throws IllegalArgumentException{
if (x < 0 || x > this.width-1) throw new IllegalArgumentException("x is not in a valid range");
if (y < 0 || y > this.height-1) throw new IllegalArgumentException("y is not in a valid range");
return playGround[x][y];
}
/**
* Gibt die breite, also die Code Länge zurück
* @return int, Schlüssel Länge 1 - ..
*/
public int getWidth(){return width;}
/**
* Gibt die Maximal mögliche Anzahl Versuche zurück um den Code zu Knacken.
* @return int, Maximale Anzahl Versuche 1 - ..
*/
public int getHeight(){return height;}
/**
* Gibt die Anzahl verschieder farben zurück die benötigt werden
* @return int, Maximale Anzahl Versuche 1 - ..
*/
public int getColors(){return colors;}
/**
* Berechnet die Auswertung der gesetzen Tacks.
* @param y int, Zeile welche berechnet werden soll
* @return Score im Format: [Anzahl Richtig Plazierte (also die Schwarzen)] * 100 +
* [Anzahl Richtige Farbe am Falschen Platz (also die weissen)]
* you have won if you reach a score of (width * 100)
*/
//2001-11-16 hef banned mechanisme added, whitout that the algorithm fail under certain circumstances
public int getScore(int y){
if (!allowCheating && y >= currentRow) return 0;
int score = 0;
boolean[] banned_i = new boolean[width];
boolean[] banned_k = new boolean[width];
for(int i=banned_i.length; --i>0;){banned_i[i] = false; banned_k[i] = false;};
for(int i=0; i < width; i++){
if (playGround[i][y] == code.charAt(i)-0x30) {
score += 100; //exact match
banned_i[i] = true;
banned_k[i] = true;
}
}
//checking color matching ...
for(int i=0; i < width; i++){
if (banned_i[i]) {continue;}
for(int k=0; k < width; k++){
if (banned_k[k]) {continue;}
if (playGround[k][y] == code.charAt(i)-0x30) {
score++; //color match
banned_k[k] = true;
break;
}
}
}
return score;
}
/**
* Incrementiert der Aktuelle Zug
* Einflussreich beim ganzen RegelWerk. So können reihen nicht mehr gesetzt
* werden die kleinder sind asl currentRow
*/
public void incrementTurn(){
currentRow++;
}
/**
* Liefert den Aktuellen Spielzug zurück
* @return int aktueller Höhe an der Gebastelt wird
*/
public int getTurn(){return currentRow; }
/**
* Liefert true wenn das Spiel gewonnen wurde
* @return boolean, True falls Alle Tacks der letzten reihe richtig sind.
*/
public boolean getWon(){return getScore(currentRow-1) == (width * 100);}
/**
* Liefert true fals das Spiel verloren wurde.
* @return boolean, true falls der aktuelle Spielzug grösser als die höhe des mastermind ist
*/
public boolean getLoose(){return currentRow >= height;}
/**
* Liefert das Code Wort zurück
* @return String Code Wort in width chars welche die farben representieren
*
*/
public String getCode(){return code;}
/**
* Liefert zurück ob der aktuelle spielzug komplett ist.
* @return boolean, true wenn alle tacks gesetzt sind des aktuellen zug.
*
*/
public boolean isTurnComplete(){
boolean b = true;
for (int i = 0; i < width; i++){
if (playGround[i][currentRow] < 1) {
b = false;
}
}
return b;
}
// SELF TEST PROCEDURES
/**
* Let The Procedures Make a self Test.
* @return bollean, false if test failed.
*/
public boolean runSelfTest(){
// we gonna save the object status;
int[][] tmp = playGround;
int tmpHeight = height;
int tmpWidth = width;
int tmpCurrentRow = currentRow;
String tmpCode = code;
boolean test = true;
// Test Values Last schould be one that fit the won contition!
String[] testCases = {"2323","1333","2111","3123","4321","1111","1112","2131","1423",
"1222","1242","1243","1214","1234","1234"};
String[] TestOnCode = {"4141","4441","1234","1234","1234","1234","1234","1234","1234",
"1234","1234","1234","1234","1244","1234"};
int[] testScores = {0,1,2,3,4,100,101,102,103,200,201,202,300,300,400};
playGround = new int[testCases[0].length()][testCases.length];
for (int i=testCases.length; --i>0;){
for (int k=testCases[0].length(); --k>0;){ playGround[k][i] = 0; }
}