<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="lib" path="/bigstorage/adt-bundle-linux-x86/sdk/platforms/android-17/android.jar"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.proofofconcept.shisensho"
+ package="de.cwde.shisensho"
android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4"></uses-sdk>
+ android:versionName="0.1">
+ <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="10"></uses-sdk>
<application android:icon="@drawable/icon" android:label="@string/app_name"
- android:name=".ShisenSho">
+ android:name=".ShisenSho" android:allowBackup="true">
<activity android:name=".ShisenShoActivity"
android:screenOrientation="landscape">
<intent-filter>
android:name=".ShisenShoOptionsActivity"
android:screenOrientation="landscape">
<intent-filter>
- <action android:name="org.proofofconcept.shisensho.SETTINGS"/>
+ <action android:name="de.cwde.shisensho.SETTINGS"/>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
\ No newline at end of file
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
native <methods>;
}
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-10
+target=android-17
<TableRow android:id="@+id/tableRow4" android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView android:paddingLeft="5dip" android:layout_width="wrap_content"
- android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/gravityLabel" android:text="@string/gravity_label" android:layout_marginTop="12px"></TextView>
- <ToggleButton android:id="@+id/gravity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ToggleButton" android:layout_marginTop="3px" android:layout_marginBottom="3px"></ToggleButton>
+ android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/gravityLabel" android:text="@string/gravity_label" android:layout_marginTop="12dp"></TextView>
+ <ToggleButton android:id="@+id/gravity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"></ToggleButton>
</TableRow>
<TableRow android:id="@+id/tableRow5" android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView android:paddingLeft="5dip" android:layout_width="wrap_content"
- android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/timeCounterLabel" android:text="@string/time_counter_label" android:layout_marginTop="12px"></TextView>
- <ToggleButton android:id="@+id/timeCounter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ToggleButton" android:layout_marginTop="3px" android:layout_marginBottom="3px"></ToggleButton>
+ android:textSize="8pt" android:layout_height="wrap_content" android:id="@+id/timeCounterLabel" android:text="@string/time_counter_label" android:layout_marginTop="12dp"></TextView>
+ <ToggleButton android:id="@+id/timeCounter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"></ToggleButton>
</TableRow>
</TableLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="hello">Hello World, ShisenSho!</string>
<string name="app_name">ShisenSho</string>
<string name="clean">Clean</string>
<string name="hint">Hint</string>
<string name="options">Options</string>
<string name="about">About</string>
<string name="aboutText">\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
</string>
<string name="size">Size</string>
<string name="difficulty">Difficulty</string>
--- /dev/null
+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<Move> 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<boardSize[0];i++)
+ for (int j=0;j<boardSize[1];j++)
+ board[i][j]=0;
+ history=new LinkedList<Move>();
+ }
+
+ 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;(upiece<charpiecesLen && charpieces.substring(upiece,1)!=piece);upiece++);
+ if (upiece<charpiecesLen) return upiece;
+ else return 0;
+ }
+
+ public String toString() {
+ String result=" ";
+ for (int j=0;j<boardSize[1];j++) {
+ if (j>0) result+=" ";
+ result+=""+(j%10);
+ }
+ result+="\n "+StringRepeat("--",boardSize[1]);
+ for (int i=0;i<boardSize[0];i++) {
+ result+="\n"+(i%10)+"|";
+ for (int j=0;j<boardSize[1];j++) {
+ if (j>0) result+=" ";
+ result+=charpieces.substring(board[i][j],board[i][j]+1);
+ }
+ result+=" |\n";
+ if (i<boardSize[0]-1)
+ result+=" |"+StringRepeat(" ",boardSize[1])+"|";
+ }
+ result+=" "+StringRepeat("--",boardSize[1])+"\n";
+ return result;
+ }
+
+ public void buildRandomBoard(int sizeI, int sizeJ, int difficulty, boolean gravity) {
+ initialize(sizeI,sizeJ);
+ this.difficulty=difficulty;
+ this.gravity=gravity;
+
+ int numDifferentPieces=((boardSize[0]-2)*(boardSize[1]-2)/((difficulty+1)*2))+1;
+ for (int n=0;n<((difficulty+1)*2);n++) {
+ for (int k=0;k<numDifferentPieces;k++) {
+ int i,j;
+ do {
+ j=(myrand() % (boardSize[1]-2))+1;
+ i=findFreeRow(j);
+ } while (i<1);
+ // ShisenSho.log("numDifferentPieces="+numDifferentPieces+", n="+n+", k="+(int)k+", i="+i+", j="+j);
+ // ShisenSho.log(toString());
+ board[i][j]=(char)k;
+ }
+ }
+ }
+
+ /*
+ ALGORITHM TO COMPUTE CONNECTION PATH BETWEEN PIECES A (IA,JA) AND B (IB,JB)
+
+ - Delete A and B from the board (consider them as blank spaces)
+ - Calculate the set H of possible horizontal lines in the board (lines through blank spaces)
+ - Calculate the set V of possible vertical lines in the board
+ - Find HA, VA, HB, VB in the sets
+ - If HA=HB, result is a straight horizontal line A-B
+ - If VA=VB, result is a straight vertical line A-B
+ - If HA cuts VB, the result is an L line A-(IA,JB)-B
+ - If VA cuts HB, the result is an L line A-(IB,JA)-B
+ - If exists an V line that cuts HA and HB, the result is a Z line A-(IA,JV)-(IB-JV)-B
+ - If exists an H line that cuts VA and VB, the result is a Z line A-(IV,JA)-(IV,JB)-B
+
+ The following data types are defined:
+
+ - Board
+ - Point(int i, int j)
+ - Line(Point a, Point b)
+ - LineSet(Line l1, ..., Line lN)
+
+ The following operations are defined
+
+ - LineSet getHorizontalLines(Board board, Point a, Point b) // a and b needed to consider them as blank
+ - LineSet getVerticalLines(Board board, Point a, Point b)
+ - boolean lineIsHorizontal(Line l)
+ - boolean lineIsVertical(Line l)
+ - boolean lineContainsPoint(Line l, Point p)
+ - boolean lineEqualsLine(Line l1, Line l2)
+ - boolean lineCutsLine(Line l1, Line l2)
+ */
+ public List<Point> getPath(Point a, Point b) {
+ List<Point> result=new ArrayList<Point>();
+
+ if (getPiece(a)!=getPiece(b)) return result;
+
+ List<Line> h=getHorizontalLines(a,b);
+ List<Line> v=getVerticalLines(a,b);
+ Line ha=null, va=null, hb=null, vb=null;
+
+ for (Line l : h) {
+ if (l.contains(a)) ha=l;
+ if (l.contains(b)) hb=l;
+ if (ha!=null && hb!=null) break;
+ }
+
+ for (Line l : v) {
+ if (l.contains(a)) va=l;
+ if (l.contains(b)) vb=l;
+ if (va!=null && vb!=null) break;
+ }
+
+ // stdout.printf("va=%s, ha=%s, vb=%s, hb=%s\n",va.toString(),ha.toString(),vb.toString(),hb.toString());
+
+ if ((ha==null && va==null) || (hb==null && vb==null))
+ return result;
+
+ if (ha.equals(hb) || va.equals(vb)) {
+ result.add(a);
+ result.add(b);
+ return result;
+ }
+
+ Point ab;
+
+ ab=ha.cuts(vb);
+ // stdout.printf("(ha cuts vb) ab=%s\n",ab.toString());
+
+ if (ab!=null) {
+ result.add(a);
+ result.add(ab);
+ result.add(b);
+ return result;
+ }
+
+ ab=va.cuts(hb);
+ // stdout.printf("(va cuts hb) ab=%s\n",ab.toString());
+
+ if (ab!=null) {
+ result.add(a);
+ result.add(ab);
+ result.add(b);
+ return result;
+ }
+
+ for (Line l : v) {
+ Point al=l.cuts(ha);
+ Point bl=l.cuts(hb);
+
+ // stdout.printf("(%s cuts ha) al=%s\n",l.toString(),al.toString());
+ // stdout.printf("(%s cuts hb) bl=%s\n",l.toString(),bl.toString());
+
+ if (al!=null && bl!=null) {
+ result.add(a);
+ result.add(al);
+ result.add(bl);
+ result.add(b);
+ return result;
+ }
+ }
+
+ for (Line l : h) {
+ Point al=l.cuts(va);
+ Point bl=l.cuts(vb);
+
+ // stdout.printf("(%s cuts va) al=%s\n",l.toString(),al.toString());
+ // stdout.printf("(%s cuts vb) bl=%s\n",l.toString(),bl.toString());
+
+ if (al!=null && bl!=null) {
+ result.add(a);
+ result.add(al);
+ result.add(bl);
+ result.add(b);
+ return result;
+ }
+ }
+
+ return result;
+ }
+
+ public char getPiece(Point p) {
+ return board[p.i][p.j];
+ }
+
+ public void setPiece(Point p, char piece) {
+ board[p.i][p.j]=piece;
+ }
+
+ public String getStrPiece(Point p) {
+ char piece=board[p.i][p.j];
+ return charpieces.substring(piece,1);
+ }
+
+ public void setStrPiece(Point p, String piece) {
+ char upiece;
+ long charpiecesLen=charpieces.length();
+ for(upiece=0;(upiece<charpiecesLen && charpieces.substring(upiece,1)!=piece);upiece++);
+ if (upiece<charpiecesLen) board[p.i][p.j]=upiece;
+ }
+
+ public void play(Point a0, Point b0) {
+ // It's important to sink the upper piece first
+ Point a=(a0.i<b0.i)?a0:b0;
+ Point b=(a0.i<b0.i)?b0:a0;
+ Move m=new Move(a,b,getPiece(a));
+ history.add(0,m);
+ setPiece(a,(char)0);
+ processGravity(a);
+ setPiece(b,(char)0);
+ processGravity(b);
+ }
+
+ public boolean getCanUndo() {
+ return !history.isEmpty();
+ }
+
+ public void undo() {
+ if (!getCanUndo()) return;
+ Move m=history.remove(0);
+ undoGravity(m.b);
+ setPiece(m.b,m.piece);
+ undoGravity(m.a);
+ setPiece(m.a,m.piece);
+ }
+
+ public List<Line> getPairs(int maxResults) {
+ List<Line> result=new ArrayList<Line>();
+ List<Integer> pieces=new ArrayList<Integer>();
+ List<List<Point>> piecePoints=new ArrayList<List<Point>>();
+ for (int i=0;i<boardSize[0];i++)
+ for (int j=0;j<boardSize[1];j++) {
+ int piece=(int)board[i][j];
+ if (piece==0) continue;
+ int key=pieces.indexOf(piece);
+ Point p=new Point(i,j);
+ if (key==-1) {
+ List<Point> points0=new ArrayList<Point>();
+ points0.add(p);
+ pieces.add(piece);
+ piecePoints.add(points0);
+
+ key=pieces.indexOf(piece);
+ piecePoints.get(key);
+ } else {
+ List<Point> points1=piecePoints.get(key);
+ points1.add(p);
+ }
+ }
+
+ int nresults=0;
+ for (List<Point> points : piecePoints) {
+ int n=(int)points.size();
+ for (int i=0;i<n;i++) {
+ Point a=points.get(i);
+ for (int j=i+1;j<n;j++) {
+ Point b=points.get(j);
+ List<Point> 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<boardSize[1];j++) {
+ for (int i=0;i<boardSize[0];i++) {
+ if (board[i][j]!=0) result++;
+ }
+ }
+ return result;
+ }
+
+ // ----------------------
+ // Private methods
+ // ----------------------
+
+ /* RAND_MAX assumed to be 32767 */
+ private int myrand() {
+ return (int)Math.floor(Math.random()*32768);
+ }
+
+ private String StringRepeat(String s, int n) {
+ String result="";
+ for (int i=0;i<n;i++)
+ result+=s;
+ return result;
+ }
+
+ private int findFreeRow(int j) {
+ for (int i=1;i<boardSize[0]-1;i++) {
+ if (board[i][j]!=0) return (i-1);
+ }
+ return (boardSize[0]-1-1);
+ }
+
+ private List<Line> getHorizontalLines(Point excludeA, Point excludeB) {
+ List<Line> result=new ArrayList<Line>();
+ for (int i=0;i<boardSize[0];i++) {
+ int j0=-1;
+ boolean empty;
+ for (int j=0;j<boardSize[1];j++) {
+ empty=(board[i][j]==0 || (i==excludeA.i && j==excludeA.j)
+ || (i==excludeB.i && j==excludeB.j));
+ if (j0==-1 && empty) {
+ j0=j;
+ } else if (j0!=-1 && !empty) {
+ result.add(new Line(new Point(i,j0), new Point(i,j-1)));
+ j0=-1;
+ }
+ }
+ if (j0!=-1) result.add(new Line(new Point(i,j0), new Point(i,boardSize[1]-1)));
+ }
+
+ // stdout.printf("\ngetHorizontalLines( %s, %s ): ",excludeA.toString(),excludeB.toString());
+ // for (Line line : result) stdout.printf("%s ",line.toString());
+ // stdout.printf("\n");
+
+ return result;
+ }
+
+ private List<Line> getVerticalLines(Point excludeA, Point excludeB) {
+ List<Line> result=new ArrayList<Line>();
+ for (int j=0;j<boardSize[1];j++) {
+ int i0=-1;
+ boolean empty;
+ for (int i=0;i<boardSize[0];i++) {
+ empty=(board[i][j]==0 || (i==excludeA.i && j==excludeA.j)
+ || (i==excludeB.i && j==excludeB.j));
+ if (i0==-1 && empty) {
+ i0=i;
+ } else if (i0!=-1 && !empty) {
+ result.add(new Line(new Point(i0,j), new Point(i-1,j)));
+ i0=-1;
+ }
+ }
+ if (i0!=-1) result.add(new Line(new Point(i0,j), new Point(boardSize[0]-1,j)));
+ }
+
+ // stdout.printf("\ngetVerticalLines( %s, %s ): ",excludeA.toString(),excludeB.toString());
+ // for (Line line : result) stdout.printf("%s ",line.toString());
+ // stdout.printf("\n");
+
+ return result;
+ }
+
+ private void processGravity(Point p) {
+ if (gravity) for (int i=p.i;i>0;i--) board[i][p.j]=board[i-1][p.j];
+ }
+
+ private void undoGravity(Point p) {
+ if (gravity) for (int i=0;i<p.i;i++) board[i][p.j]=board[i+1][p.j];
+ }
+
+}
--- /dev/null
+package de.cwde.shisensho;
+
+public class Line {
+ public Line(Point a, Point b) {
+ this.a=a;
+ this.b=b;
+ }
+
+ public boolean equals(Line l) {
+ return (a.equals(l.a) && b.equals(l.b));
+ }
+
+ public boolean isHorizontal() {
+ return (a.i==b.i);
+ }
+
+ public boolean isVertical() {
+ return (a.j==b.j);
+ }
+
+ public boolean contains(Point p) {
+ return (p.i==a.i && p.i==b.i && p.j>=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.i<b.i || a.j<b.j) return a;
+ else return b;
+ }
+
+ public Point getMax() {
+ if (a.i>b.i || a.j>b.j) return a;
+ else return b;
+ }
+
+ public String toString() {
+ return a+"-"+b;
+ }
+
+ public Point a;
+ public Point b;
+}
--- /dev/null
+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;
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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();
+ }
+ }
+
+}
--- /dev/null
+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();
+ }
+ }
+}
--- /dev/null
+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<fields.length; i++) {
+ if (!merge || !state.containsKey(fields[i])) {
+ state.putSerializable(fields[i], (Serializable)(options.get(fields[i])));
+ }
+ }
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.options);
+
+ app = ShisenSho.app();
+ state = savedInstanceState;
+ appToState(true);
+
+ Spinner s;
+ ToggleButton tb;
+ ArrayAdapter adapter;
+
+ s = (Spinner) findViewById(R.id.size);
+ adapter = ArrayAdapter.createFromResource(
+ this, R.array.sizes, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s.setAdapter(adapter);
+ s.setSelection(state.getInt("size")-1);
+ s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> 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();
+ }
+
+}
--- /dev/null
+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<Point> path=null;
+ private List<Line> 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; i<tilesetRows; i++) {
+ for (int j=0; j<tilesetCols; j++) {
+ tile[k] = Bitmap.createBitmap(tileset, j*tileWidth, i*tileHeight, tileWidth, tileHeight, null, false);
+ tile[k].setDensity(Bitmap.DENSITY_NONE);
+ k++;
+ }
+ }
+ tileWidth = tile[0].getWidth();
+ tileHeight = tile[0].getHeight();
+ }
+
+ private void loadBackground() {
+ BitmapFactory.Options ops = new BitmapFactory.Options();
+ ops.inScaled = false;
+ bg = BitmapFactory.decodeResource(getResources(), R.drawable.kshisen_bgnd, ops);
+ bg.setDensity(Bitmap.DENSITY_NONE);
+ }
+
+ private void registerTimer() {
+ if (timer!=null) return; // Already registered
+ timerHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ onUpdateTime();
+ }
+ };
+ timer=new Timer();
+ timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ timerHandler.sendEmptyMessage(Activity.RESULT_OK);
+ }
+ }, 0, 1000);
+ timerRegistered=true;
+ }
+
+ private void unregisterTimer() {
+ if (timer==null) return; // Already unregistered
+ timer.cancel();
+ timer = null;
+ timerHandler = null;
+ timerRegistered=false;
+ }
+
+ public void pauseTime() {
+ updateTime();
+ baseTime = playTime;
+ startTime = System.currentTimeMillis();
+
+ }
+
+ public void resumeTime() {
+ startTime = System.currentTimeMillis();
+ updateTime();
+ }
+
+ private void updateTime() {
+ if (cstate!=StatePlay.GAMEOVER) {
+ playTime = (System.currentTimeMillis()-startTime)/1000+baseTime;
+ }
+ }
+
+ private void initializeGame() {
+ loadBackground();
+ loadTileset();
+ screenWidth=getWidth();
+ screenHeight=getHeight();
+ //undo.sensitive=false;
+ pstate=StatePaint.BOARD;
+ app.newPlay();
+ control(StatePlay.IDLE);
+ startTime=System.currentTimeMillis();
+ playTime=0;
+ baseTime=0;
+ if (app.timeCounter && !timerRegistered) {
+ registerTimer();
+ }
+ pairs=app.board.getPairs(1);
+ }
+
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.hint:
+ this.postDelayed(new Runnable() { public void run() { onHintActivate(); } }, 100);
+ return true;
+ case R.id.undo:
+ this.postDelayed(new Runnable() { public void run() { onUndoActivate(); } }, 100);
+ return true;
+ case R.id.clean:
+ this.postDelayed(new Runnable() { public void run() { reset(); } }, 100);
+ return true;
+ case R.id.options:
+ return true;
+ case R.id.about:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public void reset() {
+ control(StatePlay.UNINITIALIZED);
+ paint(StatePaint.BOARD);
+ }
+
+ private void onHintActivate() {
+ if (cstate!=StatePlay.GAMEOVER) {
+ pairs=app.board.getPairs(1);
+ paint(StatePaint.HINT);
+ app.sleep(10);
+ paint(StatePaint.BOARD);
+ control(StatePlay.IDLE);
+ }
+ }
+
+ private void onUndoActivate() {
+ if (app.board.getCanUndo()) {
+ if (cstate==StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) {
+ // Reprogram the time update that had been
+ // deactivated with the game over status
+ registerTimer();
+ }
+ app.board.undo();
+ paint(StatePaint.BOARD);
+ //undo.sensitive=app.board.getCanUndo();
+ control(StatePlay.IDLE);
+ }
+ }
+
+ public void onTimeCounterActivate() {
+ if (app.timeCounter && cstate!=StatePlay.GAMEOVER && !timerRegistered) {
+ // Reprogram the time update that had been
+ // deactivated with the time_counter=false
+ registerTimer();
+ }
+ }
+
+ private void onUpdateTime() {
+ paint(pstate);
+ if (!(app.timeCounter && cstate!=StatePlay.GAMEOVER)) {
+ unregisterTimer();
+ }
+ }
+
+ public void drawMessage(Canvas canvas, int x, int y, boolean centered, String message, String color, float textSize) {
+ Paint paint = new Paint();
+ paint.setColor(Color.parseColor(color));
+ paint.setLinearText(true);
+ paint.setAntiAlias(true);
+ paint.setTextAlign(centered?Align.CENTER:Align.LEFT);
+ paint.setTypeface(Typeface.SANS_SERIF);
+ paint.setFakeBoldText(true);
+ paint.setTextSize(textSize);
+ canvas.drawText(message, x, y, paint);
+ }
+
+ public void repaint() {
+ if (surfaceHolder == null) return;
+ try {
+ if (canvas == null) canvas = surfaceHolder.lockCanvas(null);
+ if (canvas == null) return;
+ if (cstate==StatePlay.UNINITIALIZED) initializeGame();
+ synchronized (surfaceHolder) {
+ doDraw(canvas);
+ }
+ } finally {
+ if (canvas != null) {
+ surfaceHolder.unlockCanvasAndPost(canvas);
+ canvas = null;
+ }
+ }
+ }
+
+ protected void doDraw(Canvas canvas) {
+ try {
+ // Double buffering
+ // Bitmap buffer = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
+ //Canvas cbuffer = new Canvas(buffer);
+ Canvas cbuffer = canvas;
+ if (canvas == null) return;
+
+ //super.onDraw(canvas);
+
+ // Board upper left corner on screen
+ int x0=0;
+ int y0=0;
+
+ if (app!=null && app.board!=null) {
+ x0=(screenWidth-app.board.boardSize[1]*tileWidth)/2;
+ y0=(screenHeight-app.board.boardSize[0]*tileHeight)/2;
+ }
+
+ int red = Color.parseColor("#FF0000");
+ int orange = Color.parseColor("#F0C000");
+ Paint paint = new Paint();
+ paint.setFlags(Paint.ANTI_ALIAS_FLAG);
+
+ // Background & board painting
+ switch (pstate) {
+ case BOARD:
+ case SELECTED1:
+ case SELECTED2:
+ case MATCHED:
+ case WIN:
+ case LOSE:
+ case HINT:
+ case TIME:
+ // Background painting
+ int bgWidth = bg.getWidth();
+ int bgHeight = bg.getHeight();
+ for (int i=0; i<screenHeight/bgHeight+1; i++) {
+ for (int j=0; j<screenWidth/bgWidth+1; j++) {
+ cbuffer.drawBitmap(bg, j*bgWidth, i*bgHeight, paint);
+ }
+ }
+
+ // Board painting
+ // Max visible size: 7x17
+ if (app!=null && app.board!=null) {
+ for (int i=0;i<app.board.boardSize[0];i++) {
+ for (int j=0;j<app.board.boardSize[1];j++) {
+ // Tiles are 56px height, 40px width each
+ char piece=app.board.board[i][j];
+ if (piece!=0) {
+ cbuffer.drawBitmap(tile[piece], x0+j*tileWidth, y0+i*tileHeight, paint);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ // Red rectangle for selection 1
+ switch (pstate) {
+ case SELECTED1:
+ case SELECTED2:
+ case MATCHED:
+ paint.setColor(red);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeCap(Cap.ROUND);
+ paint.setStrokeJoin(Join.ROUND);
+ paint.setStrokeWidth(3);
+ cbuffer.drawRect(new Rect(
+ x0+selection1[1]*tileWidth-2,
+ y0+selection1[0]*tileHeight-2,
+ x0+selection1[1]*tileWidth-2+tileWidth+2*2,
+ y0+selection1[0]*tileHeight-2+tileHeight+2*2),
+ paint);
+ break;
+ }
+
+ // Red rectangle for selection 2
+ switch (pstate) {
+ case SELECTED2:
+ case MATCHED:
+ paint.setColor(red);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeCap(Cap.ROUND);
+ paint.setStrokeJoin(Join.ROUND);
+ paint.setStrokeWidth(3);
+ cbuffer.drawRect(new Rect(
+ x0+selection2[1]*tileWidth-2,
+ y0+selection2[0]*tileHeight-2,
+ x0+selection2[1]*tileWidth-2+tileWidth+2*2,
+ y0+selection2[0]*tileHeight-2+tileHeight+2*2),
+ paint);
+ break;
+ }
+
+ // Matching path
+ switch (pstate) {
+ case MATCHED:
+ paint.setColor(red);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeCap(Cap.ROUND);
+ paint.setStrokeJoin(Join.ROUND);
+ paint.setStrokeWidth(3);
+
+ 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;
+ }
+ }
+ break;
+ }
+
+ // Orange hint rectangles
+ switch (pstate) {
+ case HINT:
+ if (pairs!=null && pairs.size()>0) {
+ 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<lines.length; i++) {
+ drawMessage(cbuffer,1,l,false,lines[i],"#FFFF00",30);
+ l+=30;
+ }
+ }
+ */
+
+ // Double buffer dumping
+ // canvas.drawBitmap(buffer, 0, 0, null);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getAction()==MotionEvent.ACTION_DOWN) {
+ onClick(Math.round(event.getX()),Math.round(event.getY()));
+ }
+ return super.onTouchEvent(event);
+ }
+
+ private void onClick(int x, int y) {
+ try {
+ int i=(y-(screenHeight-app.board.boardSize[0]*tileHeight)/2)/tileHeight;
+ int j=(x-(screenWidth-app.board.boardSize[1]*tileWidth)/2)/tileWidth;
+
+ switch (cstate) {
+ case IDLE:
+ if (i>=0 &&
+ i<app.board.boardSize[0] &&
+ j>=0 && j<app.board.boardSize[1] &&
+ app.board.board[i][j]!=0) {
+ selection1[0]=i;
+ selection1[1]=j;
+ paint(StatePaint.SELECTED1);
+ control(StatePlay.SELECTED1);
+ }
+ break;
+ case SELECTED1:
+ if (i>=0 && i<app.board.boardSize[0] &&
+ j>=0 && j<app.board.boardSize[1] &&
+ app.board.board[i][j]!=0) {
+ if (i==selection1[0] && j==selection1[1]) {
+ paint(StatePaint.BOARD);
+ control(StatePlay.IDLE);
+ } else {
+ selection2[0]=i;
+ selection2[1]=j;
+ paint(StatePaint.SELECTED2);
+
+ Point a=new Point(selection1[0],selection1[1]);
+ Point b=new Point(selection2[0],selection2[1]);
+ path=app.board.getPath(a,b);
+ paint(StatePaint.MATCHED);
+ app.sleep(2);
+ paint(StatePaint.BOARD);
+ if (path.size()>0) {
+ 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<height/bgHeight+1; i++) {
+ for (int j=0; j<width/bgWidth+1; j++) {
+ canvas.drawBitmap(bg, j*bgWidth, i*bgHeight, paint);
+ }
+ }
+
+ canvas.drawBitmap(tile[randomtile], x, y, paint);
+
+ repaint();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getActionMasked()==MotionEvent.ACTION_DOWN) {
+ //computeNextTarget();
+ //nextx=Math.round(event.getX());
+ //nexty=Math.round(event.getY());
+ }
+ return super.onTouchEvent(event);
+ }
+
+ private void initialize() {
+ width = getWidth();
+ height = getHeight();
+
+ bg = BitmapFactory.decodeResource(getResources(), R.drawable.kshisen_bgnd);
+ Bitmap tileset = BitmapFactory.decodeResource(getResources(), R.drawable.tileset);
+
+ // The tile set has 4 rows x 9 columns
+ tsrows = 4;
+ tscols = 9;
+ twidth = tileset.getWidth()/tscols;
+ theight = tileset.getHeight()/tsrows;
+ tile = new Bitmap[tsrows*tscols];
+ int k=0;
+ for (int i=0; i<tsrows; i++) {
+ for (int j=0; j<tscols; j++) {
+ tile[k] = Bitmap.createBitmap(tileset, j*twidth, i*theight, twidth, theight, null, false);
+ k++;
+ }
+ }
+
+ x = width/2;
+ y = height/2;
+
+ computeNextTarget();
+
+ initialized = true;
+ }
+
+ private void computeNextTarget() {
+ startTime = System.currentTimeMillis();
+ prevx = x;
+ prevy = y;
+ nextx = (int) Math.floor(Math.random() * width);
+ nexty = (int) Math.floor(Math.random() * height);
+ randomtile = (int) Math.floor(Math.random() * tile.length);
+
+ paint = new Paint();
+ paint.setColor(Color.parseColor("#006666"));
+ paint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ }
+*/
+}
\ No newline at end of file
+++ /dev/null
-package org.proofofconcept.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<Move> 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<boardSize[0];i++)
- for (int j=0;j<boardSize[1];j++)
- board[i][j]=0;
- history=new LinkedList<Move>();
- }
-
- 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;(upiece<charpiecesLen && charpieces.substring(upiece,1)!=piece);upiece++);
- if (upiece<charpiecesLen) return upiece;
- else return 0;
- }
-
- public String toString() {
- String result=" ";
- for (int j=0;j<boardSize[1];j++) {
- if (j>0) result+=" ";
- result+=""+(j%10);
- }
- result+="\n "+StringRepeat("--",boardSize[1]);
- for (int i=0;i<boardSize[0];i++) {
- result+="\n"+(i%10)+"|";
- for (int j=0;j<boardSize[1];j++) {
- if (j>0) result+=" ";
- result+=charpieces.substring(board[i][j],board[i][j]+1);
- }
- result+=" |\n";
- if (i<boardSize[0]-1)
- result+=" |"+StringRepeat(" ",boardSize[1])+"|";
- }
- result+=" "+StringRepeat("--",boardSize[1])+"\n";
- return result;
- }
-
- public void buildRandomBoard(int sizeI, int sizeJ, int difficulty, boolean gravity) {
- initialize(sizeI,sizeJ);
- this.difficulty=difficulty;
- this.gravity=gravity;
-
- int numDifferentPieces=((boardSize[0]-2)*(boardSize[1]-2)/((difficulty+1)*2))+1;
- for (int n=0;n<((difficulty+1)*2);n++) {
- for (int k=0;k<numDifferentPieces;k++) {
- int i,j;
- do {
- j=(myrand() % (boardSize[1]-2))+1;
- i=findFreeRow(j);
- } while (i<1);
- // ShisenSho.log("numDifferentPieces="+numDifferentPieces+", n="+n+", k="+(int)k+", i="+i+", j="+j);
- // ShisenSho.log(toString());
- board[i][j]=(char)k;
- }
- }
- }
-
- /*
- ALGORITHM TO COMPUTE CONNECTION PATH BETWEEN PIECES A (IA,JA) AND B (IB,JB)
-
- - Delete A and B from the board (consider them as blank spaces)
- - Calculate the set H of possible horizontal lines in the board (lines through blank spaces)
- - Calculate the set V of possible vertical lines in the board
- - Find HA, VA, HB, VB in the sets
- - If HA=HB, result is a straight horizontal line A-B
- - If VA=VB, result is a straight vertical line A-B
- - If HA cuts VB, the result is an L line A-(IA,JB)-B
- - If VA cuts HB, the result is an L line A-(IB,JA)-B
- - If exists an V line that cuts HA and HB, the result is a Z line A-(IA,JV)-(IB-JV)-B
- - If exists an H line that cuts VA and VB, the result is a Z line A-(IV,JA)-(IV,JB)-B
-
- The following data types are defined:
-
- - Board
- - Point(int i, int j)
- - Line(Point a, Point b)
- - LineSet(Line l1, ..., Line lN)
-
- The following operations are defined
-
- - LineSet getHorizontalLines(Board board, Point a, Point b) // a and b needed to consider them as blank
- - LineSet getVerticalLines(Board board, Point a, Point b)
- - boolean lineIsHorizontal(Line l)
- - boolean lineIsVertical(Line l)
- - boolean lineContainsPoint(Line l, Point p)
- - boolean lineEqualsLine(Line l1, Line l2)
- - boolean lineCutsLine(Line l1, Line l2)
- */
- public List<Point> getPath(Point a, Point b) {
- List<Point> result=new ArrayList<Point>();
-
- if (getPiece(a)!=getPiece(b)) return result;
-
- List<Line> h=getHorizontalLines(a,b);
- List<Line> v=getVerticalLines(a,b);
- Line ha=null, va=null, hb=null, vb=null;
-
- for (Line l : h) {
- if (l.contains(a)) ha=l;
- if (l.contains(b)) hb=l;
- if (ha!=null && hb!=null) break;
- }
-
- for (Line l : v) {
- if (l.contains(a)) va=l;
- if (l.contains(b)) vb=l;
- if (va!=null && vb!=null) break;
- }
-
- // stdout.printf("va=%s, ha=%s, vb=%s, hb=%s\n",va.toString(),ha.toString(),vb.toString(),hb.toString());
-
- if ((ha==null && va==null) || (hb==null && vb==null))
- return result;
-
- if (ha.equals(hb) || va.equals(vb)) {
- result.add(a);
- result.add(b);
- return result;
- }
-
- Point ab;
-
- ab=ha.cuts(vb);
- // stdout.printf("(ha cuts vb) ab=%s\n",ab.toString());
-
- if (ab!=null) {
- result.add(a);
- result.add(ab);
- result.add(b);
- return result;
- }
-
- ab=va.cuts(hb);
- // stdout.printf("(va cuts hb) ab=%s\n",ab.toString());
-
- if (ab!=null) {
- result.add(a);
- result.add(ab);
- result.add(b);
- return result;
- }
-
- for (Line l : v) {
- Point al=l.cuts(ha);
- Point bl=l.cuts(hb);
-
- // stdout.printf("(%s cuts ha) al=%s\n",l.toString(),al.toString());
- // stdout.printf("(%s cuts hb) bl=%s\n",l.toString(),bl.toString());
-
- if (al!=null && bl!=null) {
- result.add(a);
- result.add(al);
- result.add(bl);
- result.add(b);
- return result;
- }
- }
-
- for (Line l : h) {
- Point al=l.cuts(va);
- Point bl=l.cuts(vb);
-
- // stdout.printf("(%s cuts va) al=%s\n",l.toString(),al.toString());
- // stdout.printf("(%s cuts vb) bl=%s\n",l.toString(),bl.toString());
-
- if (al!=null && bl!=null) {
- result.add(a);
- result.add(al);
- result.add(bl);
- result.add(b);
- return result;
- }
- }
-
- return result;
- }
-
- public char getPiece(Point p) {
- return board[p.i][p.j];
- }
-
- public void setPiece(Point p, char piece) {
- board[p.i][p.j]=piece;
- }
-
- public String getStrPiece(Point p) {
- char piece=board[p.i][p.j];
- return charpieces.substring(piece,1);
- }
-
- public void setStrPiece(Point p, String piece) {
- char upiece;
- long charpiecesLen=charpieces.length();
- for(upiece=0;(upiece<charpiecesLen && charpieces.substring(upiece,1)!=piece);upiece++);
- if (upiece<charpiecesLen) board[p.i][p.j]=upiece;
- }
-
- public void play(Point a0, Point b0) {
- // It's important to sink the upper piece first
- Point a=(a0.i<b0.i)?a0:b0;
- Point b=(a0.i<b0.i)?b0:a0;
- Move m=new Move(a,b,getPiece(a));
- history.add(0,m);
- setPiece(a,(char)0);
- processGravity(a);
- setPiece(b,(char)0);
- processGravity(b);
- }
-
- public boolean getCanUndo() {
- return !history.isEmpty();
- }
-
- public void undo() {
- if (!getCanUndo()) return;
- Move m=history.remove(0);
- undoGravity(m.b);
- setPiece(m.b,m.piece);
- undoGravity(m.a);
- setPiece(m.a,m.piece);
- }
-
- public List<Line> getPairs(int maxResults) {
- List<Line> result=new ArrayList<Line>();
- List<Integer> pieces=new ArrayList<Integer>();
- List<List<Point>> piecePoints=new ArrayList<List<Point>>();
- for (int i=0;i<boardSize[0];i++)
- for (int j=0;j<boardSize[1];j++) {
- int piece=(int)board[i][j];
- if (piece==0) continue;
- int key=pieces.indexOf(piece);
- Point p=new Point(i,j);
- if (key==-1) {
- List<Point> points0=new ArrayList<Point>();
- points0.add(p);
- pieces.add(piece);
- piecePoints.add(points0);
-
- key=pieces.indexOf(piece);
- piecePoints.get(key);
- } else {
- List<Point> points1=piecePoints.get(key);
- points1.add(p);
- }
- }
-
- int nresults=0;
- int k=0;
- for (List<Point> points : piecePoints) {
- int n=(int)points.size();
- for (int i=0;i<n;i++) {
- Point a=points.get(i);
- for (int j=i+1;j<n;j++) {
- Point b=points.get(j);
- List<Point> 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<boardSize[1];j++) {
- for (int i=0;i<boardSize[0];i++) {
- if (board[i][j]!=0) result++;
- }
- }
- return result;
- }
-
- // ----------------------
- // Private methods
- // ----------------------
-
- /* RAND_MAX assumed to be 32767 */
- private int myrand() {
- return (int)Math.floor(Math.random()*32768);
- }
-
- private String StringRepeat(String s, int n) {
- String result="";
- for (int i=0;i<n;i++)
- result+=s;
- return result;
- }
-
- private int findFreeRow(int j) {
- for (int i=1;i<boardSize[0]-1;i++) {
- if (board[i][j]!=0) return (i-1);
- }
- return (boardSize[0]-1-1);
- }
-
- private List<Line> getHorizontalLines(Point excludeA, Point excludeB) {
- List<Line> result=new ArrayList<Line>();
- for (int i=0;i<boardSize[0];i++) {
- int j0=-1;
- boolean empty;
- for (int j=0;j<boardSize[1];j++) {
- empty=(board[i][j]==0 || (i==excludeA.i && j==excludeA.j)
- || (i==excludeB.i && j==excludeB.j));
- if (j0==-1 && empty) {
- j0=j;
- } else if (j0!=-1 && !empty) {
- result.add(new Line(new Point(i,j0), new Point(i,j-1)));
- j0=-1;
- }
- }
- if (j0!=-1) result.add(new Line(new Point(i,j0), new Point(i,boardSize[1]-1)));
- }
-
- // stdout.printf("\ngetHorizontalLines( %s, %s ): ",excludeA.toString(),excludeB.toString());
- // for (Line line : result) stdout.printf("%s ",line.toString());
- // stdout.printf("\n");
-
- return result;
- }
-
- private List<Line> getVerticalLines(Point excludeA, Point excludeB) {
- List<Line> result=new ArrayList<Line>();
- for (int j=0;j<boardSize[1];j++) {
- int i0=-1;
- boolean empty;
- for (int i=0;i<boardSize[0];i++) {
- empty=(board[i][j]==0 || (i==excludeA.i && j==excludeA.j)
- || (i==excludeB.i && j==excludeB.j));
- if (i0==-1 && empty) {
- i0=i;
- } else if (i0!=-1 && !empty) {
- result.add(new Line(new Point(i0,j), new Point(i-1,j)));
- i0=-1;
- }
- }
- if (i0!=-1) result.add(new Line(new Point(i0,j), new Point(boardSize[0]-1,j)));
- }
-
- // stdout.printf("\ngetVerticalLines( %s, %s ): ",excludeA.toString(),excludeB.toString());
- // for (Line line : result) stdout.printf("%s ",line.toString());
- // stdout.printf("\n");
-
- return result;
- }
-
- private void processGravity(Point p) {
- if (gravity) for (int i=p.i;i>0;i--) board[i][p.j]=board[i-1][p.j];
- }
-
- private void undoGravity(Point p) {
- if (gravity) for (int i=0;i<p.i;i++) board[i][p.j]=board[i+1][p.j];
- }
-
-}
+++ /dev/null
-package org.proofofconcept.shisensho;
-
-public class Line {
- public Line(Point a, Point b) {
- this.a=a;
- this.b=b;
- }
-
- public boolean equals(Line l) {
- return (a.equals(l.a) && b.equals(l.b));
- }
-
- public boolean isHorizontal() {
- return (a.i==b.i);
- }
-
- public boolean isVertical() {
- return (a.j==b.j);
- }
-
- public boolean contains(Point p) {
- return (p.i==a.i && p.i==b.i && p.j>=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.i<b.i || a.j<b.j) return a;
- else return b;
- }
-
- public Point getMax() {
- if (a.i>b.i || a.j>b.j) return a;
- else return b;
- }
-
- public String toString() {
- return a+"-"+b;
- }
-
- public Point a;
- public Point b;
-}
+++ /dev/null
-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;
-}
+++ /dev/null
-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);
- }
-}
+++ /dev/null
-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();
- }
- }
-
-}
+++ /dev/null
-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();
- }
- }
-}
+++ /dev/null
-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<fields.length; i++) {
- if (!merge || !state.containsKey(fields[i])) {
- state.putSerializable(fields[i], (Serializable)(options.get(fields[i])));
- }
- }
- }
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.options);
-
- app = ShisenSho.app();
- state = savedInstanceState;
- appToState(true);
-
- Spinner s;
- ToggleButton tb;
- ArrayAdapter adapter;
-
- s = (Spinner) findViewById(R.id.size);
- adapter = ArrayAdapter.createFromResource(
- this, R.array.sizes, android.R.layout.simple_spinner_item);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- s.setAdapter(adapter);
- s.setSelection(state.getInt("size")-1);
- s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- public void onItemSelected(AdapterView<?> 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();
- }
-
-}
+++ /dev/null
-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<Point> path=null;
- private List<Line> 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; i<tilesetRows; i++) {
- for (int j=0; j<tilesetCols; j++) {
- tile[k] = Bitmap.createBitmap(tileset, j*tileWidth, i*tileHeight, tileWidth, tileHeight, null, false);
- tile[k].setDensity(Bitmap.DENSITY_NONE);
- k++;
- }
- }
- tileWidth = tile[0].getWidth();
- tileHeight = tile[0].getHeight();
- }
-
- private void loadBackground() {
- BitmapFactory.Options ops = new BitmapFactory.Options();
- ops.inScaled = false;
- bg = BitmapFactory.decodeResource(getResources(), R.drawable.kshisen_bgnd, ops);
- bg.setDensity(Bitmap.DENSITY_NONE);
- }
-
- private void registerTimer() {
- if (timer!=null) return; // Already registered
- timerHandler = new Handler() {
- public void handleMessage(Message msg) {
- onUpdateTime();
- }
- };
- timer=new Timer();
- timer.scheduleAtFixedRate(new TimerTask() {
- public void run() {
- timerHandler.sendEmptyMessage(Activity.RESULT_OK);
- }
- }, 0, 1000);
- timerRegistered=true;
- }
-
- private void unregisterTimer() {
- if (timer==null) return; // Already unregistered
- timer.cancel();
- timer = null;
- timerHandler = null;
- timerRegistered=false;
- }
-
- public void pauseTime() {
- updateTime();
- baseTime = playTime;
- startTime = System.currentTimeMillis();
-
- }
-
- public void resumeTime() {
- startTime = System.currentTimeMillis();
- updateTime();
- }
-
- private void updateTime() {
- if (cstate!=StatePlay.GAMEOVER) {
- playTime = (System.currentTimeMillis()-startTime)/1000+baseTime;
- }
- }
-
- private void initializeGame() {
- loadBackground();
- loadTileset();
- screenWidth=getWidth();
- screenHeight=getHeight();
- //undo.sensitive=false;
- pstate=StatePaint.BOARD;
- app.newPlay();
- control(StatePlay.IDLE);
- startTime=System.currentTimeMillis();
- playTime=0;
- baseTime=0;
- if (app.timeCounter && !timerRegistered) {
- registerTimer();
- }
- pairs=app.board.getPairs(1);
- }
-
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle item selection
- switch (item.getItemId()) {
- case R.id.hint:
- this.postDelayed(new Runnable() { public void run() { onHintActivate(); } }, 100);
- return true;
- case R.id.undo:
- this.postDelayed(new Runnable() { public void run() { onUndoActivate(); } }, 100);
- return true;
- case R.id.clean:
- this.postDelayed(new Runnable() { public void run() { reset(); } }, 100);
- return true;
- case R.id.options:
- return true;
- case R.id.about:
- return true;
- default:
- return false;
- }
- }
-
- public void reset() {
- control(StatePlay.UNINITIALIZED);
- paint(StatePaint.BOARD);
- }
-
- private void onHintActivate() {
- if (cstate!=StatePlay.GAMEOVER) {
- pairs=app.board.getPairs(1);
- paint(StatePaint.HINT);
- app.sleep(10);
- paint(StatePaint.BOARD);
- control(StatePlay.IDLE);
- }
- }
-
- private void onUndoActivate() {
- if (app.board.getCanUndo()) {
- if (cstate==StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) {
- // Reprogram the time update that had been
- // deactivated with the game over status
- registerTimer();
- }
- app.board.undo();
- paint(StatePaint.BOARD);
- //undo.sensitive=app.board.getCanUndo();
- control(StatePlay.IDLE);
- }
- }
-
- public void onTimeCounterActivate() {
- if (app.timeCounter && cstate!=StatePlay.GAMEOVER && !timerRegistered) {
- // Reprogram the time update that had been
- // deactivated with the time_counter=false
- registerTimer();
- }
- }
-
- private void onUpdateTime() {
- paint(pstate);
- if (!(app.timeCounter && cstate!=StatePlay.GAMEOVER)) {
- unregisterTimer();
- }
- }
-
- public void drawMessage(Canvas canvas, int x, int y, boolean centered, String message, String color, float textSize) {
- Paint paint = new Paint();
- paint.setColor(Color.parseColor(color));
- paint.setLinearText(true);
- paint.setAntiAlias(true);
- paint.setTextAlign(centered?Align.CENTER:Align.LEFT);
- paint.setTypeface(Typeface.SANS_SERIF);
- paint.setFakeBoldText(true);
- paint.setTextSize(textSize);
- canvas.drawText(message, x, y, paint);
- }
-
- public void repaint() {
- if (surfaceHolder == null) return;
- try {
- if (canvas == null) canvas = surfaceHolder.lockCanvas(null);
- if (canvas == null) return;
- if (cstate==StatePlay.UNINITIALIZED) initializeGame();
- synchronized (surfaceHolder) {
- doDraw(canvas);
- }
- } finally {
- if (canvas != null) {
- surfaceHolder.unlockCanvasAndPost(canvas);
- canvas = null;
- }
- }
- }
-
- protected void doDraw(Canvas canvas) {
- try {
- // Double buffering
- // Bitmap buffer = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
- //Canvas cbuffer = new Canvas(buffer);
- Canvas cbuffer = canvas;
- if (canvas == null) return;
-
- //super.onDraw(canvas);
-
- // Board upper left corner on screen
- int x0=0;
- int y0=0;
-
- if (app!=null && app.board!=null) {
- x0=(screenWidth-app.board.boardSize[1]*tileWidth)/2;
- y0=(screenHeight-app.board.boardSize[0]*tileHeight)/2;
- }
-
- int red = Color.parseColor("#FF0000");
- int orange = Color.parseColor("#F0C000");
- Paint paint = new Paint();
- paint.setFlags(Paint.ANTI_ALIAS_FLAG);
-
- // Background & board painting
- switch (pstate) {
- case BOARD:
- case SELECTED1:
- case SELECTED2:
- case MATCHED:
- case WIN:
- case LOSE:
- case HINT:
- case TIME:
- // Background painting
- int bgWidth = bg.getWidth();
- int bgHeight = bg.getHeight();
- for (int i=0; i<screenHeight/bgHeight+1; i++) {
- for (int j=0; j<screenWidth/bgWidth+1; j++) {
- cbuffer.drawBitmap(bg, j*bgWidth, i*bgHeight, paint);
- }
- }
-
- // Board painting
- // Max visible size: 7x17
- if (app!=null && app.board!=null) {
- for (int i=0;i<app.board.boardSize[0];i++) {
- for (int j=0;j<app.board.boardSize[1];j++) {
- // Tiles are 56px height, 40px width each
- char piece=app.board.board[i][j];
- if (piece!=0) {
- cbuffer.drawBitmap(tile[piece], x0+j*tileWidth, y0+i*tileHeight, paint);
- }
- }
- }
- }
- break;
- }
-
- // Red rectangle for selection 1
- switch (pstate) {
- case SELECTED1:
- case SELECTED2:
- case MATCHED:
- paint.setColor(red);
- paint.setStyle(Style.STROKE);
- paint.setStrokeCap(Cap.ROUND);
- paint.setStrokeJoin(Join.ROUND);
- paint.setStrokeWidth(3);
- cbuffer.drawRect(new Rect(
- x0+selection1[1]*tileWidth-2,
- y0+selection1[0]*tileHeight-2,
- x0+selection1[1]*tileWidth-2+tileWidth+2*2,
- y0+selection1[0]*tileHeight-2+tileHeight+2*2),
- paint);
- break;
- }
-
- // Red rectangle for selection 2
- switch (pstate) {
- case SELECTED2:
- case MATCHED:
- paint.setColor(red);
- paint.setStyle(Style.STROKE);
- paint.setStrokeCap(Cap.ROUND);
- paint.setStrokeJoin(Join.ROUND);
- paint.setStrokeWidth(3);
- cbuffer.drawRect(new Rect(
- x0+selection2[1]*tileWidth-2,
- y0+selection2[0]*tileHeight-2,
- x0+selection2[1]*tileWidth-2+tileWidth+2*2,
- y0+selection2[0]*tileHeight-2+tileHeight+2*2),
- paint);
- break;
- }
-
- // Matching path
- switch (pstate) {
- case MATCHED:
- paint.setColor(red);
- paint.setStyle(Style.STROKE);
- paint.setStrokeCap(Cap.ROUND);
- paint.setStrokeJoin(Join.ROUND);
- paint.setStrokeWidth(3);
-
- 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;
- }
- }
- break;
- }
-
- // Orange hint rectangles
- switch (pstate) {
- case HINT:
- if (pairs!=null && pairs.size()>0) {
- 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<lines.length; i++) {
- drawMessage(cbuffer,1,l,false,lines[i],"#FFFF00",30);
- l+=30;
- }
- }
- */
-
- // Double buffer dumping
- // canvas.drawBitmap(buffer, 0, 0, null);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction()==MotionEvent.ACTION_DOWN) {
- onClick(Math.round(event.getX()),Math.round(event.getY()));
- }
- return super.onTouchEvent(event);
- }
-
- private void onClick(int x, int y) {
- try {
- int i=(y-(screenHeight-app.board.boardSize[0]*tileHeight)/2)/tileHeight;
- int j=(x-(screenWidth-app.board.boardSize[1]*tileWidth)/2)/tileWidth;
-
- switch (cstate) {
- case IDLE:
- if (i>=0 &&
- i<app.board.boardSize[0] &&
- j>=0 && j<app.board.boardSize[1] &&
- app.board.board[i][j]!=0) {
- selection1[0]=i;
- selection1[1]=j;
- paint(StatePaint.SELECTED1);
- control(StatePlay.SELECTED1);
- }
- break;
- case SELECTED1:
- if (i>=0 && i<app.board.boardSize[0] &&
- j>=0 && j<app.board.boardSize[1] &&
- app.board.board[i][j]!=0) {
- if (i==selection1[0] && j==selection1[1]) {
- paint(StatePaint.BOARD);
- control(StatePlay.IDLE);
- } else {
- selection2[0]=i;
- selection2[1]=j;
- paint(StatePaint.SELECTED2);
-
- Point a=new Point(selection1[0],selection1[1]);
- Point b=new Point(selection2[0],selection2[1]);
- path=app.board.getPath(a,b);
- paint(StatePaint.MATCHED);
- app.sleep(2);
- paint(StatePaint.BOARD);
- if (path.size()>0) {
- 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<height/bgHeight+1; i++) {
- for (int j=0; j<width/bgWidth+1; j++) {
- canvas.drawBitmap(bg, j*bgWidth, i*bgHeight, paint);
- }
- }
-
- canvas.drawBitmap(tile[randomtile], x, y, paint);
-
- repaint();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getActionMasked()==MotionEvent.ACTION_DOWN) {
- //computeNextTarget();
- //nextx=Math.round(event.getX());
- //nexty=Math.round(event.getY());
- }
- return super.onTouchEvent(event);
- }
-
- private void initialize() {
- width = getWidth();
- height = getHeight();
-
- bg = BitmapFactory.decodeResource(getResources(), R.drawable.kshisen_bgnd);
- Bitmap tileset = BitmapFactory.decodeResource(getResources(), R.drawable.tileset);
-
- // The tile set has 4 rows x 9 columns
- tsrows = 4;
- tscols = 9;
- twidth = tileset.getWidth()/tscols;
- theight = tileset.getHeight()/tsrows;
- tile = new Bitmap[tsrows*tscols];
- int k=0;
- for (int i=0; i<tsrows; i++) {
- for (int j=0; j<tscols; j++) {
- tile[k] = Bitmap.createBitmap(tileset, j*twidth, i*theight, twidth, theight, null, false);
- k++;
- }
- }
-
- x = width/2;
- y = height/2;
-
- computeNextTarget();
-
- initialized = true;
- }
-
- private void computeNextTarget() {
- startTime = System.currentTimeMillis();
- prevx = x;
- prevy = y;
- nextx = (int) Math.floor(Math.random() * width);
- nexty = (int) Math.floor(Math.random() * height);
- randomtile = (int) Math.floor(Math.random() * tile.length);
-
- paint = new Paint();
- paint.setColor(Color.parseColor("#006666"));
- paint.setFlags(Paint.ANTI_ALIAS_FLAG);
- }
-*/
-}
\ No newline at end of file