zoukankan      html  css  js  c++  java
  • android开发——数独游戏

    最近研究了一下android,写了一个数独游戏,具体如下:

    游戏界面需要重写一个ShuduView继承View,

    然后自定义一个Dialog:

    1.需要继承 Dialog 类,

    2.并要定义一个有参构造函数(因为父类里面没有无参构造函数)

    3.重写 onCreate方法,一切操作将在此方法进行

    流程:

    为每个按钮添加监听事件,

    刷新九宫格里的数字,也就是重新绘制画面(在view类中调用 invalidate();),

    更新备选数字数组 ( 每次修改之后都得 进行重新计算 不可用的值   calculateAllUsedTiles() ; )

    下面介绍主要代码:

    ShuduView:

      1 package com.soccer.shudu;
      2 
      3 import android.content.Context;
      4 import android.graphics.*;
      5 import android.graphics.Paint.FontMetrics;
      6 
      7 
      8 import android.view.MotionEvent;
      9 import android.view.View;
     10 import android.view.WindowManager;
     11 
     12 
     13 public class ShuduView extends View{
     14     
     15     public ShuduView(Context context) {
     16         super(context);
     17         // TODO Auto-generated constructor stub
     18     }
     19     
     20     private float width;
     21     private float height;
     22      
     23 
     24     private Game game = new Game();
     25     
     26     @Override
     27     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
     28         //计算当前单元格宽度和高度
     29         this.height = h / 9f;
     30         this.width = w / 9f;
     31         super.onSizeChanged(w, h, oldw, oldh);
     32     }
     33 
     34 
     35 
     36     //当android的系统需要绘制一个view对象时,就需要调用该对象的onDraw方法
     37     @Override
     38     protected void onDraw(Canvas canvas) {
     39         //生成用户绘制背景色的画笔
     40         Paint backgroundPaint = new Paint();
     41         //设置画笔颜色
     42         backgroundPaint.setColor(getResources().getColor(R.color.shudu_background));
     43         //绘制背景色
     44         canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
     45         
     46         Paint darkPaint = new Paint();
     47         darkPaint.setColor(getResources().getColor(R.color.shudu_dark));
     48         
     49         Paint hilitePaint = new Paint();
     50         hilitePaint.setColor(getResources().getColor(R.color.shudu_hilite));
     51         
     52         Paint lightPaint = new Paint();
     53         lightPaint.setColor(getResources().getColor(R.color.shudu_light));
     54         
     55         for(int i = 0;i < 9;i++){
     56             //绘制横向的线
     57             canvas.drawLine(0, i * height,getWidth(),  i * height, lightPaint);
     58             canvas.drawLine(0, i * height + 1,getWidth(),  i * height + 1, hilitePaint);
     59             //绘制纵向的线
     60             canvas.drawLine(i * width, 0, i * width, getHeight(), lightPaint);
     61             canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(), hilitePaint);
     62         }
     63         
     64         for(int i = 0;i < 3;i++){
     65             //绘制横向的线
     66             canvas.drawLine(0, i * 3 * height, getWidth(),  i * 3 * height, darkPaint);
     67             canvas.drawLine(0, i * 3 * height + 1, getWidth(),  i * 3 * height + 1, darkPaint);
     68             //绘制纵向的线
     69             canvas.drawLine(i * 3 * width, 0, i * 3 * width, getHeight(), darkPaint);
     70             canvas.drawLine(i * 3 * width + 1, 0, i * 3 * width + 1, getHeight(), darkPaint);
     71         }
     72         //绘制数字
     73         Paint numberPaint = new Paint();
     74         numberPaint.setColor(Color.BLACK);
     75         //numberPaint.setStyle(Paint.Style.STROKE);
     76         numberPaint.setTextSize( height * 0.75f); 
     77         numberPaint.setTextAlign(Paint.Align.CENTER);
     78         //将数字加到格子中
     79         FontMetrics fm = numberPaint.getFontMetrics();
     80         float x = width / 2;
     81         float y = height / 2 - (fm.ascent + fm.descent) / 2;
     82         //canvas.drawText("1", 3 * width + x, height + y , numberPaint);
     83         for(int i = 0;i < 9;i++){
     84             for(int j = 0;j < 9;j++){
     85                 canvas.drawText(game.getTileString(i, j), i * width+x, j * height + y, numberPaint);
     86             }
     87         }
     88         
     89         
     90         super.onDraw(canvas); 
     91     }
     92     
     93     int selectedX;
     94     int selectedY;
     95 
     96 
     97 
     98     @Override
     99     public boolean onTouchEvent(MotionEvent event) {
    100         if(event.getAction() != MotionEvent.ACTION_DOWN){
    101         return super.onTouchEvent(event);
    102         }
    103         
    104         selectedX = (int)(event.getX() / width);
    105         selectedY = (int)(event.getY() / height); 
    106         
    107         int used[] = game.getUsedTileByCoor(selectedX, selectedY);
    108         StringBuffer sb = new StringBuffer();
    109         for(int i = 0; i < used.length;i++){
    110             System.out.println(used[i] );
    111             //sb.append(used[i]);
    112         }
    113         
    114         //生成一个LayoutInflater对象
    115         //LayoutInflater layoutInflater = LayoutInflater.from(this.getContext());
    116         //View layoutView = layoutInflater.inflate(R.layout.dialog, null);
    117         //从生成好的textView中 取出相应的控件
    118         //TextView textView =(TextView)layoutView.findViewById(R.id.usedTextId); 
    119         
    120         //textView.setText(sb.toString());
    121         
    122         //AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
    123         //builder.setView(layoutView);
    124         
    125         //AlertDialog dialog = builder.create();
    126         //dialog.show();
    127         //dialog.getWindow().setLayout(300, 200);
    128         KeyDialog keyDialog = new KeyDialog(getContext(), used,this);
    129         //透明度
    130         WindowManager.LayoutParams lp=keyDialog.getWindow().getAttributes();
    131         lp.alpha=0.9f;
    132         keyDialog.getWindow().setAttributes(lp);
    133         
    134         keyDialog.show();
    135         return true;    
    136     }
    137     
    138     public  void setSelectedTile(int tile){
    139     
    140         if(game.setTileIfValid(selectedX,selectedY,tile)){
    141             invalidate();
    142         }
    143     }
    144     
    145 }

    KeyDialog:

     1 package com.soccer.shudu;
     2 
     3 import android.app.Dialog;
     4 import android.content.Context;
     5 import android.os.Bundle;
     6 import android.view.View;
     7 import android.widget.Button;
     8 
     9 
    10 //该类用于实现dialog自定义对话框功能
    11 public class KeyDialog extends Dialog{
    12     private final View keys [] = new View[9];
    13     private final int used[];
    14     
    15     private ShuduView shuduView = null;
    16     
    17     public KeyDialog(Context context,int [] used,ShuduView shuduView){
    18         super(context);
    19         this.used = used;
    20         this.shuduView = shuduView;
    21     }
    22     //当一个dialog第一次显示的时候,会调用其onCreate方法
    23     @Override
    24     protected void onCreate(Bundle savedInstanceState) {
    25         super.onCreate(savedInstanceState);
    26         setTitle("可选数字");
    27         setContentView(R.layout.keypad);
    28         findViews();
    29         for(int i = 0;i < used.length;i++){
    30             if(used[i] != 0){
    31                 keys[used[i] - 1].setVisibility(View.INVISIBLE);
    32             }
    33         }
    34         //为每个键设置监听器
    35         setListeners();
    36         
    37         //为返回按钮设置监听器
    38         Button back_Button = (Button)findViewById(R.id.back_1);
    39         back_Button.setOnClickListener(new View.OnClickListener() {
    40             @Override
    41             public void onClick(View v) {
    42                 dismiss();
    43                 
    44             }
    45         });
    46     }
    47     
    48     
    49     
    50     
    51     private void findViews(){
    52         keys[0] = findViewById(R.id.keypad_1);
    53         keys[1] = findViewById(R.id.keypad_2);
    54         keys[2] = findViewById(R.id.keypad_3);
    55         keys[3] = findViewById(R.id.keypad_4);
    56         keys[4] = findViewById(R.id.keypad_5);
    57         keys[5] = findViewById(R.id.keypad_6);
    58         keys[6] = findViewById(R.id.keypad_7);
    59         keys[7] = findViewById(R.id.keypad_8);
    60         keys[8] = findViewById(R.id.keypad_9);
    61     }
    62     
    63     //通知ShuduView对象,刷新整个九宫格显示的数据
    64     private void returnResult(int tile){
    65         shuduView.setSelectedTile(tile);
    66         dismiss();
    67     }
    68     
    69     private void setListeners(){
    70         for(int i = 0; i < keys.length; i++){
    71             final int t = i + 1;
    72             keys[i].setOnClickListener(new View.OnClickListener() {
    73                 
    74                 @Override
    75                 public void onClick(View v) {
    76                     returnResult(t);
    77                     
    78                 }
    79             });
    80         }
    81     }
    82     
    83 }

    keypad.xml:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:id="@+id/keypad"
     4     android:orientation="vertical"
     5     android:layout_width="wrap_content"
     6     android:layout_height="wrap_content"
     7     android:stretchColumns="*" >
     8 
     9     <TableRow>
    10             <Button android:id="@+id/keypad_1"
    11                 android:text="1">
    12             </Button>
    13             <Button android:id="@+id/keypad_2"
    14                 android:text="2">
    15             </Button>
    16             <Button android:id="@+id/keypad_3"
    17                 android:text="3">
    18             </Button>
    19     </TableRow>
    20 
    21     <TableRow>
    22             <Button android:id="@+id/keypad_4"
    23                 android:text="4">
    24             </Button>
    25             <Button android:id="@+id/keypad_5"
    26                 android:text="5">
    27             </Button>
    28             <Button android:id="@+id/keypad_6"
    29                 android:text="6">
    30             </Button>
    31     </TableRow>
    32     
    33     <TableRow>
    34             <Button android:id="@+id/keypad_7"
    35                 android:text="7">
    36             </Button>
    37             <Button android:id="@+id/keypad_8"
    38                 android:text="8">
    39             </Button>
    40             <Button android:id="@+id/keypad_9"
    41                 android:text="9">
    42             </Button>
    43     </TableRow>
    44     
    45     <TableRow>
    46             <Button android:text="">
    47             </Button>
    48             <Button android:id="@+id/back_1"
    49                 android:text="@string/back_1">
    50             </Button>
    51             <Button android:text="">
    52             </Button>
    53     </TableRow>
    54 
    55 </TableLayout>

    Game.java:

      1 package com.soccer.shudu;
      2 
      3 public class Game {
      4     //数独初始化数据
      5     private final String str = "360000000004230800000004200"
      6             +"070460003820000014500013020"
      7             +"001900000007048300000000045";
      8     private int sudoku [] = new int[9*9];
      9     //用于存储每个单元格已经不可用的数据
     10     private int used[][][] = new int[9][9][];
     11     
     12     public Game(){
     13         sudoku = fromPuzzleString(str);
     14         calculateAllUsedTile();
     15     }
     16     //根据九宫格当中的坐标,返回该坐标对应的数字
     17     private int getTile(int x,int y){
     18         return sudoku[y*9 + x];
     19     }
     20     private void setTile(int x,int y,int value){
     21         sudoku[y * 9 + x] = value;
     22     }
     23     
     24     public String getTileString(int x, int y){
     25         int v = getTile(x,y);
     26         if(v == 0){          //0就不显示
     27             return "";
     28         }
     29         else
     30             return String.valueOf(v);
     31     }
     32     protected boolean setTileIfValid(int x,int y,int value){
     33         int tiles[] = getUsedTileByCoor(x,y);
     34         if(value != 0){
     35             for(int tile : tiles){
     36                 if(tile == value)
     37                     return false;
     38             }
     39         }
     40         setTile(x,y,value);
     41         calculateAllUsedTile();
     42         return true;
     43     }
     44     
     45     //根据一个字符串数据生成一个整形数组,作为数独游戏的初始化数据
     46     protected int[] fromPuzzleString(String src){
     47         int []sudo = new int[src.length()];
     48         for(int i = 0;i < sudo.length;i++)
     49         {
     50             sudo[i] = src.charAt(i) - '0';
     51         }
     52         return sudo;
     53     } 
     54     
     55     //计算所有单元格对应的不可用数据
     56     public void calculateAllUsedTile(){
     57         for(int x = 0;x < 9;x++){
     58             for(int y = 0;y < 9;y++){
     59                 used[x][y] = calculateUsedTiles(x, y);
     60             }
     61         }
     62     }
     63     
     64     //取出某一单元格当中已经不可用的数据
     65     public int[] getUsedTileByCoor(int x,int y){
     66         return used[x][y];
     67     }
     68     
     69     //计算某一单元格当中已经不可用的数据
     70     public int[] calculateUsedTiles(int x,int y){
     71         int c[] = new int[9];
     72         
     73         for(int i = 0;i < 9;i++){
     74             if(i == y)
     75                 continue;
     76             int t = getTile(x, i);
     77             if(t != 0)
     78                 c[t - 1] = t;
     79          }
     80         
     81         for(int i = 0;i < 9;i++){
     82             if(i == x)
     83                 continue;
     84             int t = getTile(i, y);
     85             if(t != 0)
     86                 c[t - 1] = t;
     87          }
     88         
     89         int startx = (x / 3) * 3;
     90         int starty = (y / 3) * 3;
     91         for(int i = startx; i < startx + 3; i++){
     92             for(int j = starty;j < starty + 3; j++){
     93                 if(i == x && j == y)
     94                     continue;
     95                 int t = getTile(i,j);
     96                 if(t!=0)
     97                     c[t-1] = t;
     98             }
     99         }
    100         //compress
    101         int nused = 0;
    102         for(int t:c){
    103             if(t!=0)
    104                 nused++;
    105         }
    106         int c1[] = new int[nused];
    107         nused = 0;
    108         for(int t:c){
    109             if(t!=0)
    110                 c1[nused++] = t;
    111         }
    112         return c1;
    113     }    
    114 }

    界面效果如下:

     

  • 相关阅读:
    简单搭建ELK日志分析平台及常见问题汇总
    【Java】开发23中设计模式详解(转载)
    【微服务】dubbo微服务的总结及结合Spring的实例
    【服务端】知识架构规划
    【java】数据缓存之 EhCache缓存
    【java】数据缓存之 Redis
    【java】多线程编程(不断扩充,但不拆分)
    【MySQL】mysql 存储过程应用
    【MySQL】基础知识-case when函数
    【MySQL】 join连接使用基本知识
  • 原文地址:https://www.cnblogs.com/soccer/p/3592687.html
Copyright © 2011-2022 走看看