Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to launch a dialog box with a button when Game is complete?
    text
    copied!<p>Please help with the following code - I need a dialog box with a button to appear when the game puzzle is completed. Thank you!</p> <p>Here's the code:</p> <p>Sudoku.java</p> <pre><code>package org.example.sudoku; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; public class Sudoku extends Activity implements OnClickListener { private static final String TAG = "Sudoku"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Set up click listeners for all the buttons View continueButton = findViewById(R.id.continue_button); continueButton.setOnClickListener(this); View newButton = findViewById(R.id.new_button); newButton.setOnClickListener(this); View aboutButton = findViewById(R.id.about_button); aboutButton.setOnClickListener(this); View exitButton = findViewById(R.id.exit_button); exitButton.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); Music.play(this, R.raw.main); } @Override protected void onPause() { super.onPause(); Music.stop(this); } public void onClick(View v) { switch (v.getId()) { case R.id.continue_button: startGame(Game.DIFFICULTY_CONTINUE); break; // ... case R.id.about_button: Intent i = new Intent(this, About.class); startActivity(i); break; // More buttons go here (if any) ... case R.id.new_button: openNewGameDialog(); break; case R.id.exit_button: finish(); break; } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: startActivity(new Intent(this, Prefs.class)); return true; // More items go here (if any) ... } return false; } /** Ask the user what difficulty level they want */ private void openNewGameDialog() { new AlertDialog.Builder(this) .setTitle(R.string.new_game_title) .setItems(R.array.difficulty, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialoginterface, int i) { startGame(i); } }) .show(); } /** Start a new game with the given difficulty level */ private void startGame(int i) { Log.d(TAG, "clicked on " + i); Intent intent = new Intent(Sudoku.this, Game.class); intent.putExtra(Game.KEY_DIFFICULTY, i); startActivity(intent); } } </code></pre> <p>Game.Java</p> <pre><code>package org.example.sudoku; import android.app.Activity; import android.app.Dialog; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.widget.Toast; 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[] = new int[9 * 9]; private final String easyPuzzle = "360000000004230800000004200" + "070460003820000014500013020" + "001900000007048300000000045"; private final String mediumPuzzle = "650000070000506000014000005" + "007009000002314700000700800" + "500000630000201000030000097"; private final String hardPuzzle = "009000000080605020501078000" + "000000700706040102004000000" + "000720903090301080000000600"; 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(); // ... // If the activity is restarted, do a continue next time getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE); } @Override protected void onResume() { super.onResume(); Music.play(this, R.raw.game); } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause"); Music.stop(this); // Save the current puzzle getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE, toPuzzleString(puzzle)).commit(); } /** Given a difficulty level, come up with a new puzzle */ private int[] getPuzzle(int diff) { String puz; switch (diff) { case DIFFICULTY_CONTINUE: puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE, easyPuzzle); break; // ... case DIFFICULTY_HARD: puz = hardPuzzle; break; case DIFFICULTY_MEDIUM: puz = mediumPuzzle; break; case DIFFICULTY_EASY: default: puz = easyPuzzle; break; } return fromPuzzleString(puz); } /** 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()]; for (int i = 0; i &lt; 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)); Dialog v = new Keypad(this, tiles, puzzleView); 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 &lt; 9; x++) { for (int y = 0; y &lt; 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 &lt; 9; i++) { if (i == y) continue; int t = getTile(x, i); if (t != 0) c[t - 1] = t; } // vertical for (int i = 0; i &lt; 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 &lt; startx + 3; i++) { for (int j = starty; j &lt; starty + 3; j++) { if (i == x &amp;&amp; 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; } } </code></pre> <p>PuzzleView.java</p> <pre><code>package org.example.sudoku; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Paint.FontMetrics; import android.graphics.Paint.Style; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.animation.AnimationUtils; public class PuzzleView extends View { 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; public PuzzleView(Context context) { super(context); this.game = (Game) context; setFocusable(true); setFocusableInTouchMode(true); // ... setId(ID); } @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)); return; } @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) { // 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 &lt; 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 &lt; 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 &lt; 9; i++) { for (int j = 0; j &lt; 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 &lt; 9; i++) { for (int j = 0; j &lt; 9; j++) { int movesleft = 9 - game.getUsedTiles(i, j).length; if (movesleft &lt; 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)); } // ... } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload