1

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

4

0 回答 0