29 Apr 2013, 03:23
Generic-user-small

Matty M (3 posts)

I am a beginner so I have no idea how to fix the problem I am having. My code matches the book exactly. Every time I click on a tile in my Sudoku game, my app closes. I have used logcat to figure out that the problem is that I am getting a null pointer exception which is causing all the problems.

The problem is in my tiles array under the showKeypadOrError method is showing up as null because my getUsedTiles method is returning a null for used[x][y] even though x and y are number themselves.

I hope this makes sense as far as the problem I am having. Any ideas how to fix this problem?

Thanks for any help I can get.

29 Apr 2013, 07:28
Generic-user-small

Anthony Shaw (131 posts)

You may think that your code matches the book, but it almost certainly does not. If you post the code here and give an indication of the line number where the null pointer is happening I will try and help you identify the root problem.

29 Apr 2013, 15:26
Generic-user-small

Matty M (3 posts)

Here is my code. In the showKeypadOrError method tiles[] is showing as a null which I think is because the used[x][y] in getUsedTiles is null. This is where I think I am getting a null pointer exception.


import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.widget.Toast;

public class Game extends Activity {

	private static final String TAG = "Sudoku";
	
	public static final String KEY_DIFFICULTY = "com.mjm.sudoku.difficulty";
	public static final int DIFFICULTY_EASY = 0;
	public static final int DIFFICULTY_MEDIUM = 1;
	public static final int DIFFICULTY_HARD = 2;
	private final String easyPuzzle = "360000000004230800000004200" +
			"070460003820000014500013020001900000007048300000000045";
	private final String mediumPuzzle = "650000070000506000014000005" +
			"007009000002314700000700800500000630000201000030000097";
	private final String hardPuzzle = "009000000080605020501078000" +
			"000000700706040102004000000000720903090301080000000600";
	
	private int puzzle [] = new int[9 * 9];
	private final int used[][][] = new int[9][9][];
	
	private PuzzleView puzzleView;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(TAG, "onCreate");
		
		int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
		puzzle = getPuzzle(diff);
		calculateUsedTiles();
		
		puzzleView = new PuzzleView(this);
		setContentView(puzzleView);
		puzzleView.requestFocus();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.game, menu);
		return true;
	}
	
	protected void showKeypadOrError(int x, int y) {
		Log.d(TAG, "showKeypadOrError x: " + x + ", y: " + y);
		int tiles[] = getUsedTiles(x,y);
		Log.d(TAG, "showKeypadOrError tiles: " + tiles);
		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));
			Dialog v = new Keypad(this, tiles, puzzleView);
			v.show();
		}
	}
	
	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;
	}
	
	//TODO: FIX THIS PROBLEM!!!! used is null which makes tiles[] null
	protected int[] getUsedTiles(int x, int y) {
		Log.d(TAG, "getUsedTiles x: " + x + ", y: " + y);
		Log.d(TAG, "getUsedTiles used: " + used[x][y]);
		return used[x][y];
	}
	
	private void calculateUsedTiles() {
		for (int x = 0; x < 9; x++) {
			for(int y = 0; y < 0; y++) {
				used[x][y] = calculatedUsedTiles(x,y);
			}
		}
	}
	
	private int[] calculatedUsedTiles(int x, int y) {
		int c[] = new int[9];
		//horizontal
		for (int i = 0; i < 9; i++) {
			if(i == y)
				continue;
			int t = getTile(x, i);
			if (t!= 0)
				c[t-1] = t;
		}
		//vertical
		for (int i = 0; i < 9; i++) {
			if (i==x)
				continue;
			int t = getTile(i, y);
			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;
	}
	
	private int[] getPuzzle(int diff) {
		String puz;
		//TODO: Continue last game
		switch(diff) {
			case DIFFICULTY_HARD:
				puz = hardPuzzle;
				break;
			case DIFFICULTY_MEDIUM:
				puz = mediumPuzzle;
				break;
			case DIFFICULTY_EASY:
				default:
				puz = easyPuzzle;
				break;
		}
		return fromPuzzleString(puz);
	}
	
	static private String toPuzzleString(int[] puz) {
		StringBuilder buf = new StringBuilder();
		for (int element: puz) {
			buf.append(element);
		}
		return buf.toString();
	}
	
	static protected int[] fromPuzzleString(String string) {
		int[] puz = new int[string.length()];
		for (int i = 0; i < puz.length; i++) {
			puz[i] = string.charAt(i) - '0';
		}
		return puz;
	}
	
	private int getTile(int x, int y) {
		return puzzle[y*9 + x];
	}
	
	private void setTile(int x, int y, int value) {
		puzzle[y*9+x] = value;
	}
	
	protected String getTileString(int x, int y) {
		int v = getTile(x,y);
		if (v == 0)
			return "";
		else
			return String.valueOf(v);
	}

}

29 Apr 2013, 18:10
Generic-user-small

Anthony Shaw (131 posts)

What do the two log messages in the getUsedTiles() method show? If used is indeed null here it would seem to indicate either that caculateUsedTiles() has not been called or the methods that it called failed in some way.

29 Apr 2013, 23:58
Generic-user-small

Matty M (3 posts)

You were right. My calculateUsedtiles() method had a tiny typo in it. Thank you for the help.

30 Apr 2013, 10:26
Generic-user-small

Anthony Shaw (131 posts)

Glad to help.

  You must be logged in to comment