05 Jan 2011, 19:56
Generic-user-small

Marshall Farrier (67 posts)

I’ve currently made it through chap. 6 but wanted to make a few changes:

1) Make the letters blue when they are not givens but black for the givens 2) Make the givens unchangeable

For the first idea, I figure we define a new color (#ff000000, for example, as puzzle_foreground_givens) in the color XML under resources. Then I would think I’d need to modify the onDraw() method in PuzzleView.java under the “Draw the numbers” comment. But that’s where I’m having trouble. How would you one color on some cells and another color elsewhere?

In general, what I thought might be the easiest way to do this would be to check the appropriate puzzle string in Game.java for a ‘0’ character or something else. If it’s ‘0’, use blue and allow changes. If there’s something there in the puzzle string, then color it black, and don’t allow changes.

Any ideas how to do this?

06 Jan 2011, 15:55
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

It sounds like you’re on the right track so far.

To use one color on some cells and another color elsewhere you can use the same technique shown a few lines later to draw the hints. First you fetch the different colors from resources (R.color.puzzle_foreground and R.color.puzzle_foreground_givens) and save them into variables or an array. Then you call foreground.setColor(xx) before calling the canvas.drawText() method, where xx is an expression that yields the correct color.

You could use an expression like (isGiven ? givenColor : regularColor). If you like you could make isGiven a function like this.game.isGiven(i,j) (similar to getTileString) and use it both in the drawing code and in the code you write that checks whether or not changes are allowed.

There are many ways to do it depending on your personal preferences and style. Working through this yourself will be a great exercise to help you learn more about Android and Java.

06 Jan 2011, 17:39
Generic-user-small

Marshall Farrier (67 posts)

Thanks! I’m hoping this will get me to a deeper understanding of how it actually works.

First question, starting off with creating the isGiven() method: Will the difficulty level be stored automatically in such a way that is retrievable for continued games? In other words, is the line which defines diff in the following going to work properly in all situations?

[code] // in Game public boolean isGiven(int i, int j) { int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY); … return false; }[/code]

06 Jan 2011, 17:52
Generic-user-small

Marshall Farrier (67 posts)

Here’s my provisional isGiven() method:

public boolean isGiven(int i, int j) {
		int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
		int loc = 9 * i + j;
		if (loc > 80) return false;
		switch (diff) {
		case DIFFICULTY_EASY:
			if (easyPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_MEDIUM:
			if (mediumPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_HARD:
			if (hardPuzzle.charAt(loc) != '0') return true;
			else return false;
		}
		return false;
	}
06 Jan 2011, 18:38
Generic-user-small

Marshall Farrier (67 posts)

Ok, that didn’t work right, but I figured out why: The last line of onCreate() in Game sets KEY_DIFFICULTY to DIFFICULTY_CONTINUE. So, to solve that, I created another stored value with this:

public static final String ORIG_DIFFICULTY = "org.example.sudoku.orig_diff";

Then I added at the end of onCreate() (in Game):

getIntent().putExtra(ORIG_DIFFICULTY, diff);

Then I just changed KEY_DIFFICULTY to ORIG_DIFFICULTY in the above code, and I did this in onDraw() in PuzzleView:

for (int i = 0; i < 9; ++i) {
			for (int j = 0; j < 9; ++j) {
				if (game.isGiven(i, j)) {
					Log.d(TAG, "(" + i + ", " + j + " is a given");
					foreground.setColor(getResources().getColor(R.color.puzzle_foreground_givens));
				}
				else {
					Log.d(TAG, "(" + i + ", " + j + " is not a given");
					foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
				}
				canvas.drawText(game.getTileString(i, j), i * width + x, j * height + y, foreground);
			}
		}

Now the log messages show me that isGiven() is working correctly. But (!!!) I still get the weird result that SOME of the givens show up as black but others show up as blue–even though the log says that isGiven() is firing correctly and that the color should be set properly. Example: In the medium puzzle, the ‘6’ appears black in field (0, 0) but the ‘5’ appears blue. And LogCat says “(0, 0 is a given / (0, 1 is a given / (0, 2 is not a given … “.

Just bizarre as far as I can see!!?? Any ideas??

06 Jan 2011, 18:44
Generic-user-small

Marshall Farrier (67 posts)

I should also perhaps add that I did remove the foreground.setColor(…) line that was originally just after Paint foreground = new Paint(…);

06 Jan 2011, 18:51
Generic-user-small

Marshall Farrier (67 posts)

I tried one more addition that I thought might make the code cleaner, but it still isn’t working. Here’s the entire relevant block (the log indicates to me that the isGiven() method is working fine):

Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
		
		foreground.setStyle(Style.FILL);
		foreground.setTextSize(height * 0.75f);
		foreground.setTextScaleX(width / height);
		foreground.setTextAlign(Paint.Align.CENTER);
		
		int[] col = {getResources().getColor(R.color.puzzle_foreground_givens),
				getResources().getColor(R.color.puzzle_foreground)};
		
		// 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) {
				if (game.isGiven(i, j)) {
					Log.d(TAG, "(" + i + ", " + j + ") is a given");
					foreground.setColor(col[0]);
				}
				else {
					Log.d(TAG, "(" + i + ", " + j + ") is not a given");
					foreground.setColor(col[1]);
				}
				canvas.drawText(game.getTileString(i, j), i * width + x, j * height + y, foreground);
			}
		}
06 Jan 2011, 20:05
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

You’ve almost got it. Here’s a hint: take another look at your isGiven() function.

06 Jan 2011, 21:46
Generic-user-small

Marshall Farrier (67 posts)

I did modify the KEY_DIFFICULTY constant to ORIG_DIFFICULTY (with appropriate modifications elsewhere), and the log shows it returning true or false exactly where it is supposed to. The color is just sometimes right, sometimes wrong.

06 Jan 2011, 22:59
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

It’s not returning true or false where it’s supposed to. To quote the twilight zone, “There is nothing wrong with your television set. We will control the horizontal. We will control the vertical.”

07 Jan 2011, 00:11
Generic-user-small

Marshall Farrier (67 posts)

Hmmm… ok, here’s the current code:

public boolean isGiven(int i, int j) {
		int diff = getIntent().getIntExtra(ORIG_DIFFICULTY, DIFFICULTY_EASY);
		int loc = 9 * i + j;
		if (loc > 80) return false;
		switch (diff) {
		case DIFFICULTY_EASY:
			if (easyPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_MEDIUM:
			if (mediumPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_HARD:
			if (hardPuzzle.charAt(loc) != '0') return true;
			else return false;
		}
		Log.d(TAG, "diff is " + diff);
		return false;
	}

And, while eclipse unfortunately won’t let me copy LogCat, here’s what it says when I click medium puzzle: (0, 0) is a given (0, 1) is a given (0, 2) is not a given …

And it has them all exactly right. Code behind the log is:

for (int i = 0; i < 9; ++i) {
			for (int j = 0; j < 9; ++j) {
				if (game.isGiven(i, j)) {
					Log.d(TAG, "(" + i + ", " + j + ") is a given");
					foreground.setColor(col[0]);
				}
				else {
					Log.d(TAG, "(" + i + ", " + j + ") is not a given");
					foreground.setColor(col[1]);
				}
				canvas.drawText(game.getTileString(i, j), i * width + x, j * height + y, foreground);
			}
		}

I’m not seeing how it can announce “is a given” or “is not a given” correctly every time, but get the color wrong more than half the time??

07 Jan 2011, 00:19
Generic-user-small

Marshall Farrier (67 posts)

Also, when I modify isGiven() like this:

public boolean isGiven(int i, int j) {
		int diff = getIntent().getIntExtra(ORIG_DIFFICULTY, DIFFICULTY_EASY);
		int loc = 9 * i + j;
		if (loc > 80) return false;
		
		switch (diff) {
		case DIFFICULTY_EASY:
			Log.d("isGiven()", String.valueOf(easyPuzzle.charAt(loc)));
			if (easyPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_MEDIUM:
			Log.d("isGiven()", String.valueOf(mediumPuzzle.charAt(loc)));
			if (mediumPuzzle.charAt(loc) != '0') return true;
			else return false;
		case DIFFICULTY_HARD:
			Log.d("isGiven()", String.valueOf(hardPuzzle.charAt(loc)));
			if (hardPuzzle.charAt(loc) != '0') return true;
			else return false;
		}
		Log.d(TAG, "diff is " + diff);
		return false;
	}

it correctly shows the numeric value of each square… ??

07 Jan 2011, 14:15
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

It should say:

(0, 0) is a given (0, 1) is not a given (0, 2) is not a given … (1, 0) is a given

The first parameter (i) is the horizontal, or x value, and the second parameter (j) is the vertical, or y value.

07 Jan 2011, 15:25
Generic-user-small

Marshall Farrier (67 posts)

ah, ok, I thought I was going crazy here! Thanks! :)

07 Jan 2011, 16:06
Generic-user-small

Marshall Farrier (67 posts)

Success!

After that snafu (which just involved changing 9 * i + j to 9 * j + i) I had to do this:

1) Modify onCreate() again at the end so that if you’re continuing the game, you don’t overwrite ORIG_DIFFICULTY. That just meant changing the value only if (diff != DIFFICULTY_CONTINUE)

2) Add as first line of setTileIfValid(): if (isGiven(x, y) return false;)

I could also do some additional stuff, such as not letting the keypad show up for givens and not having the screen shake when you try to enter a value for a given. But I think that’s a good start, and it would probably be better at the moment to work through the further chapters than to try to make the ultimate Sudoku :)

Thanks very much, Ed!

07 Jan 2011, 18:49
Burnette_ed_pragsmall

Ed Burnette (1316 posts)

You’re welcome, good luck.

17 Apr 2013, 21:57
Generic-user-small

Adam Jasinski (2 posts)

Hi everyone. I’ve tried to implement this code created by Marshall but i still can’t figure out what order all these segments should have in Game.java

Could anyone who succeded with that show exactly where those parts are supposed to be?

18 May 2013, 11:53
Generic-user-small

Anna Harris (3 posts)

I had the same problem. But, i did not get completed 100%. Anybody please help who has completed successfully?

  You must be logged in to comment