android游戏开发项目实战——数独

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

一、程序运行效果图




二、代码实现


1、main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/hello_world" /></RelativeLayout>


2、dialog.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >        <TextView         android:id="@+id/usedTextId"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/hello_world"        /></LinearLayout>


3、keypad1.xml

<?xml version="1.0" encoding="utf-8"?><TableLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content"     android:id="@+id/keypad"    android:orientation="vertical"    >        <TableRow >        <Button android:id="@+id/keypad_1"            android:text="1"            />                <Button android:id="@+id/keypad_2"            android:text="2"            />                <Button android:id="@+id/keypad_3"            android:text="3"            />    </TableRow>            <TableRow >        <Button android:id="@+id/keypad_4"            android:text="4"            />                <Button android:id="@+id/keypad_5"            android:text="5"            />                <Button android:id="@+id/keypad_6"            android:text="6"            />    </TableRow>            <TableRow >        <Button android:id="@+id/keypad_7"            android:text="7"            />                <Button android:id="@+id/keypad_8"            android:text="8"            />                <Button android:id="@+id/keypad_9"            android:text="9"            />    </TableRow></TableLayout>



4、MainActivity

package com.njupt.shudu;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(new ShuduView(this)); } @Override public boolean onCreateOptionsMenu(Menu menu) {  // Inflate the menu; this adds items to the action bar if it is present.  getMenuInflater().inflate(R.menu.main, menu);  return true; }}


5、ShuduView

package com.njupt.shudu;import android.app.AlertDialog;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetrics;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.widget.TextView;public class ShuduView extends View//单元格的宽度和高度 private float width; private float height;  private Game game = new Game(); private int selectedX; private int selectedY;  public ShuduView(Context context) {  super(context);   }  /**  * w:当前view的宽度  * h:当前view的高度  *   */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  //计算当前单元格的宽度和高度  this.width = w / 9f;  this.height = h / 9f;    super.onSizeChanged(w, h, oldw, oldh); }  @Override protected void onDraw(Canvas canvas) {  //生成用于绘制背景色的画笔  Paint backgroundPaint = new Paint();  //设置画笔的颜色  backgroundPaint.setColor(getResources().getColor(R.color.shudu_background));  //绘制背景色  canvas.drawRect(0, 0,getWidth(),getHeight(),backgroundPaint);    Paint darkPaint = new Paint();  darkPaint.setColor(getResources().getColor(R.color.shudu_dark));    Paint hilitePaint = new Paint();  hilitePaint.setColor(getResources().getColor(R.color.shudu_hilite));    Paint lightPaint = new Paint();  lightPaint.setColor(getResources().getColor(R.color.shudu_light));    /**   * 绘制用于分割小九宫格的线(即将屏幕分成81个格子)   */  for(int i = 0 ; i < 9 ; ++i){   /**    * canvas.drawLine(0, i*height, getWidth(),i*height, lightPaint)    * 第1、2个参数: 起点的坐标    * 第3、4个参数: 终点的坐标    * 第5个参数: 所使用的画笔    */   canvas.drawLine(0, i*height, getWidth(),i*height, lightPaint);//划横线   canvas.drawLine(0, i*height + 1, getWidth(), i*height + 1, hilitePaint);//也是划横线,为了对比突出那种"刻出来"的效果   canvas.drawLine(i*width, 0, i*width, getHeight(), lightPaint);   canvas.drawLine(i*width + 1, 0, i*width + 1, getHeight() , hilitePaint);     }    /**   * 绘制用于将屏幕分成9个大九宫格的线   */  for(int i = 0 ; i < 9 ; ++i){   if(i % 3 == 0){    continue;   }      canvas.drawLine(0, i*height, getWidth(),i*height, darkPaint);//划横线   canvas.drawLine(0, i*height + 1, getWidth(), i*height + 1, hilitePaint);//也是划横线,为了对比突出那种"刻出来"的效果   canvas.drawLine(i*width, 0, i*width, getHeight(), darkPaint);   canvas.drawLine(i*width + 1, 0, i*width + 1, getHeight() , hilitePaint);     }    //绘制数字  Paint numberPaint = new Paint();  numberPaint.setColor(Color.BLACK);  numberPaint.setStyle(Paint.Style.STROKE);  numberPaint.setTextSize(height*0.75f);  numberPaint.setTextAlign(Paint.Align.CENTER);//设置对齐方式    FontMetrics fm = numberPaint.getFontMetrics();  float x = width / 2;  float y = height/2 - (fm.ascent + fm.descent)/2;    //生成数独的初始化数据  for(int i = 0 ; i < 9 ; ++i){   for(int j = 0 ; j < 9 ; ++j){    canvas.drawText(game.getTileString(i, j), i*width + x, j*height + y, numberPaint);   }  }    super.onDraw(canvas); }  @Override public boolean onTouchEvent(MotionEvent event) {  if(event.getAction() != MotionEvent.ACTION_DOWN){   return super.onTouchEvent(event);  }    //判断用户点击的是哪一个单元格  selectedX = (int)(event.getX() / width);  selectedY = (int)(event.getY() / height);    int used[] = game.getUsedTilesByCoor(selectedX, selectedY);  StringBuffer sb = new StringBuffer();  for(int i = 0 ; i < used.length ; ++i){//用来验证一下看对不对   sb.append(used[i]);  }  //  //生成一个LayoutInflater对象//  LayoutInflater layoutInflater = LayoutInflater.from(this.getContext());//  //使用LayoutInflater对象根据一个布局文件,生成一个View//  View layoutView = layoutInflater.inflate(R.layout.dialog, null);//  //从生成好的TextView中,取出相应的控件//  TextView textView = (TextView)layoutView.findViewById(R.id.usedTextId);//  //设置TextView的内容//  textView.setText(sb.toString());//  //生成一个对话框的Builder对象//  AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());//  //设置对话框索要显示的内容//  builder.setView(layoutView);//  //生成对话框对象,并将其显示出来//  AlertDialog dialog = builder.create();//  dialog.show();//   KeyDialog keyDialog = new KeyDialog(getContext(),used,this);  keyDialog.show();    return true; } public void setSelectedTile(int tile) {  if(game.setTileIfValid(selectedX,selectedY,tile)){   invalidate();  } }}


7、Game

package com.njupt.shudu;public class Game //数独初始化数据的基础 private final String str = "360000000004230800000004200"   +"070460003820000014500013020"   +"001900000007048300000000045";  private int sudoku[] = new int[9*9]; //用于存储每个单元格已经不可用的数据 private int used[][][] = new int[9][9][];  public Game() {  sudoku = fromPuzzleString(str);  calculateAllUsedTiles(); }   /**  * 根据九宫格当中的坐标,返回该坐标所应该填写的数字  * @param x  * @param y  * @return  */ private int getTile(int x, int y){  return sudoku[y*9 + x]; }  /**  * 根据x轴坐标和y轴坐标得到这一单元格不可用的数据  * @param x  * @param y  * @return  */ public String getTileString(int x, int y){  int v = getTile(x,y);  if(v == 0){   return "";  }else{   return String.valueOf(v);  } }  /**  * 根据一个字符串数据,生成一个整型数组,所谓数独游戏的初始化数据  * @param src  * @return  */ protected int[] fromPuzzleString(String src){  int[] sudo = new int[src.length()];    for(int i = 0 ; i < sudo.length ; ++i){   sudo[i] = src.charAt(i) - '0';   }    return sudo; }  /**  * 计算所有单元格对应的不可用的数据  */ public void calculateAllUsedTiles(){  for(int x = 0 ; x < 9 ; ++x){   for(int y = 0 ; y < 9 ; ++y){    used[x][y] = calculateUsedTiles(x, y);   }  } }   /**  * 取出某一单元格中已经不可用的数据  * @param x  * @param y  * @return  */ public int[] getUsedTilesByCoor(int x, int y){  return used[x][y]; }   /**  * 计算某一单元格之中已经不可用的数据  * @param x  * @param y  */ public int[] calculateUsedTiles(int x,int y) {  int c[] = new int[9];    /**   * 计算在y轴(列)方向上那些数字不可用...   */  for(int i = 0 ; i < 9 ; ++i){   if(i == y){//如果这是用户点击的格子    continue;   }      int t = getTile(x,i);   if(t != 0){    c[t - 1] = t;   }  }    for(int i = 0 ; i < 9 ; ++i){   if(i == x){    continue;   }      int t = getTile(i,y);   if(t != 0){    c[t - 1] = t;   }  }    /**   * 计算在小的九宫格中有那些数字已经用过了..   */  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;    }   }  }      /**   * 把c中的0给去掉   */  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;     } public boolean setTileIfValid(int x, int y, int value) {  int tiles[] = getUesdTiles(x,y);  if(value != 0){   for(int tile : tiles){    if(tile == value){     return false;    }   }  }    setTile(x,y,value);//把用户输入的数字添加到九宫格中  calculateAllUsedTiles();//更新该单元格可以使用的数字  return true; } protected int[] getUesdTiles(int x, int y) {  return used[x][y]; }  private void setTile(int x, int y, int value){  sudoku[y*9 + x] = value; }}


8、KeyDialog

package com.njupt.shudu;import android.app.Dialog;import android.content.Context;import android.os.Bundle;import android.view.View;/** * 该类用于实现Dialog,实现自定义的对话框功能... * @author Administrator * */public class KeyDialog extends Dialog//用来存放代表对话框当中按钮的对象 private final View keys[] = new View[9]; private final int used[];  private ShuduView shuduView; /**  *   * 构造函数的第二个参数中保存着当前单元格已经使用过的数字  * @param context  * @param used  */ public KeyDialog(Context context , int[] used , ShuduView shuduView) {  super(context);  this.used = used;  this.shuduView = shuduView; }  /**  * 当一个Dialog第一次显示的时候,会调用其onCreate方法  */ @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);    //设置对话框的标题  setTitle("KeyDialog");  //用于为该Dialog设置布局文件  setContentView(R.layout.keypad1);  findViews();    //显示某一单元格中可用的数字  for(int i = 0 ; i < used.length ; ++i){   if(used[i] != 0){    keys[used[i] - 1].setVisibility(View.INVISIBLE);   }  }    //为对话框当中所有按钮设置监听器  setListeners(); } private void findViews() {  keys[0] = findViewById(R.id.keypad_1);  keys[1] = findViewById(R.id.keypad_2);  keys[2] = findViewById(R.id.keypad_3);  keys[3] = findViewById(R.id.keypad_4);  keys[4] = findViewById(R.id.keypad_5);  keys[5] = findViewById(R.id.keypad_6);  keys[6] = findViewById(R.id.keypad_7);  keys[7] = findViewById(R.id.keypad_8);  keys[8] = findViewById(R.id.keypad_9);   }  /**  * 通知ShuduView对象,刷新挣个九宫格显示的数据  * @param tile  */ private void returnResult(int tile){  System.out.println("shuduView: " + shuduView);  shuduView.setSelectedTile(tile);  dismiss();//取消对话框的显示 }  private void setListeners(){  for(int i = 0 ; i < keys.length ; ++i){   final int t = i + 1;   keys[i].setOnClickListener(new View.OnClickListener() {        @Override    public void onClick(View v) {     returnResult(t);    }   });  } }}



本项目源码下载:http://download.csdn.net/detail/caihongshijie6/6883785

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/sfhinsc/article/details/84098416