Missig files from the 'Working Version'.
This commit is contained in:
@@ -7,19 +7,24 @@
|
||||
android:targetSdkVersion="14"/>
|
||||
<application android:label="@string/app_name"
|
||||
android:name="org.dyndns.vahagn.sokoban.App"
|
||||
android:theme="@android:style/Theme.Light">
|
||||
<activity android:name="org.dyndns.vahagn.sokoban.SokobanMenu"
|
||||
android:label="@string/app_name">
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme">
|
||||
<activity android:name="org.dyndns.vahagn.sokoban.MainMenu"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="portrait" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="org.dyndns.vahagn.sokoban.PlayActivity"
|
||||
android:label="@string/play_activity">
|
||||
<activity android:name="org.dyndns.vahagn.sokoban.play.PlayActivity"
|
||||
android:label="@string/play_activity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="portrait" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.dyndns.vahagn.sokoban.SokobanMenu" />
|
||||
android:value="org.dyndns.vahagn.sokoban.MainMenu" />
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -21,8 +21,8 @@ protected:
|
||||
empty = 0,
|
||||
wall,
|
||||
box,
|
||||
hole,
|
||||
box_in_hole,
|
||||
goal,
|
||||
box_in_goal,
|
||||
worker
|
||||
};
|
||||
|
||||
@@ -69,10 +69,10 @@ public:
|
||||
*it++ = box;
|
||||
break;
|
||||
case '.':
|
||||
*it++ = hole;
|
||||
*it++ = goal;
|
||||
break;
|
||||
case '*':
|
||||
*it++ = box_in_hole;
|
||||
*it++ = box_in_goal;
|
||||
break;
|
||||
case '@':
|
||||
*it++ = worker;
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/splash"
|
||||
>
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<GridView
|
||||
android:id="@+id/puzzle_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:horizontalSpacing="2mm"
|
||||
android:verticalSpacing="2mm"
|
||||
android:columnWidth="10mm"
|
||||
android:numColumns="auto_fit"
|
||||
android:stretchMode="columnWidth"
|
||||
android:gravity="center" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start"
|
||||
@@ -14,5 +22,6 @@
|
||||
android:onClick="onStartCurrentPuzzle"
|
||||
android:text="Start" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
package org.dyndns.vahagn.sokoban;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
public class App extends Application {
|
||||
public class App extends Application
|
||||
{
|
||||
public static final String TAG = "Sokoban";
|
||||
public static final String PREFS = "org.dyndns.vahagn.sokoban.prefs";
|
||||
static final int MIN_LEVEL = 1;
|
||||
|
||||
private static App mApp = null;
|
||||
protected PuzzleContainer pc;
|
||||
public int level;
|
||||
protected int current_level;
|
||||
protected int achieved_level;
|
||||
protected int max_level;
|
||||
protected SharedPreferences prefs;
|
||||
protected SharedPreferences.Editor prefsEdit;
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -17,21 +29,82 @@ public class App extends Application {
|
||||
super.onCreate();
|
||||
mApp = this;
|
||||
pc = new PuzzleContainer();
|
||||
level = 0;
|
||||
prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
|
||||
prefsEdit = prefs.edit();
|
||||
max_level = pc.getCount();
|
||||
current_level = prefs.getInt("current_level", MIN_LEVEL);
|
||||
achieved_level = prefs.getInt("achieved_level", MIN_LEVEL);
|
||||
}
|
||||
|
||||
//
|
||||
// This is a singleton object.
|
||||
//
|
||||
public static App theApp()
|
||||
{
|
||||
return mApp;
|
||||
}
|
||||
|
||||
public PuzzleContainer getPuzzleContainer()
|
||||
//
|
||||
// Puzzles.
|
||||
//
|
||||
public Puzzle getPuzzle( int level )
|
||||
{
|
||||
return pc;
|
||||
return pc.getPuzzle( level-1 );
|
||||
}
|
||||
|
||||
public Puzzle getCurrentPuzzle()
|
||||
{
|
||||
return getPuzzleContainer().getPuzzle( level );
|
||||
return getPuzzle( getCurrentLevel() );
|
||||
}
|
||||
//
|
||||
// Provide amount of puzzles.
|
||||
//
|
||||
public final int getPuzzleCount()
|
||||
{
|
||||
return max_level;
|
||||
}
|
||||
//
|
||||
// Provide highest solved puzzle.
|
||||
//
|
||||
public final int getAchivedLevel()
|
||||
{
|
||||
return achieved_level;
|
||||
}
|
||||
//
|
||||
// Provide last played puzzle.
|
||||
//
|
||||
public final int getCurrentLevel()
|
||||
{
|
||||
return current_level;
|
||||
}
|
||||
//
|
||||
// Set the current puzzle level. It deons't alter
|
||||
//
|
||||
public void setCurrentLevel( int l )
|
||||
{
|
||||
if ( current_level != l )
|
||||
{
|
||||
current_level = l;
|
||||
prefsEdit.putInt("current_level", current_level);
|
||||
prefsEdit.apply();
|
||||
if ( !prefs.edit().commit() )
|
||||
Log.d(TAG, "prefs.edit().commit() failed.");
|
||||
}
|
||||
}
|
||||
//
|
||||
// Advances current level. It also reviews achived level if the
|
||||
// new level is bigger than achieved level.
|
||||
//
|
||||
public void advanceCurrentLevel()
|
||||
{
|
||||
int new_level = current_level+1;
|
||||
if ( new_level == max_level )
|
||||
new_level = MIN_LEVEL;
|
||||
if ( new_level > achieved_level )
|
||||
{
|
||||
achieved_level = new_level;
|
||||
prefsEdit.putInt("achieved_level", achieved_level);
|
||||
// Don't call apply() here since the call below
|
||||
// to setCurrentLevel() will do that.
|
||||
}
|
||||
setCurrentLevel(new_level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +1,132 @@
|
||||
package org.dyndns.vahagn.sokoban;
|
||||
|
||||
import org.dyndns.vahagn.sokoban.play.PlayActivity;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import static org.dyndns.vahagn.sokoban.App.theApp;
|
||||
|
||||
public class SokobanMenu extends Activity
|
||||
public class MainMenu extends Activity
|
||||
{
|
||||
protected final String TAG = "SokobanMenu";
|
||||
protected final String LEVEL= "org.dyndns.vahagn.sokoban.LEVEL";
|
||||
protected GridView puzzle_grid;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
Log.d(TAG, "onCreate: " + savedInstanceState );
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.menu);
|
||||
|
||||
try {
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
puzzle_grid = (GridView)findViewById(R.id.puzzle_grid);
|
||||
puzzle_grid.setAdapter( new PuzzlesAdapter(this) );
|
||||
//puzzle_grid.addView(puzzle_grid);
|
||||
puzzle_grid.setOnItemClickListener(new OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
|
||||
{
|
||||
onPuzzleClicked(v,(int)id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class PuzzlesAdapter extends BaseAdapter
|
||||
{
|
||||
private Context mContext;
|
||||
private int icon_size;
|
||||
private int text_x;
|
||||
private int text_y;
|
||||
private Bitmap lock_icon;
|
||||
private Bitmap unlock_icon;
|
||||
private Paint paint;
|
||||
|
||||
public PuzzlesAdapter(Context c)
|
||||
{
|
||||
mContext = c;
|
||||
icon_size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 10, getResources().getDisplayMetrics() );
|
||||
int text_size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 4, getResources().getDisplayMetrics() );
|
||||
text_x = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 9, getResources().getDisplayMetrics() );
|
||||
text_y = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 9, getResources().getDisplayMetrics() );
|
||||
|
||||
Bitmap lock_icon_tmp = BitmapFactory.decodeResource( getResources(), R.drawable.lock );
|
||||
lock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888);
|
||||
Canvas lock_canvas = new Canvas(lock_icon);
|
||||
lock_canvas.drawBitmap(lock_icon_tmp,
|
||||
new Rect(0,0,lock_icon_tmp.getWidth()-1,lock_icon_tmp.getHeight()-1),
|
||||
new Rect(0,0,icon_size, icon_size),
|
||||
null);
|
||||
|
||||
Bitmap unlock_icon_tmp = BitmapFactory.decodeResource( getResources(), R.drawable.unlock );
|
||||
unlock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888);
|
||||
Canvas unlock_canvas = new Canvas(unlock_icon);
|
||||
unlock_canvas.drawBitmap(unlock_icon_tmp,
|
||||
new Rect(0,0,unlock_icon_tmp.getWidth()-1,unlock_icon_tmp.getHeight()-1),
|
||||
new Rect(0,0,icon_size, icon_size),
|
||||
null);
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor( Color.WHITE );
|
||||
paint.setTextSize( text_size );
|
||||
paint.setTextAlign(Paint.Align.RIGHT);
|
||||
}
|
||||
|
||||
public int getCount()
|
||||
{
|
||||
return theApp().getPuzzleCount();
|
||||
}
|
||||
|
||||
public Object getItem(int position)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getItemId(int position)
|
||||
{
|
||||
return position+1;
|
||||
}
|
||||
|
||||
// create a new ImageView for each item referenced by the Adapter
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
ImageView imageView;
|
||||
if (convertView == null)
|
||||
{ // if it's not recycled, initialize some attributes
|
||||
imageView = new ImageView(mContext);
|
||||
imageView.setLayoutParams(new GridView.LayoutParams(icon_size, icon_size));
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
// imageView.setPadding(8, 8, 8, 8);
|
||||
}
|
||||
else
|
||||
imageView = (ImageView) convertView;
|
||||
|
||||
int id = (int)getItemId(position);
|
||||
Bitmap icon = ( id <= theApp().getAchivedLevel() )
|
||||
? unlock_icon.copy(Bitmap.Config.ARGB_8888,true)
|
||||
: lock_icon.copy(Bitmap.Config.ARGB_8888,true);
|
||||
Canvas canvas = new Canvas(icon);
|
||||
canvas.drawText( Integer.toString(id), text_x, text_y, paint);
|
||||
imageView.setImageBitmap(icon);
|
||||
return imageView;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,11 +185,20 @@ public class SokobanMenu extends Activity
|
||||
// setContentView(R.layout-l.menu);
|
||||
}
|
||||
|
||||
public void onStartCurrentPuzzle( View v)
|
||||
public void onStartCurrentPuzzle(View v)
|
||||
{
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
|
||||
startActivity( intent );
|
||||
Log.d(TAG, "onStartCurrentPuzzle: " );
|
||||
}
|
||||
|
||||
public void onPuzzleClicked(View v, int level )
|
||||
{
|
||||
if ( level <= theApp().getAchivedLevel() )
|
||||
{
|
||||
theApp().setCurrentLevel(level);
|
||||
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
startActivity( intent );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,73 +2,51 @@ package org.dyndns.vahagn.sokoban;
|
||||
|
||||
//import java.lang.Exception;
|
||||
import java.io.*;
|
||||
import static java.lang.Math.*;
|
||||
import android.util.Log;
|
||||
import android.graphics.Point;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import static org.dyndns.vahagn.sokoban.App.TAG;
|
||||
|
||||
public class Puzzle
|
||||
{
|
||||
public enum symbole
|
||||
{
|
||||
FLOOR,
|
||||
WALL,
|
||||
BOX,
|
||||
HOLE,
|
||||
BOX_IN_HOLE,
|
||||
WORKER;
|
||||
public final static int FLOOR = 0x0;
|
||||
public final static int GOAL = 0x1;
|
||||
public final static int FLOOR_MASK = ~(GOAL | FLOOR);
|
||||
public final static int WALL = 0x2;
|
||||
public final static int BOX = 0x4;
|
||||
public final static int BINGO = BOX | GOAL;
|
||||
public final static int WORKER = 0x8;
|
||||
public final static int WORKER_NORTH = 0x00 | WORKER;
|
||||
public final static int WORKER_SOUTH = 0x10 | WORKER;
|
||||
public final static int WORKER_WEST = 0x20 | WORKER;
|
||||
public final static int WORKER_EAST = 0x30 | WORKER;
|
||||
public final static int WORKER_MASK = WORKER_EAST | WORKER_WEST | WORKER_SOUTH | WORKER_NORTH;
|
||||
public final static int SELECTED = 0x40;
|
||||
public final static int MAX_COUNT = 0x80-1;
|
||||
|
||||
public static int MAX_COUNT()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
};
|
||||
|
||||
protected static final String TAG = "Puzzle";
|
||||
protected int columns;
|
||||
protected int rows;
|
||||
protected symbole [] board;
|
||||
protected int box_count;
|
||||
|
||||
protected int [] board;
|
||||
protected int worker_x;
|
||||
protected int worker_y;
|
||||
protected int selected_x;
|
||||
protected int selected_y;
|
||||
protected int bingos;
|
||||
|
||||
public Puzzle( InputStream is )
|
||||
{
|
||||
load( is );
|
||||
}
|
||||
|
||||
private void load( InputStream is )
|
||||
{try{
|
||||
columns = is.read();
|
||||
rows = is.read();
|
||||
byte [] b = new byte [columns*rows];
|
||||
board = new symbole[columns*rows];
|
||||
is.read( b, 0, columns*rows);
|
||||
for( int i = 0; i < b.length; ++i )
|
||||
{
|
||||
switch( b[i] )
|
||||
{
|
||||
case 0:
|
||||
board[i] = symbole.FLOOR;
|
||||
break;
|
||||
case 1:
|
||||
board[i] = symbole.WALL;
|
||||
break;
|
||||
case 2:
|
||||
board[i] = symbole.BOX;
|
||||
break;
|
||||
case 3:
|
||||
board[i] = symbole.HOLE;
|
||||
break;
|
||||
case 4:
|
||||
board[i] = symbole.BOX_IN_HOLE;
|
||||
break;
|
||||
case 5:
|
||||
board[i] = symbole.WORKER;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Log.d( TAG, "load()", e);
|
||||
}}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Low level helper functions.
|
||||
//
|
||||
|
||||
public final int getColumnCount()
|
||||
{
|
||||
@@ -80,15 +58,347 @@ public class Puzzle
|
||||
}
|
||||
public static int getSymCount()
|
||||
{
|
||||
return symbole.MAX_COUNT();
|
||||
return MAX_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* r- row
|
||||
* c- column
|
||||
*/
|
||||
public final symbole getSym( int r, int c )
|
||||
public final int getIndex( int x, int y )
|
||||
{
|
||||
return board[r*columns+c];
|
||||
return y*columns+x;
|
||||
}
|
||||
public final int getX( int idx )
|
||||
{
|
||||
return idx % columns;
|
||||
}
|
||||
public final int getY( int idx )
|
||||
{
|
||||
return idx / columns;
|
||||
}
|
||||
|
||||
public final int getSym( int x, int y )
|
||||
{
|
||||
return board[getIndex(x,y)];
|
||||
}
|
||||
public void setSym( int x, int y, int v )
|
||||
{
|
||||
board[getIndex(x,y)]=v;
|
||||
}
|
||||
|
||||
public static boolean isEmpty( int v )
|
||||
{
|
||||
return (v & FLOOR_MASK) == 0;
|
||||
}
|
||||
public static boolean hasBox( int v )
|
||||
{
|
||||
return (v & BOX) != 0;
|
||||
}
|
||||
public static boolean hasWorker( int v )
|
||||
{
|
||||
return (v & WORKER) != 0;
|
||||
}
|
||||
|
||||
public final int getWorkerX()
|
||||
{
|
||||
return worker_x;
|
||||
}
|
||||
|
||||
public final int getWorkerY()
|
||||
{
|
||||
return worker_y;
|
||||
}
|
||||
|
||||
public final boolean isSelected()
|
||||
{
|
||||
return selected_x != -1;
|
||||
}
|
||||
|
||||
public final boolean isSelected( int x, int y )
|
||||
{
|
||||
return selected_x == x && selected_y == y;
|
||||
}
|
||||
|
||||
public final int getSelectedX()
|
||||
{
|
||||
return selected_x;
|
||||
}
|
||||
|
||||
public final int getSelectedY()
|
||||
{
|
||||
return selected_y;
|
||||
}
|
||||
|
||||
public final boolean isValid( int x, int y )
|
||||
{
|
||||
return ( 0 <= x && 0 <= y
|
||||
&& x < getColumnCount()
|
||||
&& y < getRowCount() );
|
||||
}
|
||||
|
||||
public final boolean isOneStep( int x, int y )
|
||||
{
|
||||
return isValid(x,y)
|
||||
&& (abs(worker_x-x )+abs(worker_y-y) == 1);
|
||||
}
|
||||
|
||||
public final boolean isDone()
|
||||
{
|
||||
return bingos == box_count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Loading.
|
||||
//
|
||||
private void load( InputStream is )
|
||||
{try{
|
||||
columns = is.read();
|
||||
rows = is.read();
|
||||
box_count = 0;
|
||||
bingos = 0;
|
||||
selected_x = -1;
|
||||
selected_y = -1;
|
||||
board = new int[columns*rows];
|
||||
byte [] b = new byte [columns*rows];
|
||||
is.read( b, 0, columns*rows);
|
||||
for( int i = 0; i < b.length; ++i )
|
||||
{
|
||||
switch( b[i] )
|
||||
{
|
||||
case 0:
|
||||
board[i] = FLOOR;
|
||||
break;
|
||||
case 1:
|
||||
board[i] = WALL;
|
||||
break;
|
||||
case 2:
|
||||
board[i] = BOX;
|
||||
++box_count;
|
||||
break;
|
||||
case 3:
|
||||
board[i] = GOAL;
|
||||
break;
|
||||
case 4:
|
||||
board[i] = BINGO;
|
||||
++box_count;
|
||||
++bingos;
|
||||
break;
|
||||
case 5:
|
||||
board[i] = WORKER;
|
||||
worker_x = getX(i);
|
||||
worker_y = getY(i);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Log.d( TAG, "load()", e);
|
||||
}}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Move worker.
|
||||
//
|
||||
|
||||
public boolean walk( int x, int y)
|
||||
{
|
||||
//
|
||||
// Check that this is one step away.
|
||||
//
|
||||
if ( !isOneStep(x,y) )
|
||||
return false;
|
||||
//
|
||||
// Check that this is empty space.
|
||||
//
|
||||
int v = getSym(x,y);
|
||||
if ( !isEmpty(v) )
|
||||
return false;
|
||||
//
|
||||
// If something is selected then unselect first.
|
||||
//
|
||||
if ( isSelected() )
|
||||
unselect();
|
||||
//
|
||||
// Find direction to move.
|
||||
//
|
||||
int worker;
|
||||
if ( worker_x < x )
|
||||
worker = WORKER_WEST;
|
||||
else if ( worker_x > x )
|
||||
worker = WORKER_EAST;
|
||||
else if ( worker_y > y )
|
||||
worker = WORKER_SOUTH;
|
||||
else
|
||||
worker = WORKER_NORTH;
|
||||
//
|
||||
// Move worker marker from current position to asked position.
|
||||
//
|
||||
setSym(worker_x,worker_y,getSym(worker_x,worker_y)&~WORKER_MASK);
|
||||
worker_x =x;
|
||||
worker_y =y;
|
||||
setSym(worker_x,worker_y,getSym(worker_x,worker_y)|worker);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean select( int x, int y)
|
||||
{
|
||||
//
|
||||
// Check that this is one step away.
|
||||
//
|
||||
if ( !isOneStep(x,y) )
|
||||
return false;
|
||||
//
|
||||
// Check that this is empty space.
|
||||
//
|
||||
int v = getSym(x,y);
|
||||
if ( !hasBox(v) )
|
||||
return false;
|
||||
//
|
||||
// If something is selected then unselect first.
|
||||
//
|
||||
if ( isSelected() )
|
||||
unselect();
|
||||
//
|
||||
// Find direction to move.
|
||||
//
|
||||
int worker;
|
||||
if ( worker_x < x )
|
||||
worker = WORKER_WEST;
|
||||
else if ( worker_x > x )
|
||||
worker = WORKER_EAST;
|
||||
else if ( worker_y > y )
|
||||
worker = WORKER_SOUTH;
|
||||
else
|
||||
worker = WORKER_NORTH;
|
||||
//
|
||||
// Move worker marker from current position to asked position.
|
||||
//
|
||||
selected_x =x;
|
||||
selected_y =y;
|
||||
setSym(worker_x,worker_y,getSym(worker_x,worker_y)&~WORKER_MASK|worker|SELECTED);
|
||||
setSym(selected_x,selected_y,getSym(selected_x,selected_y)|SELECTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean unselect()
|
||||
{
|
||||
//
|
||||
// If not selected then do nothing.
|
||||
//
|
||||
if ( !isSelected() )
|
||||
return false;
|
||||
//
|
||||
// Move worker marker from current position to asked position.
|
||||
//
|
||||
setSym(worker_x,worker_y,getSym(worker_x,worker_y)&~SELECTED);
|
||||
setSym(selected_x,selected_y,getSym(selected_x,selected_y)&~SELECTED);
|
||||
selected_x =-1;
|
||||
selected_y =-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean push(int x, int y)
|
||||
{
|
||||
//
|
||||
// If not selected then do nothing.
|
||||
//
|
||||
if ( !isSelected() )
|
||||
return false;
|
||||
//
|
||||
// Check that we go to the selected direction.
|
||||
//
|
||||
if ( selected_x != x && selected_y != y )
|
||||
return false;
|
||||
//
|
||||
// Check that this is a box that we move.
|
||||
//
|
||||
int v = getSym(x,y);
|
||||
if ( !hasBox(v) )
|
||||
return false;
|
||||
//
|
||||
// Check that the next space to the box is empty.
|
||||
//w - 2*(w-x) = 2x -w
|
||||
int next_x = 2*x - worker_x;
|
||||
int next_y = 2*y - worker_y;
|
||||
int next_v = getSym(next_x,next_y);
|
||||
if ( !isEmpty(next_v) )
|
||||
return false;
|
||||
//
|
||||
// Ok, looks we can move the box. Do it actually.
|
||||
//
|
||||
unselect();
|
||||
setSym(x,y,getSym(x,y)&~BOX);
|
||||
setSym(next_x,next_y,getSym(next_x,next_y)|BOX);
|
||||
walk(x,y);
|
||||
select(next_x,next_y);
|
||||
//
|
||||
// Keep track of box count in place.
|
||||
//
|
||||
if ( (v & GOAL) != 0 )
|
||||
--bingos;
|
||||
if ( (next_v & GOAL) != 0 )
|
||||
++bingos;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Undo/Redo.
|
||||
//
|
||||
|
||||
protected class State
|
||||
{
|
||||
public int [] board;
|
||||
public int worker_x;
|
||||
public int worker_y;
|
||||
public int selected_x;
|
||||
public int selected_y;
|
||||
public int bingos;
|
||||
|
||||
public State(Puzzle puzzle)
|
||||
{
|
||||
board = puzzle.board.clone();
|
||||
worker_x = puzzle.worker_x;
|
||||
worker_y = puzzle.worker_y;
|
||||
selected_x = puzzle.selected_x;
|
||||
selected_y = puzzle.selected_y;
|
||||
bingos = puzzle.bingos;
|
||||
}
|
||||
|
||||
public void restore(Puzzle puzzle)
|
||||
{
|
||||
puzzle.board = board;
|
||||
puzzle.worker_x = worker_x;
|
||||
puzzle.worker_y = worker_y;
|
||||
puzzle.selected_x = selected_x;
|
||||
puzzle.selected_y = selected_y;
|
||||
puzzle.bingos = bingos;
|
||||
}
|
||||
}
|
||||
protected LinkedList<State> undoStack = new LinkedList<State>();
|
||||
|
||||
//
|
||||
// Save this state to be able to restore later.
|
||||
//
|
||||
public void save()
|
||||
{
|
||||
State s = new State(this);
|
||||
undoStack.addFirst(s);
|
||||
}
|
||||
//
|
||||
// Restore state.
|
||||
//
|
||||
public void restore()
|
||||
{
|
||||
State s = undoStack.removeFirst();
|
||||
if ( s != null )
|
||||
s.restore(this);
|
||||
}
|
||||
//
|
||||
// Check if there are items in the undo stack.
|
||||
//
|
||||
public final boolean isUndoable()
|
||||
{
|
||||
return undoStack.size() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import android.util.Log;
|
||||
|
||||
public class PuzzleContainer
|
||||
{
|
||||
protected final String TAG = "PuzzleContainer";
|
||||
|
||||
protected int count;
|
||||
|
||||
/*
|
||||
@@ -41,11 +39,13 @@ public class PuzzleContainer
|
||||
}
|
||||
catch ( java.lang.Exception e )
|
||||
{
|
||||
Log.d(TAG, "Exception: " + e.getMessage() );
|
||||
//Log.d(TAG, "Exception: " + e.getMessage() );
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}}
|
||||
|
||||
//
|
||||
// Retrive amount of puzzles.
|
||||
//
|
||||
public int getCount()
|
||||
{try{
|
||||
if ( count == 0 )
|
||||
@@ -57,11 +57,13 @@ public class PuzzleContainer
|
||||
}
|
||||
catch ( java.lang.Exception e )
|
||||
{
|
||||
Log.d(TAG, "Exception: " + e.getMessage() );
|
||||
//Log.d(TAG, "Exception: " + e.getMessage() );
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}}
|
||||
|
||||
//
|
||||
// Helper function to read little endian 32bit integer.
|
||||
//
|
||||
protected int read_i32( InputStream is ) throws IOException
|
||||
{
|
||||
int i = is.read();
|
||||
|
||||
Reference in New Issue
Block a user