Die ‘response’ ist in diesem Beispiel einfach ein Point, der verwendet wird, um 2 ints zu speichern: Die Anzahl der richtigen Farben+Position, und die Anzahl der richtigen Farben. Das ist ja das, was man dem Computer (also dem NPC) geben muss, und auf Basis dessen er seinen nächsten “guess” berechnet. Die Methode “computeResponse”, die dort dabei ist, wird NUR verwendet, um diese Response auszurechnen. NUR die Response wird dann dem Computer gegeben, aber die echte Lösung bekommt er NICHT. Die ‘computeResponse’-Methode ist auch static, d.h. der Computer “kann” sich da gar nichts merken. Man könnte die Methode ‘computeResponse’ wie gesagt in eine eigene Klasse auslagern, oder ganz wegnehmen. Intern verwendet der Computerspieler zwar auch eine computeResponse-Methode, aber die errechnet in diesem Fall nur mögliche Antworten auf mögliche echte Kombinationen.
Wenn man’s drauf anlegt: So hat die MasterMindComputerPlayer-Klasse nur noch zwei public-Methoden
- public String makeGuess() : Liefert einen neuen Guess
- public void provideResponse(Point response) : Das teilt man dem Computerspieler mit
Nichts wo er die echte Kombination übergeben bekommt:
// By Marco13 for http://forum.byte-welt.de/showthread.php?p=16589#post16589
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class MasterMindTest
{
public static void main(String args[])
{
MasterMindComputerPlayer mm = new MasterMindComputerPlayer();
String real = "cfca";
System.out.println("Real "+real);
while (true)
{
String guess = mm.makeGuess();
Point response = computeResponseWithoutTellingTheComputerPlayerTheRealCombination(real, guess);
System.out.println("Guess "+guess+" response "+response);
if (guess.equals(real))
{
break;
}
mm.provideResponse(response);
}
System.out.println("Done");
}
public static Point computeResponseWithoutTellingTheComputerPlayerTheRealCombination(String real, String guess)
{
// Not very elegant (i.e.: a hack)
List<Character> realList = toCharList(real);
List<Character> guessList = toCharList(guess);
int rightColorAndRightPosition = 0;
for (int i=0; i<real.length(); i++)
{
if (guess.charAt(i) == real.charAt(i))
{
rightColorAndRightPosition++;
realList.set(i, null);
guessList.set(i, null);
}
}
int rightColorAndWrongPosition = 0;
for (int i=0; i<real.length(); i++)
{
Character guessChar = guessList.get(i);
int index = realList.indexOf(guessChar);
if (guessChar != null && index != -1)
{
realList.set(index, null);
rightColorAndWrongPosition++;
}
}
return new Point(rightColorAndRightPosition, rightColorAndWrongPosition);
}
private static List<Character> toCharList(String s)
{
List<Character> result = new ArrayList<Character>();
for (int i=0; i<s.length(); i++)
{
result.add(s.charAt(i));
}
return result;
}
}
class MasterMindComputerPlayer
{
private static final Map<String, String> guessFourMap = new HashMap<String, String>();
static
{
guessFourMap.put("acfb", "dcad");
guessFourMap.put("aebf", "edfd");
guessFourMap.put("aefb", "eacc");
guessFourMap.put("afbe", "bfcd");
guessFourMap.put("bafe", "eadc");
guessFourMap.put("beaf", "edae");
guessFourMap.put("befa", "eeda");
guessFourMap.put("eabf", "fdfb");
guessFourMap.put("aadb", "babd");
guessFourMap.put("abae", "bbcc");
guessFourMap.put("aeaf", "cffd");
guessFourMap.put("cafa", "fdfa");
guessFourMap.put("aaee", "dddf");
}
private int guessCounter = 0;
private String lastGuess = null;
private List<String> currentList = null;
public MasterMindComputerPlayer()
{
List<String> completeList = createCompleteList();
List<List<String>> categories = splitByNumberOfDuplicates(completeList);
currentList = new ArrayList<String>();
for (List<String> category : categories)
{
Collections.sort(category);
currentList.addAll(category);
}
//System.out.println("Current list: ");
//for (String s : currentList)
//{
// System.out.println(s);
//}
}
public String makeGuess()
{
guessCounter++;
switch (guessCounter)
{
case 1: lastGuess = "abcd"; break;
case 2: lastGuess = "bcde"; break;
case 3: lastGuess = "cdef"; break;
case 4:
lastGuess = currentList.get(0);
String value = guessFourMap.get(lastGuess);
if (value != null)
{
lastGuess = value;
}
break;
default:
lastGuess = currentList.get(0);
}
return lastGuess;
}
private static Point computeResponse(String real, String guess)
{
// Not very elegant (i.e.: a hack)
List<Character> realList = toCharList(real);
List<Character> guessList = toCharList(guess);
int rightColorAndRightPosition = 0;
for (int i=0; i<real.length(); i++)
{
if (guess.charAt(i) == real.charAt(i))
{
rightColorAndRightPosition++;
realList.set(i, null);
guessList.set(i, null);
}
}
int rightColorAndWrongPosition = 0;
for (int i=0; i<real.length(); i++)
{
Character guessChar = guessList.get(i);
int index = realList.indexOf(guessChar);
if (guessChar != null && index != -1)
{
realList.set(index, null);
rightColorAndWrongPosition++;
}
}
return new Point(rightColorAndRightPosition, rightColorAndWrongPosition);
}
private static List<Character> toCharList(String s)
{
List<Character> result = new ArrayList<Character>();
for (int i=0; i<s.length(); i++)
{
result.add(s.charAt(i));
}
return result;
}
public void provideResponse(Point response)
{
List<String> toRemove = new ArrayList<String>();
for (String possible : currentList)
{
Point possibleResponse = computeResponse(possible, lastGuess);
if (!response.equals(possibleResponse))
{
//System.out.println("Response for "+possible+" would be "+possibleResponse);
toRemove.add(possible);
}
}
currentList.removeAll(toRemove);
//System.out.println("Remaining possibilities: "+currentList);
}
private static List<String> createCompleteList()
{
List<String> result = new ArrayList<String>();
String input[] = { "a", "b", "c", "d", "e", "f" };
CombinationIterable<String> ci = new CombinationIterable<String>(4, input);
for (String sa[] : ci)
{
String string = "";
for (String s : sa)
{
string += s;
}
result.add(string);
}
return result;
}
private static List<List<String>> splitByNumberOfDuplicates(List<String> list)
{
List<List<String>> result = new ArrayList<List<String>>();
for (int i=0; i<4; i++)
{
result.add(new ArrayList<String>());
}
for (String string : list)
{
int duplicates = countDuplicates(string);
List<String> target = result.get(duplicates);
target.add(string);
}
return result;
}
private static int countDuplicates(String s)
{
int count = 0;
for (int i=1; i<s.length(); i++)
{
if (s.charAt(i) == s.charAt(i-1))
{
count++;
}
}
return count;
}
private static class CombinationIterable<T> implements Iterable<T[]>
{
private T input[];
private int sampleSize;
private int numElements;
public CombinationIterable(int sampleSize, T... input)
{
this.sampleSize = sampleSize;
this.input = input.clone();
numElements = (int) Math.pow(input.length, sampleSize);
}
public Iterator<T[]> iterator()
{
return new Iterator<T[]>()
{
private int current = 0;
private int chosen[] = new int[sampleSize];
public boolean hasNext()
{
return current < numElements;
}
public T[] next()
{
@SuppressWarnings("unchecked")
T result[] = (T[]) java.lang.reflect.Array.newInstance(
input.getClass().getComponentType(), sampleSize);
for (int i = 0; i < sampleSize; i++)
{
result** = input[chosen**];
}
increase();
current++;
return result;
}
private void increase()
{
int index = chosen.length - 1;
while (index >= 0)
{
if (chosen[index] < input.length - 1)
{
chosen[index]++;
return;
}
else
{
chosen[index] = 0;
index--;
}
}
}
public void remove()
{
throw new UnsupportedOperationException(
"May not remove elements from a combination");
}
};
}
}
}