I have make a view class like this-
public class PuzzleView extends View {
public PuzzleView(Context context, AttributeSet attrs)
{
super(context, attrs);
bmap = BitmapFactory.decodeResource(getResources(), R.drawable.da);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// ...
setId(ID);
// TODO Auto-generated constructor stub
}
Bitmap bmap;
private static final String TAG = "Sudoku";
private static final String SELX = "selX";
private static final String SELY = "selY";
private static final String VIEW_STATE = "viewState";
private static final int ID = 42;
private float width;
// width of one tile
private float height;// height of one tile
private int selX; // X index of selection
private int selY; // Y index of selection
private final Rect selRect = new Rect();
private final Game game;
@Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Log.d(TAG, "onSaveInstanceState");
Bundle bundle = new Bundle();
bundle.putInt(SELX, selX);
bundle.putInt(SELY, selY);
bundle.putParcelable(VIEW_STATE, p);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Log.d(TAG, "onRestoreInstanceState");
Bundle bundle = (Bundle) state;
select(bundle.getInt(SELX), bundle.getInt(SELY));
super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged: width " + width + ", height " + height);
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
canvas.drawBitmap(bmap, 0, 0, paint);
// Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// Draw the board...
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
// Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), light);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height, dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// Draw the numbers...
// Define color and style for numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
// Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in X: use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y: measure ascent/descent first
float y = height / 2 - (fm.ascent + fm.descent) / 2;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.game.getTileString(i, j), i * width + x, j
* height + y, foreground);
}
}
if (Prefs.getHints(getContext())) {
// Draw the hints...
// Pick a hint color based on #moves left
Paint hint = new Paint();
int c[] = { getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2), };
Rect r = new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft = 9 - game.getUsedTiles(i, j).length;
if (movesleft < c.length) {
getRect(i, j, r);
hint.setColor(c[movesleft]);
canvas.drawRect(r, hint);
}
}
}
}
// Draw the selection...
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int) (event.getX() / width), (int) (event.getY() / height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
return true;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG, "onKeyDown: keycode=" + keyCode + ", event=" + event);
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:
setSelectedTile(0);
break;
case KeyEvent.KEYCODE_1:
setSelectedTile(1);
break;
case KeyEvent.KEYCODE_2:
setSelectedTile(2);
break;
case KeyEvent.KEYCODE_3:
setSelectedTile(3);
break;
case KeyEvent.KEYCODE_4:
setSelectedTile(4);
break;
case KeyEvent.KEYCODE_5:
setSelectedTile(5);
break;
case KeyEvent.KEYCODE_6:
setSelectedTile(6);
break;
case KeyEvent.KEYCODE_7:
setSelectedTile(7);
break;
case KeyEvent.KEYCODE_8:
setSelectedTile(8);
break;
case KeyEvent.KEYCODE_9:
setSelectedTile(9);
break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
break;
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();// may change hints
} else {
// Number is not valid for this tile
// Log.d(TAG, "setSelectedTile: invalid: " + tile);
// startAnimation(AnimationUtils.loadAnimation(game,
// R.anim.shake));
}
}
private void select(int x, int y) {
invalidate(selRect);
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);
}
private void getRect(int x, int y, Rect rect) {
rect.set((int) (x * width), (int) (y * height),
(int) (x * width + width), (int) (y * height + height));
}
}
I have make xml of this view like this:-
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<org.example.sudoku.PuzzleView
android:id="@+id/puzzleView"
android:layout_width="fill_parent"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
</RelativeLayout>
I use this xml in my activity its showing good but when I want to fill cell by dialog occur null pointer. code is as:-
public class Game extends Activity {
private static final String TAG = "Sudoku";
public static final String KEY_DIFFICULTY = "org.example.sudoku.difficulty";
private static final String PREF_PUZZLE = "puzzle";
public static final int DIFFICULTY_EASY = 0;
public static final int DIFFICULTY_MEDIUM = 1;
public static final int DIFFICULTY_HARD = 2;
protected static final int DIFFICULTY_CONTINUE = -1;
private int puzzle[];
private final String easyPuzzle = "360000000004230800000004200"
+ "070460003820000014500013020" + "001900000007048300000000045";
private final String mediumPuzzle = "650000070000506000014000005"
+ "007009000002314700000700800" + "500000630000201000030000097";
private final String hardPuzzle = "009000000080605020501078000"
+ "000000700706040102004000000" + "000720903090301080000000600";
private PuzzleView objpuzzleview;
private ViewGroup objviewgroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// puzzleView=new PuzzleView(this);
Log.d(TAG, "onCreate");
setContentView(R.layout.gameview);
objviewgroup =(ViewGroup)findViewById(R.id.mainlayout);
objpuzzleview = (PuzzleView)findViewById(R.id.puzzleView);
//objpuzzleview.requestFocus();
int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
puzzle = getPuzzle(diff);
calculateUsedTiles();
//
// ...
// If the activity is restarted, do a continue next time
getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
}
/** Convert an array into a puzzle string */
static private String toPuzzleString(int[] puz) {
StringBuilder buf = new StringBuilder();
for (int element : puz) {
buf.append(element);
}
return buf.toString();
}
/** Convert a puzzle string into an array */
static protected int[] fromPuzzleString(String string) {
int[] puz = new int[string.length()];
System.out.println(puz);
for (int i = 0; i < puz.length; i++) {
puz[i] = string.charAt(i) - '0';
}
return puz;
}
/** Return the tile at the given coordinates */
private int getTile(int x, int y) {
return puzzle[y * 9 + x];
}
/** Change the tile at the given coordinates */
private void setTile(int x, int y, int value) {
puzzle[y * 9 + x] = value;
}
/** Return a string for the tile at the given coordinates */
protected String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0)
return "";
else
return String.valueOf(v);
}
/** Change the tile only if it's a valid move */
protected boolean setTileIfValid(int x, int y, int value) {
int tiles[] = getUsedTiles(x, y);
if (value != 0) {
for (int tile : tiles) {
if (tile == value)
return false;
}
}
setTile(x, y, value);
calculateUsedTiles();
return true;
}
/** Open the keypad if there are any valid moves */
protected void showKeypadOrError(int x, int y) {
int tiles[] = getUsedTiles(x, y);
if (tiles.length == 9) {
Toast toast = Toast.makeText(this, R.string.no_moves_label,
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
} else {
Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles));
///////////////////////////////////////////Exception is here PuzzeleView=null?why
**Dialog v = new Keypad(this, tiles, objpuzzleview);
v.show();**
}
}
/** Cache of used tiles */
private final int used[][][] = new int[9][9][];
/** Return cached used tiles visible from the given coords */
protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}
/** Compute the two dimensional array of used tiles */
private void calculateUsedTiles() {
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
used[x][y] = calculateUsedTiles(x, y);
// Log.d(TAG, "used[" + x + "][" + y + "] = "
// + toPuzzleString(used[x][y]));
}
}
}
/** Compute the used tiles visible from this position */
private int[] calculateUsedTiles(int x, int y) {
int c[] = new int[9];
// horizontal
for (int i = 0; i < 9; i++) {
if (i == x)
continue;
int t = getTile(i, y);
if (t != 0)
c[t - 1] = t;
}
// vertical
for (int i = 0; i < 9; i++) {
if (i == y)
continue;
int t = getTile(x, i);
if (t != 0)
c[t - 1] = t;
}
// same cell block
int startx = (x / 3) * 3;
int starty = (y / 3) * 3;
for (int i = startx; i < startx + 3; i++) {
for (int j = starty; j < starty + 3; j++) {
if (i == x && j == y)
continue;
int t = getTile(i, j);
if (t != 0)
c[t - 1] = t;
}
}
// compress
int nused = 0;
for (int t : c) {
if (t != 0)
nused++;
}
int c1[] = new int[nused];
nused = 0;
for (int t : c) {
if (t != 0)
c1[nused++] = t;
}
return c1;
}
} Here is logcat:-
01-20 19:38:16.225: E/AndroidRuntime(2371): FATAL EXCEPTION: main
01-20 19:38:16.225: E/AndroidRuntime(2371): java.lang.NullPointerException
01-20 19:38:16.225: E/AndroidRuntime(2371): at org.example.sudoku.Keypad.returnResult(Keypad.java:86)
01-20 19:38:16.225: E/AndroidRuntime(2371): at org.example.sudoku.Keypad.access$0(Keypad.java:85)
01-20 19:38:16.225: E/AndroidRuntime(2371): at org.example.sudoku.Keypad$1.onClick(Keypad.java:117)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.view.View.performClick(View.java:4084)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.view.View$PerformClick.run(View.java:16966)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.os.Handler.handleCallback(Handler.java:615)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.os.Handler.dispatchMessage(Handler.java:92)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.os.Looper.loop(Looper.java:137)
01-20 19:38:16.225: E/AndroidRuntime(2371): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-20 19:38:16.225: E/AndroidRuntime(2371): at java.lang.reflect.Method.invokeNative(Native Method)
01-20 19:38:16.225: E/AndroidRuntime(2371): at java.lang.reflect.Method.invoke(Method.java:511)
01-20 19:38:16.225: E/AndroidRuntime(2371): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-20 19:38:16.225: E/AndroidRuntime(2371): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-20 19:38:16.225: E/AndroidRuntime(2371): at dalvik.system.NativeStart.main(Native Method)
//////////////////// i add my KeyPad class?????
public class Keypad extends Dialog {
protected static final String TAG = "Sudoku";
private final View keys[] = new View[9];
private View keypad;
private final int useds[];
private final PuzzleView puzzleView;
public Keypad(Context context, int useds[], PuzzleView puzzleView) {
super(context);
this.useds = useds;
this.puzzleView = puzzleView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.keypad_title);
setContentView(R.layout.keypad);
findViews();
for (int element : useds) {
if (element != 0)
keys[element - 1].setVisibility(View.VISIBLE);
}
setListeners();
}
// ...
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int tile = 0;
switch (keyCode) {
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:
tile = 0;
break;
case KeyEvent.KEYCODE_1:
tile = 1;
break;
case KeyEvent.KEYCODE_2:
tile = 2;
break;
case KeyEvent.KEYCODE_3:
tile = 3;
break;
case KeyEvent.KEYCODE_4:
tile = 4;
break;
case KeyEvent.KEYCODE_5:
tile = 5;
break;
case KeyEvent.KEYCODE_6:
tile = 6;
break;
case KeyEvent.KEYCODE_7:
tile = 7;
break;
case KeyEvent.KEYCODE_8:
tile = 8;
break;
case KeyEvent.KEYCODE_9:
tile = 9;
break;
default:
return super.onKeyDown(keyCode, event);
}
if (isValid(tile)) {
returnResult(tile);
}
return true;
}
/** Return the chosen tile to the caller */
private void returnResult(int tile) {
puzzleView.setSelectedTile(tile);
dismiss();
}
private boolean isValid(int tile) {
for (int t : useds) {
if (tile == t)
return false;
}
return true;
}
private void findViews() {
keypad = findViewById(R.id.keypad);
keys[0] = findViewById(R.id.keypad_1);
keys[1] = findViewById(R.id.keypad_2);
keys[2] = findViewById(R.id.keypad_3);
keys[3] = findViewById(R.id.keypad_4);
keys[4] = findViewById(R.id.keypad_5);
keys[5] = findViewById(R.id.keypad_6);
keys[6] = findViewById(R.id.keypad_7);
keys[7] = findViewById(R.id.keypad_8);
keys[8] = findViewById(R.id.keypad_9);
}
private void setListeners() {
for (int i = 0; i < keys.length; i++) {
final int t = i + 1;
keys[i].setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
returnResult(t);
}
});
}
keypad.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
returnResult(0);
}
});
}
}
please anyone suggest me ASAP.thanks in advance