Skip to content

Commit cac7ee2

Browse files
unknownunknown
authored andcommitted
preserving tile order when orientation changes
1 parent 9dcbba3 commit cac7ee2

File tree

4 files changed

+133
-39
lines changed

4 files changed

+133
-39
lines changed

res/layout/activity_main.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
android:layout_height="match_parent"
55
android:padding="5dp" >
66

7-
<cz.destil.sliderpuzzle.ui.GameboardView
7+
<cz.destil.sliderpuzzle.ui.GameBoardView
88
android:id="@+id/gameboard"
99
android:layout_width="match_parent"
1010
android:layout_height="match_parent" >
11-
</cz.destil.sliderpuzzle.ui.GameboardView>
11+
</cz.destil.sliderpuzzle.ui.GameBoardView>
1212

1313
</LinearLayout>

src/cz/destil/sliderpuzzle/ui/GameboardView.java

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cz.destil.sliderpuzzle.ui;
22

33
import java.util.ArrayList;
4+
import java.util.LinkedList;
45

56
import android.animation.Animator;
67
import android.animation.Animator.AnimatorListener;
@@ -34,7 +35,7 @@
3435
* @author David Vavra
3536
*
3637
*/
37-
public class GameboardView extends RelativeLayout implements OnTouchListener {
38+
public class GameBoardView extends RelativeLayout implements OnTouchListener {
3839

3940
public static final int GRID_SIZE = 4; // 4x4
4041
private int tileSize;
@@ -44,8 +45,9 @@ public class GameboardView extends RelativeLayout implements OnTouchListener {
4445
private RectF gameboardRect;
4546
private PointF lastDragPoint;
4647
private ArrayList<GameTileMotionDescriptor> currentMotionDescriptors;
48+
private LinkedList<Integer> tileOrder;
4749

48-
public GameboardView(Context context, AttributeSet attrSet) {
50+
public GameBoardView(Context context, AttributeSet attrSet) {
4951
super(context, attrSet);
5052
}
5153

@@ -89,10 +91,20 @@ public void fillTiles() {
8991
Bitmap original = ((BitmapDrawable) globe).getBitmap();
9092
TileSlicer tileSlicer = new TileSlicer(original, GRID_SIZE, getContext());
9193
// fill gameboard with slices
94+
if (tileOrder == null) {
95+
tileSlicer.randomizeSlices();
96+
} else {
97+
tileSlicer.setSliceOrder(tileOrder);
98+
}
9299
tiles = new ArrayList<TileView>();
93100
for (int rowI = 0; rowI < GRID_SIZE; rowI++) {
94101
for (int colI = 0; colI < GRID_SIZE; colI++) {
95-
TileView tile = tileSlicer.getSlice(TileSlicer.RANDOM_SLICE);
102+
TileView tile;
103+
if (tileOrder == null) {
104+
tile = tileSlicer.getTile();
105+
} else {
106+
tile = tileSlicer.getTile();
107+
}
96108
tile.coordinate = new Coordinate(rowI, colI);
97109
if (tile.isEmpty()) {
98110
emptyTile = tile;
@@ -186,8 +198,8 @@ private boolean lastDragMovedMinimally() {
186198
}
187199

188200
/**
189-
* Follows finger while dragging all currently moved tiles.
190-
* Allows movement only along x axis for row and y axis for column.
201+
* Follows finger while dragging all currently moved tiles. Allows movement
202+
* only along x axis for row and y axis for column.
191203
*
192204
* @param event
193205
*/
@@ -454,6 +466,32 @@ private Rect rectForCoordinate(Coordinate coordinate) {
454466
return new Rect(left, top, left + tileSize, top + tileSize);
455467
}
456468

469+
/**
470+
* Returns current tile locations. Useful for preserving state when
471+
* orientation changes.
472+
*
473+
* @return current tile locations
474+
*/
475+
public LinkedList<Integer> getTileOrder() {
476+
LinkedList<Integer> tileLocations = new LinkedList<Integer>();
477+
for (int rowI = 0; rowI < GRID_SIZE; rowI++) {
478+
for (int colI = 0; colI < GRID_SIZE; colI++) {
479+
TileView tile = getTileAtCoordinate(new Coordinate(rowI, colI));
480+
tileLocations.add(tile.originalIndex);
481+
}
482+
}
483+
return tileLocations;
484+
}
485+
486+
/**
487+
* Sets tile locations from previous state.
488+
*
489+
* @param tileLocations list of integers marking order
490+
*/
491+
public void setTileOrder(LinkedList<Integer> tileLocations) {
492+
this.tileOrder = tileLocations;
493+
}
494+
457495
/**
458496
* Describes movement of the tile. It is used to move several tiles at once.
459497
*/

src/cz/destil/sliderpuzzle/ui/MainActivity.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package cz.destil.sliderpuzzle.ui;
22

3+
import java.util.LinkedList;
4+
35
import android.content.Intent;
46
import android.os.Bundle;
7+
import android.util.Log;
58

69
import com.actionbarsherlock.app.SherlockActivity;
710
import com.actionbarsherlock.view.Menu;
@@ -19,10 +22,20 @@
1922
*/
2023
public class MainActivity extends SherlockActivity {
2124

25+
private GameBoardView gameBoard;
26+
2227
@Override
2328
public void onCreate(Bundle savedInstanceState) {
2429
super.onCreate(savedInstanceState);
2530
setContentView(R.layout.activity_main);
31+
gameBoard = (GameBoardView) findViewById(R.id.gameboard);
32+
// use preserved tile locations when orientation changed
33+
@SuppressWarnings({ "deprecation", "unchecked" })
34+
final LinkedList<Integer> tileOrder = (LinkedList<Integer>) getLastNonConfigurationInstance();
35+
if (tileOrder != null) {
36+
Log.d("tile locations",tileOrder.toString());
37+
gameBoard.setTileOrder(tileOrder);
38+
}
2639
}
2740

2841
@Override
@@ -36,8 +49,8 @@ public boolean onCreateOptionsMenu(Menu menu) {
3649
public boolean onOptionsItemSelected(MenuItem item) {
3750
switch (item.getItemId()) {
3851
case R.id.new_game:
39-
GameboardView gameboard = (GameboardView) findViewById(R.id.gameboard);
40-
gameboard.fillTiles();
52+
gameBoard.setTileOrder(null);
53+
gameBoard.fillTiles();
4154
return true;
4255
case R.id.about:
4356
startActivity(new Intent(this, AboutActivity.class));
@@ -47,5 +60,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
4760
}
4861
}
4962

50-
// TODO: preserve state when rotated
63+
@Override
64+
public Object onRetainNonConfigurationInstance() {
65+
// preserve state when rotated
66+
Log.d("tile locations",gameBoard.getTileOrder().toString());
67+
return gameBoard.getTileOrder();
68+
}
5169
}

src/cz/destil/sliderpuzzle/util/TileSlicer.java

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package cz.destil.sliderpuzzle.util;
22

3-
import java.util.ArrayList;
4-
import java.util.Random;
3+
import java.util.Collections;
4+
import java.util.LinkedList;
5+
import java.util.List;
56

67
import android.content.Context;
78
import android.graphics.Bitmap;
@@ -26,8 +27,9 @@ public class TileSlicer {
2627
public static final int RANDOM_SLICE = -1;
2728
private Bitmap original;
2829
private int tileSize, gridSize;
29-
private ArrayList<Bitmap> slices;
30-
private Random random;
30+
private List<Bitmap> slices;
31+
private int lastSliceServed;
32+
private List<Integer> sliceOrder;
3133
private Context context;
3234

3335
/**
@@ -44,8 +46,7 @@ public TileSlicer(Bitmap original, int gridSize, Context context) {
4446
this.gridSize = gridSize;
4547
this.tileSize = original.getWidth() / gridSize;
4648
this.context = context;
47-
random = new Random();
48-
slices = new ArrayList<Bitmap>();
49+
slices = new LinkedList<Bitmap>();
4950
sliceOriginal();
5051
}
5152

@@ -55,32 +56,66 @@ public TileSlicer(Bitmap original, int gridSize, Context context) {
5556
private void sliceOriginal() {
5657
int x, y;
5758
Bitmap bitmap;
59+
lastSliceServed = 0;
5860
for (int rowI = 0; rowI < gridSize; rowI++) {
5961
for (int colI = 0; colI < gridSize; colI++) {
6062
// don't slice last part - empty slice
6163
if (rowI == gridSize - 1 && colI == gridSize - 1) {
6264
continue;
65+
} else {
66+
x = rowI * tileSize;
67+
y = colI * tileSize;
68+
// slice
69+
bitmap = Bitmap.createBitmap(original, x, y, tileSize, tileSize);
70+
// draw border lines
71+
Canvas canvas = new Canvas(bitmap);
72+
Paint paint = new Paint();
73+
paint.setColor(Color.parseColor("#fbfdff"));
74+
int end = tileSize - 1;
75+
canvas.drawLine(0, 0, 0, end, paint);
76+
canvas.drawLine(0, end, end, end, paint);
77+
canvas.drawLine(end, end, end, 0, paint);
78+
canvas.drawLine(end, 0, 0, 0, paint);
79+
slices.add(bitmap);
6380
}
64-
x = rowI * tileSize;
65-
y = colI * tileSize;
66-
// slice
67-
bitmap = Bitmap.createBitmap(original, x, y, tileSize, tileSize);
68-
// draw border lines
69-
Canvas canvas = new Canvas(bitmap);
70-
Paint paint = new Paint();
71-
paint.setColor(Color.parseColor("#fbfdff"));
72-
int end = tileSize - 1;
73-
canvas.drawLine(0, 0, 0, end, paint);
74-
canvas.drawLine(0, end, end, end, paint);
75-
canvas.drawLine(end, end, end, 0, paint);
76-
canvas.drawLine(end, 0, 0, 0, paint);
77-
slices.add(bitmap);
7881
}
7982
}
8083
// remove original bitmap from memory
8184
original = null;
8285
}
8386

87+
/**
88+
* Randomizes slices in case no previous instance is available.
89+
*/
90+
public void randomizeSlices() {
91+
// randomize first 15 slices
92+
Collections.shuffle(slices);
93+
// last one is empty slice
94+
slices.add(null);
95+
sliceOrder = null;
96+
}
97+
98+
/**
99+
* Sets slice order in case of previous instance is available, eg. from
100+
* screen rotation.
101+
*
102+
* @param order
103+
* list of integers marking order of slices
104+
*/
105+
public void setSliceOrder(List<Integer> order) {
106+
List<Bitmap> newSlices = new LinkedList<Bitmap>();
107+
for (int o : order) {
108+
if (o < slices.size()) {
109+
newSlices.add(slices.get(o));
110+
} else {
111+
// empty slice
112+
newSlices.add(null);
113+
}
114+
}
115+
sliceOrder = order;
116+
slices = newSlices;
117+
}
118+
84119
/**
85120
* Serves slice and frees it from memory
86121
*
@@ -90,18 +125,21 @@ private void sliceOriginal() {
90125
* @return TileView with the image or empty tile if there are no such
91126
* slices.
92127
*/
93-
public TileView getSlice(int index) {
128+
public TileView getTile() {
94129
TileView tile = null;
95130
if (slices.size() > 0) {
96-
if (index == RANDOM_SLICE) {
97-
index = random.nextInt(slices.size());
131+
int originalIndex;
132+
if (sliceOrder == null) {
133+
originalIndex = lastSliceServed++;
134+
} else {
135+
originalIndex = sliceOrder.get(lastSliceServed++);
136+
}
137+
tile = new TileView(context, originalIndex);
138+
if (slices.get(0) == null) {
139+
// empty slice
140+
tile.setEmpty(true);
98141
}
99-
tile = new TileView(context, index);
100-
tile.setImageBitmap(slices.remove(index));
101-
} else {
102-
// empty slice
103-
tile = new TileView(context, index);
104-
tile.setEmpty(true);
142+
tile.setImageBitmap(slices.remove(0));
105143
}
106144
return tile;
107145
}

0 commit comments

Comments
 (0)