Nun ist die Luftlinie auch in der Knoten Klasse integriert.
[schiebespiel.git] / MinSchritte.java
blob4257fdaa635725d3729130a14dd244a198e8f001
1 import java.util.*;
2 import java.lang.*;
3 import java.math.BigInteger;
6 class MinSchritte {
7 class SteinCoords {
8 int x,y;
9 SteinCoords(int x, int y) {
10 this.x = x;
11 this.y = y;
13 public int distanz(SteinCoords sc) {
14 return Math.abs(x - sc.x) + Math.abs(y - sc.y);
18 /* Index 0 -> Leere
19 Index 1 -> Einer
20 Index 2 -> Zweier horizontal
21 Index 3 -> Zweier vertikal
22 Index 4 -> Vierer */
23 ArrayList< ArrayList<SteinCoords> > zielCoords = new ArrayList< ArrayList<SteinCoords> >();
25 ArrayList< ArrayList<SteinCoords> > findCoords(Knoten k) {
27 ArrayList<SteinCoords> einer = new ArrayList<SteinCoords>();
28 ArrayList<SteinCoords> zweier_horiz = new ArrayList<SteinCoords>();
29 ArrayList<SteinCoords> zweier_vertik = new ArrayList<SteinCoords>();
30 ArrayList<SteinCoords> vierer = new ArrayList<SteinCoords>();
31 SteinCoords sc;
33 int[][] feld = k.get_spielfeld();
34 for(int x = 0; x < feld.length; ++x) {
35 for(int y = 0; y < feld[0].length; ++y) {
36 switch(feld[x][y]) {
37 case Knoten.einer:
38 sc = new SteinCoords(x,y);
39 einer.add(sc);
40 break;
41 case Knoten.zweier_links:
42 sc = new SteinCoords(x,y);
43 zweier_horiz.add(sc);
44 break;
45 case Knoten.zweier_oben:
46 sc = new SteinCoords(x,y);
47 zweier_vertik.add(sc);
48 break;
49 case Knoten.vierer_lo:
50 sc = new SteinCoords(x,y);
51 vierer.add(sc);
52 break;
53 default:
54 break;
58 ArrayList<ArrayList<SteinCoords>> coords = new ArrayList<ArrayList<SteinCoords>>();
59 coords.add(einer);
60 coords.add(zweier_horiz);
61 coords.add(zweier_vertik);
62 coords.add(vierer);
64 return coords;
67 MinSchritte(Knoten ziel) {
68 setZielCoords(ziel);
71 void setZielCoords(Knoten ziel) {
72 zielCoords = findCoords(ziel);
75 int computeLuftlinie(Knoten k) {
77 PermutationGenerator x;
78 int[] indices;
79 int luftlinie = 0;
80 ArrayList<ArrayList<SteinCoords>> kCoords = findCoords(k);
81 ArrayList<SteinCoords> scList, zscList;
83 for (int i=0; i<4; ++i) {
84 int tmpSum = 0;
85 int minSum = 1000;
86 scList = kCoords.get(i);
87 zscList = zielCoords.get(i);
88 x = new PermutationGenerator(scList.size());
89 while(x.hasMore()) {
90 tmpSum = 0;
91 indices = x.getNext();
92 for (int j=0; j<scList.size(); ++j) {
93 tmpSum += scList.get(j).distanz(zscList.get(indices[j]));
95 if (minSum > tmpSum) {
96 minSum = tmpSum;
99 luftlinie += minSum;
101 return luftlinie;
106 //--------------------------------------
107 // Systematically generate permutations.
108 //--------------------------------------
110 class PermutationGenerator {
112 private int[] a;
113 private BigInteger numLeft;
114 private BigInteger total;
116 //-----------------------------------------------------------
117 // Constructor. WARNING: Don't make n too large.
118 // Recall that the number of permutations is n!
119 // which can be very large, even when n is as small as 20 --
120 // 20! = 2,432,902,008,176,640,000 and
121 // 21! is too big to fit into a Java long, which is
122 // why we use BigInteger instead.
123 //----------------------------------------------------------
125 public PermutationGenerator (int n) {
126 if (n < 1) {
127 throw new IllegalArgumentException ("Min 1");
129 a = new int[n];
130 total = getFactorial (n);
131 reset ();
134 //------
135 // Reset
136 //------
138 public void reset () {
139 for (int i = 0; i < a.length; i++) {
140 a[i] = i;
142 numLeft = new BigInteger (total.toString ());
145 //------------------------------------------------
146 // Return number of permutations not yet generated
147 //------------------------------------------------
149 public BigInteger getNumLeft () {
150 return numLeft;
153 //------------------------------------
154 // Return total number of permutations
155 //------------------------------------
157 public BigInteger getTotal () {
158 return total;
161 //-----------------------------
162 // Are there more permutations?
163 //-----------------------------
165 public boolean hasMore() {
166 return numLeft.compareTo (BigInteger.ZERO) == 1;
169 //------------------
170 // Compute factorial
171 //------------------
173 private static BigInteger getFactorial (int n) {
174 BigInteger fact = BigInteger.ONE;
175 for (int i = n; i > 1; i--) {
176 fact = fact.multiply (new BigInteger (Integer.toString (i)));
178 return fact;
181 //--------------------------------------------------------
182 // Generate next permutation (algorithm from Rosen p. 284)
183 //--------------------------------------------------------
185 public int[] getNext () {
187 if (numLeft.equals (total)) {
188 numLeft = numLeft.subtract (BigInteger.ONE);
189 return a;
192 int temp;
194 // Find largest index j with a[j] < a[j+1]
196 int j = a.length - 2;
197 while (a[j] > a[j+1]) {
198 j--;
201 // Find index k such that a[k] is smallest integer
202 // greater than a[j] to the right of a[j]
204 int k = a.length - 1;
205 while (a[j] > a[k]) {
206 k--;
209 // Interchange a[j] and a[k]
211 temp = a[k];
212 a[k] = a[j];
213 a[j] = temp;
215 // Put tail end of permutation after jth position in increasing order
217 int r = a.length - 1;
218 int s = j + 1;
220 while (r > s) {
221 temp = a[s];
222 a[s] = a[r];
223 a[r] = temp;
224 r--;
225 s++;
228 numLeft = numLeft.subtract (BigInteger.ONE);
229 return a;