From: gitknilch Date: Sun, 24 Feb 2013 19:54:27 +0000 (+0100) Subject: rename, add hdpi icons, cleanup some warnings X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/FreeShisen/commitdiff_plain/d0e04237b00df7c11616f359200255a8b47e79d7?hp=b023eec723db5ee6d0a6a6aca7795c391d98377e rename, add hdpi icons, cleanup some warnings --- diff --git a/.classpath b/.classpath index 6c635c0..835b375 100644 --- a/.classpath +++ b/.classpath @@ -2,6 +2,7 @@ - + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6de4e1e..a517c81 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,13 +1,13 @@ - + android:versionName="0.1"> + + android:name=".ShisenSho" android:allowBackup="true"> @@ -19,7 +19,7 @@ android:name=".ShisenShoOptionsActivity" android:screenOrientation="landscape"> - + diff --git a/artwork/logo.png b/artwork/logo.png deleted file mode 100644 index b5d6a6d..0000000 Binary files a/artwork/logo.png and /dev/null differ diff --git a/artwork/screenshots/device-2013-01-16-011637.png b/artwork/screenshots/device-2013-01-16-011637.png deleted file mode 100644 index 75205c2..0000000 Binary files a/artwork/screenshots/device-2013-01-16-011637.png and /dev/null differ diff --git a/artwork/screenshots/device-2013-01-16-011744.png b/artwork/screenshots/device-2013-01-16-011744.png deleted file mode 100644 index 7fe59be..0000000 Binary files a/artwork/screenshots/device-2013-01-16-011744.png and /dev/null differ diff --git a/artwork/screenshots/device-2013-01-16-011805.png b/artwork/screenshots/device-2013-01-16-011805.png deleted file mode 100644 index ea4a108..0000000 Binary files a/artwork/screenshots/device-2013-01-16-011805.png and /dev/null differ diff --git a/artwork/screenshots/device-2013-01-16-011832.png b/artwork/screenshots/device-2013-01-16-011832.png deleted file mode 100644 index 689939d..0000000 Binary files a/artwork/screenshots/device-2013-01-16-011832.png and /dev/null differ diff --git a/lint.xml b/lint.xml new file mode 100644 index 0000000..ee0eead --- /dev/null +++ b/lint.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/proguard.cfg b/proguard.cfg index 12dd039..4dc32b1 100644 --- a/proguard.cfg +++ b/proguard.cfg @@ -14,15 +14,15 @@ -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService --keepclasseswithmembernames class * { +-keepclasseswithmembers class * { native ; } --keepclasseswithmembernames class * { +-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); } --keepclasseswithmembernames class * { +-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); } diff --git a/project.properties b/project.properties index b7c2081..a3ee5ab 100644 --- a/project.properties +++ b/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-10 +target=android-17 diff --git a/res/drawable-hdpi/tileset.png b/res/drawable-hdpi/tileset.png new file mode 100644 index 0000000..a001c5f Binary files /dev/null and b/res/drawable-hdpi/tileset.png differ diff --git a/res/layout/options.xml b/res/layout/options.xml index 493b173..1c1352f 100644 --- a/res/layout/options.xml +++ b/res/layout/options.xml @@ -25,13 +25,13 @@ - + android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/gravityLabel" android:text="@string/gravity_label" android:layout_marginTop="12dp"> + - + android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/timeCounterLabel" android:text="@string/time_counter_label" android:layout_marginTop="12dp"> + diff --git a/res/values/strings.xml b/res/values/strings.xml index 4011bc8..4b0535b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,6 +1,5 @@ - Hello World, ShisenSho! ShisenSho Clean Hint @@ -8,12 +7,13 @@ Options About \n -(C) 2013 contact.proofofconcept@gmail.com\n +© 2013 knilch. Originally:\n +© 2013 contact.proofofconcept@gmail.com\n Images taken from kshisen (Shisen Sho 1.5.1), from the package kdegames\n -(C) 1997 Mario Weilguni\n +© 1997 Mario Weilguni\n Distributed under GPL v2:\n http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt\n -Get the source code: http://db.tt/Imh8zH4M +Get the source code: TODO Size Difficulty diff --git a/src/de/cwde/shisensho/Board.java b/src/de/cwde/shisensho/Board.java new file mode 100644 index 0000000..140b855 --- /dev/null +++ b/src/de/cwde/shisensho/Board.java @@ -0,0 +1,389 @@ +package de.cwde.shisensho; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class Board { + private static String charpieces = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + public int difficulty=1; // 1=Hard ... N=Easy + public boolean gravity=true; + public int [] boardSize; + public char[][] board; + public LinkedList history; + + // ---------------------- + // Public methods + // ---------------------- + + public Board() { + } + + // The board always has a 1-square width free rectangle that has + // to be taken into account when specifying the size + public void initialize(int sizeI, int sizeJ) { + boardSize = new int[2]; + boardSize[0]=sizeI; + boardSize[1]=sizeJ; + board = new char[boardSize[0]][boardSize[1]]; + for (int i=0;i(); + } + + public static String pieceToString(char piece) { + return charpieces.substring(piece,1); + } + + public static char StringToPiece(String piece) { + char upiece; + long charpiecesLen=charpieces.length(); + for(upiece=0;(upiece0) result+=" "; + result+=""+(j%10); + } + result+="\n "+StringRepeat("--",boardSize[1]); + for (int i=0;i0) result+=" "; + result+=charpieces.substring(board[i][j],board[i][j]+1); + } + result+=" |\n"; + if (i getPairs(int maxResults) { + List result=new ArrayList(); + List pieces=new ArrayList(); + List> piecePoints=new ArrayList>(); + for (int i=0;i points0=new ArrayList(); + points0.add(p); + pieces.add(piece); + piecePoints.add(points0); + + key=pieces.indexOf(piece); + piecePoints.get(key); + } else { + List points1=piecePoints.get(key); + points1.add(p); + } + } + + int nresults=0; + for (List points : piecePoints) { + int n=(int)points.size(); + for (int i=0;i path=getPath(a.copy(),b.copy()); + if (path!=null && path.size()>0) { + result.add(new Line(a,b)); + if (nresults++==maxResults) break; + } + } + if (nresults==maxResults) break; + } + if (nresults==maxResults) break; + } + return result; + } + + public int getNumPieces() { + int result=0; + for (int j=0;j getHorizontalLines(Point excludeA, Point excludeB) { + List result=new ArrayList(); + for (int i=0;i getVerticalLines(Point excludeA, Point excludeB) { + List result=new ArrayList(); + for (int j=0;j0;i--) board[i][p.j]=board[i-1][p.j]; + } + + private void undoGravity(Point p) { + if (gravity) for (int i=0;i=getMin().j && p.j<=getMax().j) + || (p.j==a.j && p.j==b.j && p.i>=getMin().i && p.i<=getMax().i); + } + + public Point cuts(Line l) { + if (isHorizontal() && l.isVertical() + && getMin().j<=l.a.j && getMax().j>=l.a.j + && l.getMin().i<=a.i && l.getMax().i>=a.i ) { + return new Point(a.i,l.a.j); + } else if (isVertical() && l.isHorizontal() + && getMin().i<=l.a.i && getMax().i>=l.a.i + && l.getMin().j<=a.j && l.getMax().j>=a.j ) { + return new Point(l.a.i,a.j); + } else return null; + } + + public Point getMin() { + if (a.ib.i || a.j>b.j) return a; + else return b; + } + + public String toString() { + return a+"-"+b; + } + + public Point a; + public Point b; +} diff --git a/src/de/cwde/shisensho/Move.java b/src/de/cwde/shisensho/Move.java new file mode 100644 index 0000000..28bf071 --- /dev/null +++ b/src/de/cwde/shisensho/Move.java @@ -0,0 +1,17 @@ +package de.cwde.shisensho; + +public class Move { + public Move(Point a, Point b, char piece) { + this.a=a; + this.b=b; + this.piece=piece; + } + + public String toString() { + return a+"-"+b+"("+Board.pieceToString(piece)+")"; + } + + public Point a; + public Point b; + public char piece; +} diff --git a/src/de/cwde/shisensho/Point.java b/src/de/cwde/shisensho/Point.java new file mode 100644 index 0000000..73879cd --- /dev/null +++ b/src/de/cwde/shisensho/Point.java @@ -0,0 +1,30 @@ +package de.cwde.shisensho; + +class Point { + public Point(int i, int j) { + this.i=i; + this.j=j; + } + + public boolean equals(Point p) { + return (i==p.i && j==p.j); + } + + public String toString() { + return "("+i+","+j+")"; + } + + public static Point fromString(String s) { + String[] ij=s.split(",",2); + int i=Integer.parseInt(ij[0]); + int j=Integer.parseInt(ij[1]); + return new Point(i,j); + } + + public int i; + public int j; + + public Point copy() { + return new Point(this.i,this.j); + } +} diff --git a/src/de/cwde/shisensho/ShisenSho.java b/src/de/cwde/shisensho/ShisenSho.java new file mode 100644 index 0000000..8fe7d30 --- /dev/null +++ b/src/de/cwde/shisensho/ShisenSho.java @@ -0,0 +1,117 @@ +package de.cwde.shisensho; + +import android.app.Application; +import android.os.Bundle; +import android.util.Log; + +public class ShisenSho extends Application { + private static ShisenSho instance = null; + private ShisenShoView view = null; + public ShisenShoActivity activity = null; + + public Board board; + public int[] boardSize=new int[2]; + public int difficulty=1; // 1=Hard, 2=Easy + public int size=3; // 1=Small, 2=Medium, 3=Big + public boolean gravity=true; + public boolean timeCounter=true; + + public static void log(String msg) { + Log.w("ShisenSho", msg); + } + + public void newPlay() { + board = new Board(); + board.buildRandomBoard(boardSize[0],boardSize[1],difficulty,gravity); + } + + public void setSize(int s) { + switch (s) { + case 1: + size=1; + boardSize[0]=6+2; + boardSize[1]=8+2; + break; + case 2: + size=2; + boardSize[0]=6+2; + boardSize[1]=12+2; + break; + case 3: + default: + size=3; + boardSize[0]=6+2; + boardSize[1]=16+2; + break; + } + } + + public void sleep(int deciSeconds) { + try { + Thread.sleep(deciSeconds*100); + } catch (InterruptedException e) { } + } + + public ShisenSho() { + instance = this; + setSize(size); + } + + public static synchronized ShisenSho app() { + return instance; + } + + public ShisenShoView getView() { + if (view == null) view = new ShisenShoView(this); + return view; + } + + /** Called when the activity is first created. */ + @Override + public void onCreate() { + super.onCreate(); + } + + public Bundle getOptions() { + Bundle options = new Bundle(); + options.putInt("size", size); + options.putInt("difficulty", difficulty); + options.putBoolean("gravity", gravity); + options.putBoolean("timeCounter", timeCounter); + return options; + } + + public void setOptions(Bundle options) { + int size = options.getInt("size"); + int difficulty = options.getInt("difficulty"); + boolean gravity = options.getBoolean("gravity"); + boolean timeCounter = options.getBoolean("timeCounter"); + + boolean needsReset = false; + + if (size != this.size) { + setSize(size); + needsReset = true; + } + + if (difficulty != this.difficulty) { + this.difficulty = difficulty; + needsReset = true; + } + + if (gravity != this.gravity) { + this.gravity = gravity; + needsReset = true; + } + + if (timeCounter != this.timeCounter) { + this.timeCounter = timeCounter; + view.onTimeCounterActivate(); + } + + if (needsReset) { + view.reset(); + } + } + +} diff --git a/src/de/cwde/shisensho/ShisenShoActivity.java b/src/de/cwde/shisensho/ShisenShoActivity.java new file mode 100644 index 0000000..b87979f --- /dev/null +++ b/src/de/cwde/shisensho/ShisenShoActivity.java @@ -0,0 +1,120 @@ +package de.cwde.shisensho; + +import de.cwde.shisensho.R; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.util.Linkify; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.TextView; + +public class ShisenShoActivity extends Activity { + private ShisenShoView view; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_NO_TITLE); + //getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + // WindowManager.LayoutParams.FLAG_FULLSCREEN); + + view = ShisenSho.app().getView(); + ShisenSho.app().activity = this; + setContentView(view); + } + + @Override + protected void onDestroy() { + ViewGroup vg = (ViewGroup)(view.getParent()); + vg.removeView(view); + ShisenSho.app().activity = null; + super.onDestroy(); + } + + @Override + protected void onPause() { + if (view!=null) { + view.pauseTime(); + } + super.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + if (view!=null) { + view.resumeTime(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle item selection + switch (item.getItemId()) { + case R.id.hint: + case R.id.undo: + case R.id.clean: + return view.onOptionsItemSelected(item); + case R.id.options: + startActivityForResult(new Intent("de.cwde.shisensho.SETTINGS", null), 0); + return true; + case R.id.about: + onAboutActivate(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void onAboutActivate() { + // Try to load the a package matching the name of our own package + PackageInfo pInfo; + try { + pInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA); + String aboutTitle = String.format("About %s", getString(R.string.app_name)); + String versionString = String.format("Version: %s", pInfo.versionName); + String aboutText = getString(R.string.aboutText); + + // Set up the TextView + final TextView message = new TextView(this); + // We'll use a spannablestring to be able to make links clickable + final SpannableString s = new SpannableString(aboutText); + + // Set some padding + message.setPadding(5, 5, 5, 5); + // Set up the final string + message.setText(versionString + "\n" + s); + // Now linkify the text + Linkify.addLinks(message, Linkify.ALL); + + new AlertDialog.Builder(this) + .setTitle(aboutTitle) + .setCancelable(true) + .setIcon(R.drawable.icon) + .setPositiveButton(getString(android.R.string.ok), null) + .setView(message).create() + .show(); + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/src/de/cwde/shisensho/ShisenShoOptionsActivity.java b/src/de/cwde/shisensho/ShisenShoOptionsActivity.java new file mode 100644 index 0000000..9d3ecbb --- /dev/null +++ b/src/de/cwde/shisensho/ShisenShoOptionsActivity.java @@ -0,0 +1,101 @@ +package de.cwde.shisensho; + +import java.io.Serializable; + +import de.cwde.shisensho.R; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.Spinner; +import android.widget.ToggleButton; + +public class ShisenShoOptionsActivity extends Activity { + + Bundle state; + ShisenSho app; + + private void appToState (boolean merge) { + String[] fields = { "size", "difficulty", "gravity", "timeCounter" }; + Bundle options = app.getOptions(); + if (state == null) state = new Bundle(); + for (int i=0; i arg0, View arg1, + int pos, long arg3) { + state.putInt("size", pos+1); + } + + public void onNothingSelected(AdapterView arg0) { } + }); + + s = (Spinner) findViewById(R.id.difficulty); + adapter = ArrayAdapter.createFromResource( + this, R.array.difficulties, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + s.setAdapter(adapter); + s.setSelection(2-state.getInt("difficulty")); + s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView arg0, View arg1, + int pos, long arg3) { + state.putInt("difficulty", 2-pos); + } + + public void onNothingSelected(AdapterView arg0) { } + }); + + tb = (ToggleButton) findViewById(R.id.gravity); + tb.setChecked(state.getBoolean("gravity")); + tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton arg0, boolean arg1) { + state.putBoolean("gravity", arg1); + } + }); + + tb = (ToggleButton) findViewById(R.id.timeCounter); + tb.setChecked(state.getBoolean("timeCounter")); + tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton arg0, boolean arg1) { + state.putBoolean("timeCounter", arg1); + } + }); + } + + @Override + public void onBackPressed() { + app.setOptions(state); + super.onBackPressed(); + } + +} diff --git a/src/de/cwde/shisensho/ShisenShoView.java b/src/de/cwde/shisensho/ShisenShoView.java new file mode 100644 index 0000000..cb1a57c --- /dev/null +++ b/src/de/cwde/shisensho/ShisenShoView.java @@ -0,0 +1,662 @@ +package de.cwde.shisensho; + +import java.util.List; +import java.util.Locale; +import java.util.Timer; +import java.util.TimerTask; + +import de.cwde.shisensho.R; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.Paint.Cap; +import android.graphics.Paint.Join; +import android.graphics.Paint.Style; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.os.Handler; +import android.os.Message; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { + + private enum StatePlay { UNINITIALIZED, IDLE, SELECTED1, SELECTED2, GAMEOVER }; + private enum StatePaint { BOARD, SELECTED1, SELECTED2, MATCHED, WIN, LOSE, HINT, TIME }; + + private int screenWidth; + private int screenHeight; + private int tilesetRows; + private int tilesetCols; + private int tileHeight; + private int tileWidth; + private Bitmap bg; + private Bitmap tile[]; + private int[] selection1=new int[2]; + private int[] selection2=new int[2]; + private List path=null; + private List pairs=null; + private long startTime; + private long playTime; + private long baseTime; + private Timer timer; + private static Handler timerHandler; + + private boolean timerRegistered=false; + private ShisenSho app; + private StatePlay cstate; + private StatePaint pstate; + private Canvas canvas = null; + private SurfaceHolder surfaceHolder = null; + public ShisenShoView(ShisenSho shishenSho) { + super((Context)shishenSho); + this.app = shishenSho; + cstate = StatePlay.UNINITIALIZED; + surfaceHolder = getHolder(); + surfaceHolder.addCallback(this); + } + + private void paint(StatePaint pstate) { + this.pstate=pstate; + repaint(); + } + + private void control(StatePlay cstate) { + this.cstate=cstate; + } + + private void loadTileset() { + BitmapFactory.Options ops = new BitmapFactory.Options(); + ops.inScaled = false; + Bitmap tileset = BitmapFactory.decodeResource(getResources(), R.drawable.tileset, ops); + tileset.setDensity(Bitmap.DENSITY_NONE); + + // The tile set has 4 rows x 9 columns + tilesetRows = 4; + tilesetCols = 9; + tileWidth = tileset.getWidth()/tilesetCols; + tileHeight = tileset.getHeight()/tilesetRows; + tile = new Bitmap[tilesetRows*tilesetCols]; + int k=0; + for (int i=0; i0) { + Line pair=pairs.get(0); + Point a=pair.a; + Point b=pair.b; + path=app.board.getPath(a,b); + paint.setColor(orange); + paint.setStyle(Style.STROKE); + paint.setStrokeCap(Cap.ROUND); + paint.setStrokeJoin(Join.ROUND); + paint.setStrokeWidth(3); + + cbuffer.drawRect(new Rect( + x0+a.j*tileWidth-2, + y0+a.i*tileHeight-2, + x0+a.j*tileWidth-2+tileWidth+2*2, + y0+a.i*tileHeight-2+tileHeight+2*2), + paint); + + if (path!=null) { + Point p0=null; + for (Point p1 : path) { + if (p0!=null) { + cbuffer.drawLine( + x0+p0.j*tileWidth-2+(tileWidth/2), + y0+p0.i*tileHeight-2+(tileHeight/2), + x0+p1.j*tileWidth-2+(tileWidth/2), + y0+p1.i*tileHeight-2+(tileHeight/2), + paint); + } + p0=p1; + } + path=null; + } + + cbuffer.drawRect(new Rect( + x0+b.j*tileWidth-2, + y0+b.i*tileHeight-2, + x0+b.j*tileWidth-2+tileWidth+2*2, + y0+b.i*tileHeight-2+tileHeight+2*2), + paint); + } + break; + } + + // Win & loose notifications + switch (pstate) { + case WIN: + drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"You Win!", "#FFFFFF", 100); + break; + case LOSE: + drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"Game Over", "#FFFFFF", 100); + break; + } + + if (app.timeCounter) switch (pstate) { + case BOARD: + case SELECTED1: + case SELECTED2: + case MATCHED: + case WIN: + case LOSE: + case HINT: + case TIME: + updateTime(); + int hours=(int)(playTime/(60*60)); + int minutes=(int)((playTime/60)%60); + int seconds=(int)(playTime%60); + String time=String.format(Locale.US, "%01d:%02d:%02d", hours, minutes, seconds); + + int timePosX=screenWidth-120; + int timePosY=screenHeight-10; + + drawMessage(cbuffer, timePosX+1,timePosY+1,false,time,"#000000",30); + drawMessage(cbuffer, timePosX,timePosY,false,time,"#FFFFFF",30); + break; + } + + // Debug messages + /* + debugMessage="StatePlay: "+cstate+"\n"+"StatePaint: "+pstate; + if (debugMessage!=null && debugMessage.length()>0) { + int l = 20; + String lines[] = debugMessage.split("\n"); + for (int i=0; i=0 && + i=0 && j=0 && i=0 && j0) { + app.board.play(a,b); + } + path=null; + paint(StatePaint.BOARD); + + pairs=app.board.getPairs(1); + if (pairs.size()==0) { + if (app.board.getNumPieces()==0) { + paint(StatePaint.WIN); + } else { + paint(StatePaint.LOSE); + } + control(StatePlay.GAMEOVER); + } else { + control(StatePlay.IDLE); + } + //undo.sensitive=app.board.getCanUndo(); + } + } + break; + case GAMEOVER: + reset(); + paint(StatePaint.BOARD); + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, + int height) { + surfaceHolder = holder; + if (cstate!=StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) { + registerTimer(); + } + repaint(); + } + + public void surfaceCreated(SurfaceHolder holder) { + surfaceHolder = holder; + repaint(); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + surfaceHolder = null; + if (timerRegistered) { + unregisterTimer(); + } + } + + /* + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (!initialized) initialize(); + + long currTime = System.currentTimeMillis(); + + a = (float)(currTime - startTime) / (float)duration; + if (a > (float)1.0) a = (float)1.0; + + x = Math.round(nextx*a + prevx*(1-a)); + y = Math.round(nexty*a + prevy*(1-a)); + + if (a == (float)1.0) computeNextTarget(); + + int bgWidth = bg.getWidth(); + int bgHeight = bg.getHeight(); + for (int i=0; i history; - - // ---------------------- - // Public methods - // ---------------------- - - public Board() { - } - - // The board always has a 1-square width free rectangle that has - // to be taken into account when specifying the size - public void initialize(int sizeI, int sizeJ) { - boardSize = new int[2]; - boardSize[0]=sizeI; - boardSize[1]=sizeJ; - board = new char[boardSize[0]][boardSize[1]]; - for (int i=0;i(); - } - - public static String pieceToString(char piece) { - return charpieces.substring(piece,1); - } - - public static char StringToPiece(String piece) { - char upiece; - long charpiecesLen=charpieces.length(); - for(upiece=0;(upiece0) result+=" "; - result+=""+(j%10); - } - result+="\n "+StringRepeat("--",boardSize[1]); - for (int i=0;i0) result+=" "; - result+=charpieces.substring(board[i][j],board[i][j]+1); - } - result+=" |\n"; - if (i getPairs(int maxResults) { - List result=new ArrayList(); - List pieces=new ArrayList(); - List> piecePoints=new ArrayList>(); - for (int i=0;i points0=new ArrayList(); - points0.add(p); - pieces.add(piece); - piecePoints.add(points0); - - key=pieces.indexOf(piece); - piecePoints.get(key); - } else { - List points1=piecePoints.get(key); - points1.add(p); - } - } - - int nresults=0; - int k=0; - for (List points : piecePoints) { - int n=(int)points.size(); - for (int i=0;i path=getPath(a.copy(),b.copy()); - if (path!=null && path.size()>0) { - result.add(new Line(a,b)); - if (nresults++==maxResults) break; - } - } - if (nresults==maxResults) break; - } - k++; - if (nresults==maxResults) break; - } - return result; - } - - public int getNumPieces() { - int result=0; - for (int j=0;j getHorizontalLines(Point excludeA, Point excludeB) { - List result=new ArrayList(); - for (int i=0;i getVerticalLines(Point excludeA, Point excludeB) { - List result=new ArrayList(); - for (int j=0;j0;i--) board[i][p.j]=board[i-1][p.j]; - } - - private void undoGravity(Point p) { - if (gravity) for (int i=0;i=getMin().j && p.j<=getMax().j) - || (p.j==a.j && p.j==b.j && p.i>=getMin().i && p.i<=getMax().i); - } - - public Point cuts(Line l) { - if (isHorizontal() && l.isVertical() - && getMin().j<=l.a.j && getMax().j>=l.a.j - && l.getMin().i<=a.i && l.getMax().i>=a.i ) { - return new Point(a.i,l.a.j); - } else if (isVertical() && l.isHorizontal() - && getMin().i<=l.a.i && getMax().i>=l.a.i - && l.getMin().j<=a.j && l.getMax().j>=a.j ) { - return new Point(l.a.i,a.j); - } else return null; - } - - public Point getMin() { - if (a.ib.i || a.j>b.j) return a; - else return b; - } - - public String toString() { - return a+"-"+b; - } - - public Point a; - public Point b; -} diff --git a/src/org/proofofconcept/shisensho/Move.java b/src/org/proofofconcept/shisensho/Move.java deleted file mode 100644 index 1b51289..0000000 --- a/src/org/proofofconcept/shisensho/Move.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.proofofconcept.shisensho; - -public class Move { - public Move(Point a, Point b, char piece) { - this.a=a; - this.b=b; - this.piece=piece; - } - - public String toString() { - return a+"-"+b+"("+Board.pieceToString(piece)+")"; - } - - public Point a; - public Point b; - public char piece; -} diff --git a/src/org/proofofconcept/shisensho/Point.java b/src/org/proofofconcept/shisensho/Point.java deleted file mode 100644 index 7771ef5..0000000 --- a/src/org/proofofconcept/shisensho/Point.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.proofofconcept.shisensho; - -class Point { - public Point(int i, int j) { - this.i=i; - this.j=j; - } - - public boolean equals(Point p) { - return (i==p.i && j==p.j); - } - - public String toString() { - return "("+i+","+j+")"; - } - - public static Point fromString(String s) { - String[] ij=s.split(",",2); - int i=Integer.parseInt(ij[0]); - int j=Integer.parseInt(ij[1]); - return new Point(i,j); - } - - public int i; - public int j; - - public Point copy() { - return new Point(this.i,this.j); - } -} diff --git a/src/org/proofofconcept/shisensho/ShisenSho.java b/src/org/proofofconcept/shisensho/ShisenSho.java deleted file mode 100644 index a7d29b4..0000000 --- a/src/org/proofofconcept/shisensho/ShisenSho.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.proofofconcept.shisensho; - -import java.util.Observable; -import java.util.Observer; - -import android.app.Application; -import android.os.Bundle; -import android.util.Log; - -public class ShisenSho extends Application { - private static ShisenSho instance = null; - private ShisenShoView view = null; - public ShisenShoActivity activity = null; - - public Board board; - public int[] boardSize=new int[2]; - public int difficulty=1; // 1=Hard, 2=Easy - public int size=3; // 1=Small, 2=Medium, 3=Big - public boolean gravity=true; - public boolean timeCounter=true; - - public static void log(String msg) { - Log.w("ShisenSho", msg); - } - - public void newPlay() { - board = new Board(); - board.buildRandomBoard(boardSize[0],boardSize[1],difficulty,gravity); - } - - public void setSize(int s) { - switch (s) { - case 1: - size=1; - boardSize[0]=6+2; - boardSize[1]=8+2; - break; - case 2: - size=2; - boardSize[0]=6+2; - boardSize[1]=12+2; - break; - case 3: - default: - size=3; - boardSize[0]=6+2; - boardSize[1]=16+2; - break; - } - } - - public void sleep(int deciSeconds) { - try { - Thread.sleep(deciSeconds*100); - } catch (InterruptedException e) { } - } - - public ShisenSho() { - instance = this; - setSize(size); - } - - public static synchronized ShisenSho app() { - return instance; - } - - public ShisenShoView getView() { - if (view == null) view = new ShisenShoView(this); - return view; - } - - /** Called when the activity is first created. */ - @Override - public void onCreate() { - super.onCreate(); - } - - public Bundle getOptions() { - Bundle options = new Bundle(); - options.putInt("size", size); - options.putInt("difficulty", difficulty); - options.putBoolean("gravity", gravity); - options.putBoolean("timeCounter", timeCounter); - return options; - } - - public void setOptions(Bundle options) { - int size = options.getInt("size"); - int difficulty = options.getInt("difficulty"); - boolean gravity = options.getBoolean("gravity"); - boolean timeCounter = options.getBoolean("timeCounter"); - - boolean needsReset = false; - - if (size != this.size) { - setSize(size); - needsReset = true; - } - - if (difficulty != this.difficulty) { - this.difficulty = difficulty; - needsReset = true; - } - - if (gravity != this.gravity) { - this.gravity = gravity; - needsReset = true; - } - - if (timeCounter != this.timeCounter) { - this.timeCounter = timeCounter; - view.onTimeCounterActivate(); - } - - if (needsReset) { - view.reset(); - } - } - -} diff --git a/src/org/proofofconcept/shisensho/ShisenShoActivity.java b/src/org/proofofconcept/shisensho/ShisenShoActivity.java deleted file mode 100644 index 5036eb8..0000000 --- a/src/org/proofofconcept/shisensho/ShisenShoActivity.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.proofofconcept.shisensho; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.text.SpannableString; -import android.text.util.Linkify; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.TextView; - -public class ShisenShoActivity extends Activity { - private ShisenShoView view; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - requestWindowFeature(Window.FEATURE_NO_TITLE); - //getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - // WindowManager.LayoutParams.FLAG_FULLSCREEN); - - view = ShisenSho.app().getView(); - ShisenSho.app().activity = this; - setContentView(view); - } - - @Override - protected void onDestroy() { - ViewGroup vg = (ViewGroup)(view.getParent()); - vg.removeView(view); - ShisenSho.app().activity = null; - super.onDestroy(); - } - - @Override - protected void onPause() { - if (view!=null) { - view.pauseTime(); - } - super.onPause(); - } - - @Override - protected void onResume() { - super.onResume(); - if (view!=null) { - view.resumeTime(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle item selection - switch (item.getItemId()) { - case R.id.hint: - case R.id.undo: - case R.id.clean: - return view.onOptionsItemSelected(item); - case R.id.options: - startActivityForResult(new Intent("org.proofofconcept.shisensho.SETTINGS", null), 0); - return true; - case R.id.about: - onAboutActivate(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - private void onAboutActivate() { - // Try to load the a package matching the name of our own package - PackageInfo pInfo; - try { - pInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA); - String aboutTitle = String.format("About %s", getString(R.string.app_name)); - String versionString = String.format("Version: %s", pInfo.versionName); - String aboutText = getString(R.string.aboutText); - - // Set up the TextView - final TextView message = new TextView(this); - // We'll use a spannablestring to be able to make links clickable - final SpannableString s = new SpannableString(aboutText); - - // Set some padding - message.setPadding(5, 5, 5, 5); - // Set up the final string - message.setText(versionString + "\n" + s); - // Now linkify the text - Linkify.addLinks(message, Linkify.ALL); - - new AlertDialog.Builder(this) - .setTitle(aboutTitle) - .setCancelable(true) - .setIcon(R.drawable.icon) - .setPositiveButton(getString(android.R.string.ok), null) - .setView(message).create() - .show(); - } catch (NameNotFoundException e) { - e.printStackTrace(); - } - } -} diff --git a/src/org/proofofconcept/shisensho/ShisenShoOptionsActivity.java b/src/org/proofofconcept/shisensho/ShisenShoOptionsActivity.java deleted file mode 100644 index 87631bd..0000000 --- a/src/org/proofofconcept/shisensho/ShisenShoOptionsActivity.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.proofofconcept.shisensho; - -import java.io.Serializable; - -import android.app.Activity; -import android.os.Bundle; -import android.view.View; -import android.view.Window; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.CompoundButton; -import android.widget.Spinner; -import android.widget.ToggleButton; - -public class ShisenShoOptionsActivity extends Activity { - - Bundle state; - ShisenSho app; - - private void appToState (boolean merge) { - String[] fields = { "size", "difficulty", "gravity", "timeCounter" }; - Bundle options = app.getOptions(); - if (state == null) state = new Bundle(); - for (int i=0; i arg0, View arg1, - int pos, long arg3) { - state.putInt("size", pos+1); - } - - public void onNothingSelected(AdapterView arg0) { } - }); - - s = (Spinner) findViewById(R.id.difficulty); - adapter = ArrayAdapter.createFromResource( - this, R.array.difficulties, android.R.layout.simple_spinner_item); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - s.setAdapter(adapter); - s.setSelection(2-state.getInt("difficulty")); - s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - public void onItemSelected(AdapterView arg0, View arg1, - int pos, long arg3) { - state.putInt("difficulty", 2-pos); - } - - public void onNothingSelected(AdapterView arg0) { } - }); - - tb = (ToggleButton) findViewById(R.id.gravity); - tb.setChecked(state.getBoolean("gravity")); - tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - public void onCheckedChanged(CompoundButton arg0, boolean arg1) { - state.putBoolean("gravity", arg1); - } - }); - - tb = (ToggleButton) findViewById(R.id.timeCounter); - tb.setChecked(state.getBoolean("timeCounter")); - tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - public void onCheckedChanged(CompoundButton arg0, boolean arg1) { - state.putBoolean("timeCounter", arg1); - } - }); - } - - @Override - public void onBackPressed() { - app.setOptions(state); - super.onBackPressed(); - } - -} diff --git a/src/org/proofofconcept/shisensho/ShisenShoView.java b/src/org/proofofconcept/shisensho/ShisenShoView.java deleted file mode 100644 index 1cc1e07..0000000 --- a/src/org/proofofconcept/shisensho/ShisenShoView.java +++ /dev/null @@ -1,661 +0,0 @@ -package org.proofofconcept.shisensho; - -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Align; -import android.graphics.Paint.Cap; -import android.graphics.Paint.Join; -import android.graphics.Paint.Style; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.os.Handler; -import android.os.Message; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { - - private enum StatePlay { UNINITIALIZED, IDLE, SELECTED1, SELECTED2, GAMEOVER }; - private enum StatePaint { BOARD, SELECTED1, SELECTED2, MATCHED, WIN, LOSE, HINT, TIME }; - - private int screenWidth; - private int screenHeight; - private int tilesetRows; - private int tilesetCols; - private int tileHeight; - private int tileWidth; - private Bitmap bg; - private Bitmap tile[]; - private int[] selection1=new int[2]; - private int[] selection2=new int[2]; - private List path=null; - private List pairs=null; - private long startTime; - private long playTime; - private long baseTime; - private Timer timer; - private Handler timerHandler; - - private boolean timerRegistered=false; - private ShisenSho app; - private StatePlay cstate; - private StatePaint pstate; - private Canvas canvas = null; - private SurfaceHolder surfaceHolder = null; - private String debugMessage = ""; - - public ShisenShoView(ShisenSho shishenSho) { - super((Context)shishenSho); - this.app = shishenSho; - cstate = StatePlay.UNINITIALIZED; - surfaceHolder = getHolder(); - surfaceHolder.addCallback(this); - } - - private void paint(StatePaint pstate) { - this.pstate=pstate; - repaint(); - } - - private void control(StatePlay cstate) { - this.cstate=cstate; - } - - private void loadTileset() { - BitmapFactory.Options ops = new BitmapFactory.Options(); - ops.inScaled = false; - Bitmap tileset = BitmapFactory.decodeResource(getResources(), R.drawable.tileset, ops); - tileset.setDensity(Bitmap.DENSITY_NONE); - - // The tile set has 4 rows x 9 columns - tilesetRows = 4; - tilesetCols = 9; - tileWidth = tileset.getWidth()/tilesetCols; - tileHeight = tileset.getHeight()/tilesetRows; - tile = new Bitmap[tilesetRows*tilesetCols]; - int k=0; - for (int i=0; i0) { - Line pair=pairs.get(0); - Point a=pair.a; - Point b=pair.b; - path=app.board.getPath(a,b); - paint.setColor(orange); - paint.setStyle(Style.STROKE); - paint.setStrokeCap(Cap.ROUND); - paint.setStrokeJoin(Join.ROUND); - paint.setStrokeWidth(3); - - cbuffer.drawRect(new Rect( - x0+a.j*tileWidth-2, - y0+a.i*tileHeight-2, - x0+a.j*tileWidth-2+tileWidth+2*2, - y0+a.i*tileHeight-2+tileHeight+2*2), - paint); - - if (path!=null) { - Point p0=null; - for (Point p1 : path) { - if (p0!=null) { - cbuffer.drawLine( - x0+p0.j*tileWidth-2+(tileWidth/2), - y0+p0.i*tileHeight-2+(tileHeight/2), - x0+p1.j*tileWidth-2+(tileWidth/2), - y0+p1.i*tileHeight-2+(tileHeight/2), - paint); - } - p0=p1; - } - path=null; - } - - cbuffer.drawRect(new Rect( - x0+b.j*tileWidth-2, - y0+b.i*tileHeight-2, - x0+b.j*tileWidth-2+tileWidth+2*2, - y0+b.i*tileHeight-2+tileHeight+2*2), - paint); - } - break; - } - - // Win & loose notifications - switch (pstate) { - case WIN: - drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"You Win!", "#FFFFFF", 100); - break; - case LOSE: - drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"Game Over", "#FFFFFF", 100); - break; - } - - if (app.timeCounter) switch (pstate) { - case BOARD: - case SELECTED1: - case SELECTED2: - case MATCHED: - case WIN: - case LOSE: - case HINT: - case TIME: - updateTime(); - int hours=(int)(playTime/(60*60)); - int minutes=(int)((playTime/60)%60); - int seconds=(int)(playTime%60); - String time=String.format("%01d:%02d:%02d", hours, minutes, seconds); - - int timePosX=screenWidth-120; - int timePosY=screenHeight-10; - - drawMessage(cbuffer, timePosX+1,timePosY+1,false,time,"#000000",30); - drawMessage(cbuffer, timePosX,timePosY,false,time,"#FFFFFF",30); - break; - } - - // Debug messages - /* - debugMessage="StatePlay: "+cstate+"\n"+"StatePaint: "+pstate; - if (debugMessage!=null && debugMessage.length()>0) { - int l = 20; - String lines[] = debugMessage.split("\n"); - for (int i=0; i=0 && - i=0 && j=0 && i=0 && j0) { - app.board.play(a,b); - } - path=null; - paint(StatePaint.BOARD); - - pairs=app.board.getPairs(1); - if (pairs.size()==0) { - if (app.board.getNumPieces()==0) { - paint(StatePaint.WIN); - } else { - paint(StatePaint.LOSE); - } - control(StatePlay.GAMEOVER); - } else { - control(StatePlay.IDLE); - } - //undo.sensitive=app.board.getCanUndo(); - } - } - break; - case GAMEOVER: - reset(); - paint(StatePaint.BOARD); - break; - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height) { - surfaceHolder = holder; - if (cstate!=StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) { - registerTimer(); - } - repaint(); - } - - public void surfaceCreated(SurfaceHolder holder) { - surfaceHolder = holder; - repaint(); - } - - public void surfaceDestroyed(SurfaceHolder holder) { - surfaceHolder = null; - if (timerRegistered) { - unregisterTimer(); - } - } - - /* - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (!initialized) initialize(); - - long currTime = System.currentTimeMillis(); - - a = (float)(currTime - startTime) / (float)duration; - if (a > (float)1.0) a = (float)1.0; - - x = Math.round(nextx*a + prevx*(1-a)); - y = Math.round(nexty*a + prevy*(1-a)); - - if (a == (float)1.0) computeNextTarget(); - - int bgWidth = bg.getWidth(); - int bgHeight = bg.getHeight(); - for (int i=0; i