Project

General

Profile

Download (10.2 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / states / RubikStateSolver.java @ 1f9772f3

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.states;
21

    
22
import android.content.SharedPreferences;
23
import android.content.res.Resources;
24
import android.graphics.Bitmap;
25
import android.graphics.Canvas;
26
import android.graphics.Paint;
27
import android.util.DisplayMetrics;
28
import android.view.View;
29
import android.widget.Button;
30
import android.widget.ImageButton;
31
import android.widget.LinearLayout;
32

    
33
import org.distorted.main.R;
34
import org.distorted.main.RubikActivity;
35
import org.distorted.objects.RubikObject;
36
import org.distorted.objects.RubikObjectList;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class RubikStateSolver extends RubikStateAbstract
41
  {
42
  private static final int NUM_FACES   =  6;
43
  private static final int BITMAP_SIZE = 35;
44

    
45
  private static final int[] FACE_COLORS = new int[]
46
         {
47
           0xffffff00, 0xffffffff,
48
           0xff0000ff, 0xff00ff00,
49
           0xffff0000, 0xffb5651d
50
         };
51

    
52
  private static Bitmap[] mBitmap;
53
  private ImageButton[] mColorButton;
54
  private Button mBackButton, mSolveButton;
55
  private boolean mSolving;
56
  private int mCurrentColor;
57

    
58
  private class Solver implements Runnable
59
    {
60
    private String mCubeString;
61
    private RubikActivity mAct;
62

    
63
    ///////////////////////////////////////////////////
64

    
65
    Solver(String str, RubikActivity act)
66
   	  {
67
	    mCubeString = str;
68
	    mAct        = act;
69
   	  }
70

    
71
    ///////////////////////////////////////////////////
72

    
73
    public void start()
74
      {
75
	    Thread thr = new Thread(this);
76
	    thr.start();
77
      }
78

    
79
    ///////////////////////////////////////////////////
80

    
81
    public void interrupt()
82
      {
83
	    org.distorted.solvers.cube3.Search.interrupt();
84
      }
85

    
86
    ///////////////////////////////////////////////////
87

    
88
    public void run()
89
	    {
90
	    Resources res = mAct.getResources();
91
	    String result;
92

    
93
	    if( !org.distorted.solvers.cube3.Search.prepare(res) )
94
	      result= "Error 9";
95
	    else
96
	      result = org.distorted.solvers.cube3.Search.solution(mCubeString, 24, 20);
97

    
98
	    if (result.contains("Error"))
99
	      {
100
	      switch (result.charAt(result.length() - 1))
101
	        {
102
		      case '1': result = res.getString(R.string.error1); break;
103
		      case '2': result = res.getString(R.string.error2); break;
104
		      case '3': result = res.getString(R.string.error3); break;
105
		      case '4': result = res.getString(R.string.error4); break;
106
		      case '5': result = res.getString(R.string.error5); break;
107
		      case '6': result = res.getString(R.string.error6); break;
108
		      case '7': result = res.getString(R.string.error7); break;
109
		      case '8': result = res.getString(R.string.error8); break;
110
		      case '9': result = res.getString(R.string.error9); break;
111
		      }
112

    
113
	      // TODO: pop up an error dialog.
114
	      }
115
	    else
116
        {
117
        setSolved( mAct, org.distorted.solvers.cube3.Search.numMoves(), result);
118
        }
119
	    }
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  void leaveState(RubikActivity act)
125
    {
126
    RubikObject object = act.getObject();
127
    object.resetAllTextureMaps();
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  void enterState(final RubikActivity act)
133
    {
134
    mSolving = false;
135

    
136
    act.changeObject(RubikObjectList.CUBE,3,null);
137

    
138
    DisplayMetrics metrics = act.getResources().getDisplayMetrics();
139
    final float scale = metrics.density;
140

    
141
    // TOP ////////////////////////////
142
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
143
    layoutTop.removeAllViews();
144

    
145
    if( mBitmap     ==null ) setupBitmaps(scale);
146
    if( mColorButton==null ) setupColorButtons(act,scale);
147

    
148
    for(ImageButton button: mColorButton) layoutTop.addView(button);
149

    
150
    // BOT ////////////////////////////
151
    if( mSolveButton==null ) setupSolveButton(act,scale);
152

    
153
    LinearLayout layoutLeft = act.findViewById(R.id.mainBarLeft);
154
    layoutLeft.removeAllViews();
155
    layoutLeft.addView(mSolveButton);
156

    
157
    if( mBackButton==null ) setupBackButton(act,scale);
158

    
159
    LinearLayout layoutRight = act.findViewById(R.id.mainBarRight);
160
    layoutRight.removeAllViews();
161
    layoutRight.addView(mBackButton);
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  private void setSolved( RubikActivity act, int numMoves, String moves)
167
    {
168
    mSolving = false;
169

    
170
    RubikState.switchState(act,RubikState.SOLU);
171
    }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

    
175
  private void setupBitmaps(float scale)
176
    {
177
    final int SIZE = (int)(scale*BITMAP_SIZE);
178
    final float R = SIZE*0.10f;
179
    final float M = SIZE*0.05f;
180

    
181
    mBitmap = new Bitmap[NUM_FACES];
182

    
183
    Paint paint = new Paint();
184
    paint.setColor(0xff008800);
185
    paint.setStyle(Paint.Style.FILL);
186

    
187
    paint.setAntiAlias(true);
188
    paint.setTextAlign(Paint.Align.CENTER);
189
    paint.setStyle(Paint.Style.FILL);
190

    
191
    for(int i=0; i<NUM_FACES; i++)
192
      {
193
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
194
      Canvas canvas = new Canvas(mBitmap[i]);
195

    
196
      paint.setColor(0xff000000);
197
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
198

    
199
      paint.setColor(FACE_COLORS[i]);
200
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
201
      }
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  private void setupColorButtons(final RubikActivity act, final float scale)
207
    {
208
    mColorButton = new ImageButton[NUM_FACES];
209

    
210
    for(int i=0; i<NUM_FACES; i++)
211
      {
212
      final int ii = i;
213
      int padding = (int)(3*scale + 0.5f);
214
      LinearLayout.LayoutParams objectParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
215
      mColorButton[i] = new ImageButton(act);
216
      mColorButton[i].setLayoutParams(objectParams);
217
      mColorButton[i].setPadding(padding,0,padding,0);
218
      mColorButton[i].setImageBitmap(mBitmap[i]);
219

    
220
      mColorButton[i].setOnClickListener( new View.OnClickListener()
221
        {
222
        @Override
223
        public void onClick(View view)
224
          {
225
          android.util.Log.e("solver", "button "+FACE_COLORS[ii]+" clicked");
226
          }
227
        });
228
      }
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  private void setupSolveButton(final RubikActivity act, final float scale)
234
    {
235
    int padding = (int)(3*scale + 0.5f);
236
    LinearLayout.LayoutParams backParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
237
    mSolveButton = new Button(act);
238
    mSolveButton.setLayoutParams(backParams);
239
    mSolveButton.setPadding(padding,0,padding,0);
240
    mSolveButton.setText(R.string.solve);
241

    
242
    mSolveButton.setOnClickListener( new View.OnClickListener()
243
      {
244
      @Override
245
      public void onClick(View v)
246
        {
247
        if( !mSolving )
248
          {
249
          String cubeString = "INVALID"; // TODO: obtain a valid cube string
250
          Solver solver = new Solver(cubeString, act );
251
          solver.start();
252
          mSolving = true;
253
          }
254
        }
255
      });
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

    
260
  private void setupBackButton(final RubikActivity act, final float scale)
261
    {
262
    int padding = (int)(3*scale + 0.5f);
263
    LinearLayout.LayoutParams backParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
264
    mBackButton = new Button(act);
265
    mBackButton.setLayoutParams(backParams);
266
    mBackButton.setPadding(padding,0,padding,0);
267
    mBackButton.setText(R.string.back);
268

    
269
    mBackButton.setOnClickListener( new View.OnClickListener()
270
      {
271
      @Override
272
      public void onClick(View v)
273
        {
274
        RubikState.goBack(act);
275
        }
276
      });
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  public void savePreferences(SharedPreferences.Editor editor)
282
    {
283
    mColorButton = null;
284
    mBackButton  = null;
285
    mSolveButton = null;
286

    
287
    editor.putInt("stateSolver_color", mCurrentColor);
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  public void restorePreferences(SharedPreferences preferences)
293
    {
294
    mCurrentColor = preferences.getInt("stateSolver_color", 0);
295
    }
296
  }
(7-7/8)