PuzzleView.java
上传用户:xmjingguan
上传日期:2009-07-06
资源大小:2054k
文件大小:8k
源码类别:

android开发

开发平台:

Java

  1. /***  * Excerpted from "Hello, Android!",  * published by The Pragmatic Bookshelf.  * Copyrights apply to this code. It may not be used to create training material,   * courses, books, articles, and the like. Contact us if you are in doubt.  * We make no guarantees that this code is fit for any purpose.   * Visit http://www.pragmaticprogrammer.com/titles/eband for more book information. ***/
  2. package org.example.sudoku;
  3. import android.content.Context;
  4. import android.graphics.Canvas;
  5. import android.graphics.Paint;
  6. import android.graphics.Rect;
  7. import android.graphics.Paint.FontMetrics;
  8. import android.graphics.Paint.Style;
  9. import android.util.Log;
  10. import android.view.KeyEvent;
  11. import android.view.MotionEvent;
  12. import android.view.View;
  13. import android.view.animation.AnimationUtils;
  14. public class PuzzleView extends View {
  15.    private static final String TAG = "Sudoku";
  16.    
  17.    
  18.    private float width;    // width of one tile
  19.    private float height;   // height of one tile
  20.    private int selX;       // X index of selection
  21.    private int selY;       // Y index of selection
  22.    private final Rect selRect = new Rect();
  23.    
  24.    
  25.    private final Game game;
  26.    public PuzzleView(Context context) {
  27.       super(context);
  28.       this.game = (Game) context;
  29.       setFocusable(true);
  30.       setFocusableInTouchMode(true);
  31.    }
  32.    // ...
  33.    
  34.    
  35.    @Override
  36.    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  37.       width = w / 9f;
  38.       height = h / 9f;
  39.       getRect(selX, selY, selRect);
  40.       Log.d(TAG, "onSizeChanged: width " + width + ", height "
  41.             + height);
  42.       super.onSizeChanged(w, h, oldw, oldh);
  43.    }
  44.    
  45.    
  46.    @Override
  47.    protected void onDraw(Canvas canvas) {
  48.       // Draw the background...
  49.       Paint background = new Paint();
  50.       background.setColor(getResources().getColor(
  51.             R.color.puzzle_background));
  52.       canvas.drawRect(0, 0, getWidth(), getHeight(), background);
  53.       
  54.       // Draw the board...
  55.       
  56.       // Define colors for the grid lines
  57.       Paint dark = new Paint();
  58.       dark.setColor(getResources().getColor(R.color.puzzle_dark));
  59.       Paint hilite = new Paint();
  60.       hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
  61.       Paint light = new Paint();
  62.       light.setColor(getResources().getColor(R.color.puzzle_light));
  63.       // Draw the minor grid lines
  64.       for (int i = 0; i < 9; i++) {
  65.          canvas.drawLine(0, i * height, getWidth(), i * height,
  66.                light);
  67.          canvas.drawLine(0, i * height + 1, getWidth(), i * height
  68.                + 1, hilite);
  69.          canvas.drawLine(i * width, 0, i * width, getHeight(),
  70.                light);
  71.          canvas.drawLine(i * width + 1, 0, i * width + 1,
  72.                getHeight(), hilite);
  73.       }
  74.       // Draw the major grid lines
  75.       for (int i = 0; i < 9; i++) {
  76.          if (i % 3 != 0)
  77.             continue;
  78.          canvas.drawLine(0, i * height, getWidth(), i * height,
  79.                dark);
  80.          canvas.drawLine(0, i * height + 1, getWidth(), i * height
  81.                + 1, hilite);
  82.          canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
  83.          canvas.drawLine(i * width + 1, 0, i * width + 1,
  84.                getHeight(), hilite);
  85.       }
  86.       
  87.       
  88.       
  89.       // Draw the numbers...
  90.       
  91.       // Define color and style for numbers
  92.       Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
  93.       foreground.setColor(getResources().getColor(
  94.             R.color.puzzle_foreground));
  95.       foreground.setStyle(Style.FILL);
  96.       foreground.setTextSize(height * 0.75f);
  97.       foreground.setTextScaleX(width / height);
  98.       foreground.setTextAlign(Paint.Align.CENTER);
  99.       // Draw the number in the center of the tile
  100.       FontMetrics fm = foreground.getFontMetrics();
  101.       // Centering in X: use alignment (and X at midpoint)
  102.       float x = width / 2;
  103.       // Centering in Y: measure ascent/descent first
  104.       float y = height / 2 - (fm.ascent + fm.descent) / 2;
  105.       for (int i = 0; i < 9; i++) {
  106.          for (int j = 0; j < 9; j++) {
  107.             canvas.drawText(this.game.getTileString(i, j), i
  108.                   * width + x, j * height + y, foreground);
  109.          }
  110.       }
  111.       
  112.       
  113.       
  114.       // Draw the hints...
  115.       
  116.       // Pick a hint color based on #moves left
  117.       Paint hint = new Paint();
  118.       int c[] = { getResources().getColor(R.color.puzzle_hint_0),
  119.             getResources().getColor(R.color.puzzle_hint_1),
  120.             getResources().getColor(R.color.puzzle_hint_2), };
  121.       Rect r = new Rect();
  122.       for (int i = 0; i < 9; i++) {
  123.          for (int j = 0; j < 9; j++) {
  124.             int movesleft = 9 - game.getUsedTiles(i, j).length;
  125.             if (movesleft < c.length) {
  126.                getRect(i, j, r);
  127.                hint.setColor(c[movesleft]);
  128.                canvas.drawRect(r, hint);
  129.             }
  130.          }
  131.       }
  132.       
  133.       
  134.       
  135.       // Draw the selection...
  136.       
  137.       Log.d(TAG, "selRect=" + selRect);
  138.       Paint selected = new Paint();
  139.       selected.setColor(getResources().getColor(
  140.             R.color.puzzle_selected));
  141.       canvas.drawRect(selRect, selected);
  142.       
  143.       
  144.    }
  145.    
  146.    
  147.    @Override
  148.    public boolean onTouchEvent(MotionEvent event) {
  149.       if (event.getAction() != MotionEvent.ACTION_DOWN)
  150.          return super.onTouchEvent(event);
  151.       select((int) (event.getX() / width),
  152.             (int) (event.getY() / height));
  153.       game.showKeypadOrError(selX, selY);
  154.       Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
  155.       return true;
  156.    }
  157.    
  158.    
  159.    @Override
  160.    public boolean onKeyDown(int keyCode, KeyEvent event) {
  161.       Log.d(TAG, "onKeyDown: keycode=" + keyCode + ", event="
  162.             + event);
  163.       switch (keyCode) {
  164.       case KeyEvent.KEYCODE_DPAD_UP:
  165.          select(selX, selY - 1);
  166.          break;
  167.       case KeyEvent.KEYCODE_DPAD_DOWN:
  168.          select(selX, selY + 1);
  169.          break;
  170.       case KeyEvent.KEYCODE_DPAD_LEFT:
  171.          select(selX - 1, selY);
  172.          break;
  173.       case KeyEvent.KEYCODE_DPAD_RIGHT:
  174.          select(selX + 1, selY);
  175.          break;
  176.       
  177.       
  178.       case KeyEvent.KEYCODE_0:
  179.       case KeyEvent.KEYCODE_SPACE: setSelectedTile(0); break;
  180.       case KeyEvent.KEYCODE_1:     setSelectedTile(1); break;
  181.       case KeyEvent.KEYCODE_2:     setSelectedTile(2); break;
  182.       case KeyEvent.KEYCODE_3:     setSelectedTile(3); break;
  183.       case KeyEvent.KEYCODE_4:     setSelectedTile(4); break;
  184.       case KeyEvent.KEYCODE_5:     setSelectedTile(5); break;
  185.       case KeyEvent.KEYCODE_6:     setSelectedTile(6); break;
  186.       case KeyEvent.KEYCODE_7:     setSelectedTile(7); break;
  187.       case KeyEvent.KEYCODE_8:     setSelectedTile(8); break;
  188.       case KeyEvent.KEYCODE_9:     setSelectedTile(9); break;
  189.       case KeyEvent.KEYCODE_ENTER:
  190.       case KeyEvent.KEYCODE_DPAD_CENTER:
  191.          game.showKeypadOrError(selX, selY);
  192.          break;
  193.          
  194.          
  195.       default:
  196.          return super.onKeyDown(keyCode, event);
  197.       }
  198.       return true;
  199.    }
  200.    
  201.    
  202.    public void setSelectedTile(int tile) {
  203.       if (game.setTileIfValid(selX, selY, tile)) {
  204.          invalidate();// may change hints
  205.       } else {
  206.          
  207.          // Number is not valid for this tile
  208.          Log.d(TAG, "setSelectedTile: invalid: " + tile);
  209.          
  210.          startAnimation(AnimationUtils.loadAnimation(game,
  211.                R.anim.shake));
  212.          
  213.          
  214.       }
  215.    }
  216.    
  217.    
  218.    private void select(int x, int y) {
  219.       invalidate(selRect);
  220.       selX = Math.min(Math.max(x, 0), 8);
  221.       selY = Math.min(Math.max(y, 0), 8);
  222.       getRect(selX, selY, selRect);
  223.       invalidate(selRect);
  224.    }
  225.    
  226.    
  227.    private void getRect(int x, int y, Rect rect) {
  228.       rect.set((int) (x * width), (int) (y * height), (int) (x
  229.             * width + width), (int) (y * height + height));
  230.    }
  231.    
  232.    
  233. }