欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義View實現(xiàn)數(shù)獨游戲

 更新時間:2017年12月18日 11:32:50   作者:安卓小小白  
這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)數(shù)獨游戲,具有一定的參考價值,感興趣的小伙伴們可以參考一下

先說一下數(shù)獨游戲的規(guī)則:

1.在整個橫坐標(biāo)和縱坐標(biāo)的9個格子上只能填土1-9的數(shù)字且不重復(fù)
2.在當(dāng)前3*3 的格子上填入1-9數(shù)字且不重復(fù)

先給大家看效果圖

項目思路

1、UI呈現(xiàn):這個放在 GameView 類里面
        顯示原始數(shù)據(jù)
        顯示當(dāng)然用戶填寫的數(shù)據(jù)
        顯示用戶當(dāng)前點擊的位置
        顯示候選區(qū)數(shù)據(jù)

2、邏輯處理:這個是放在Matrix類里面的
    原始數(shù)據(jù):游戲開始的時候就要創(chuàng)建出來的,
    當(dāng)前數(shù)據(jù):用戶填寫上去的實時數(shù)據(jù)
    數(shù)據(jù)判斷:判斷這個位置可以修改數(shù)據(jù)嗎? 比如,原始數(shù)據(jù)就是不可以修改的
            判斷這個位置可以填入的數(shù)據(jù),比如,原始數(shù)據(jù)這個位置有8了,就不能填8了。

代碼 GameView 類

public class GameView extends View {

 private int PhoneWidth; // 手機(jī)屏幕的寬度
 private int mGridWidth; // 當(dāng)前格子的寬度

 private int[] mFalseNumber; // 候選區(qū)不能填寫的數(shù)字

 private Paint mLinePaint; // 白線
 private Paint mDarkPaint; // 淺藍(lán)色的 方格子
 private Paint mOptDarkPaint; // 用戶點擊 淺綠色的格子
 private Paint numberPaint; // 原始數(shù)據(jù) 數(shù)字
 private Paint changePaint; // 用戶填寫的數(shù)字
 private Paint mOptPaint; // 候選區(qū)數(shù)字

 private Matrix M; // 用戶計算類

 private float tCX; 
 private float tCY;
 private int mOptBoard;
 private int mOptNumber;

 public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 initView();
 }

 public GameView(Context context, AttributeSet attrs) {
 super(context, attrs);
 initView();
 }

 public GameView(Context context) {
 super(context);

 initView();
 }

 private void initView() {

 PhoneWidth = getResources().getDisplayMetrics().widthPixels;
 mGridWidth = (PhoneWidth - 40) / 9;

 tCX = mGridWidth / 2;
 tCY = tCX - tCX / 2;

 mFalseNumber = new int[9];

 for (int i = 0; i < 9; i++) {
  mFalseNumber[i] = i;
 }

 M = new Matrix();
 initPaint();

 invalidate();
 }

 private void initPaint() {
 mLinePaint = new Paint();
 mLinePaint.setColor(Color.WHITE);
 mLinePaint.setStyle(Paint.Style.STROKE);
 mLinePaint.setStrokeWidth(2f);

 mDarkPaint = new Paint();
 mDarkPaint.setColor(Color.parseColor("#52E7CD"));
 mDarkPaint.setStyle(Paint.Style.FILL);

 numberPaint = new Paint();
 numberPaint.setColor(Color.WHITE);
 numberPaint.setTextSize(mGridWidth * 0.65f);
 numberPaint.setTextAlign(Paint.Align.CENTER);
 numberPaint.setShadowLayer(10F, -5F, 8F, Color.parseColor("#999999"));
 numberPaint.setAntiAlias(true);

 mOptPaint = new Paint();
 mOptPaint.setColor(Color.WHITE);
 mOptPaint.setTextSize(mGridWidth * 0.65f+15);
 mOptPaint.setTextAlign(Paint.Align.CENTER);
 mOptPaint.setShadowLayer(10F, -5F, 8F, Color.parseColor("#999999"));
 mOptPaint.setAntiAlias(true);

 changePaint = new Paint();
 changePaint.setColor(Color.parseColor("#FCA454"));
 changePaint.setTextSize(mGridWidth * 0.65f);
 changePaint.setTextAlign(Paint.Align.CENTER);
 changePaint.setShadowLayer(10F, -5F, 8F, Color.parseColor("#999999"));
 changePaint.setAntiAlias(true);

 mOptDarkPaint = new Paint();
 mOptDarkPaint.setColor(Color.parseColor("#52E76E"));
 mOptDarkPaint.setStyle(Paint.Style.FILL);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 setMeasuredDimension(PhoneWidth, PhoneWidth + mGridWidth+20);
 }

 @Override
 protected void onDraw(Canvas canvas) {

 drawBoard(canvas);

 int x = mOptBoard / 9;
 int y = mOptBoard % 9;
 // 畫出棋盤選擇框
 canvas.drawRect(x * mGridWidth+22, y * mGridWidth+22, x * mGridWidth+20 + mGridWidth, y * mGridWidth+20 + mGridWidth, mOptDarkPaint);

 // 當(dāng)前棋盤數(shù)據(jù)
 for (int i = 0; i < 9; i++) {
  for (int j = 0; j < 9; j++) {
  int cutData = M.getCutData(i, j);
  if (M.getOnClicked(i,j) && cutData>0) {
   canvas.drawText(Integer.toString(cutData), i * mGridWidth + tCX+20, j*mGridWidth + mGridWidth - tCY+20, changePaint);
  }
  } 
 }

 // 候選區(qū)文字

 drawTrueText(canvas);

 }

 private void drawTrueText(Canvas canvas) {
 float startY = PhoneWidth + 30;

 // 畫平行四邊形
 canvas.drawLine(50, startY, PhoneWidth-50, startY, mLinePaint);
 canvas.drawLine(10, startY + mGridWidth - 40, PhoneWidth-10, startY + mGridWidth-40, mLinePaint);
 canvas.drawLine(50, startY, 10, startY + mGridWidth - 40, mLinePaint);
 canvas.drawLine(PhoneWidth-50, startY, PhoneWidth-10, startY + mGridWidth-40, mLinePaint);

 float y = (mGridWidth - 30)/2.0f;

 for (int i = 0; i < 9; i++) {
  if (mFalseNumber[i] == 0) {
  canvas.drawText(Integer.toString(i+1), i * mGridWidth + tCX+ 20, startY + (mGridWidth - tCY) - y, mOptPaint);
  }
 }
 }

 private void drawBoard(Canvas canvas) {

 // 畫底色
 for (int i = 0; i < 9; i++) {
  for (int j = 0; j < 9; j++) {
  int x = i / 3;
  int y = j / 3;
  if ((x == 0 || x == 2) && (y == 0 || y == 2)) {
   canvas.drawRect(mGridWidth * j + 20, 20 + mGridWidth * i,
    mGridWidth * j + 20 + mGridWidth, 20 + mGridWidth
     * i + mGridWidth, mDarkPaint);
  } else if (y == 1 && x == 1) {
   canvas.drawRect(mGridWidth * j + 20, 20 + mGridWidth * i,
    mGridWidth * j + 20 + mGridWidth, 20 + mGridWidth
     * i + mGridWidth, mDarkPaint);
  }

  }
 }

 // 畫白線
 for (int i = 0; i < 10; i++) {
  canvas.drawLine(20, mGridWidth * i + 1 + 20, 9 * mGridWidth + 20,
   mGridWidth * i + 1 + 20, mLinePaint);
  canvas.drawLine(mGridWidth * i + 1 + 20, 0 + 20, mGridWidth * i + 1
   + 20, 9 * mGridWidth + 20, mLinePaint);
 }

 //畫初始數(shù)字
 for (int i = 0; i < 9; i++) {
  for (int j = 0; j < 9; j++) {
  if (!M.getOnClicked(i, j)) {
   canvas.drawText(M.getText(i, j), i * mGridWidth +20+tCX, mGridWidth * j + 20+mGridWidth-tCY, numberPaint);

  }
  }
 }
 }


 @Override
 public boolean onTouchEvent(MotionEvent event) {
 if (event.getAction() != MotionEvent.ACTION_DOWN) {
  return super.onTouchEvent(event);
 }

 if (event.getX()<20 || event.getY()<20 || event.getX()>PhoneWidth-20) {
  Log.e("123", "點到邊了");
  return super.onTouchEvent(event);
 }

 int choX = (int) ((event.getX()-20) / mGridWidth);
 int choY = (int) ((event.getY()-20) / mGridWidth);

 Log.i("game ", "optX "+choX+" optY "+choY);

 if (event.getY() < PhoneWidth-20) { // 棋盤的點擊

  if (M.getOnClicked(choX, choY)) {
  mFalseNumber = new int[9];
  int[] trueData = M.getFalseData(choY, choX);
  mOptBoard = choX * 9 + choY;
  for (int i : trueData) {
   mFalseNumber[i - 1] = 1;
  }

  }

 } else { // 候選區(qū)點擊
  Log.e("game ","opt Number " + choX + 1);

  System.out.println(Arrays.toString(mFalseNumber));

  if (mFalseNumber[choX] == 0) {
  mOptNumber = choX;
  int x = mOptBoard / 9;
  int y = mOptBoard % 9;
  M.setCutData(x, y, mOptNumber+1);
  }

 }
 invalidate();

 return true;
 }


 // 再來一局
 public void play() {
 initView();
 }
 // 重頭開始
 public void repeat(){
 M.initCutData();
 invalidate();
 }

代碼 Matrix類

public class Matrix {

 private int [][]mData ; // 原始數(shù)據(jù)
 private int [][]mCutData; // 當(dāng)前數(shù)據(jù)


 public Matrix() {

 int i = (int)(Math.random()*5);

 switch (i) {
 case 1:
  mData = GAMEDATA1;
  break;
 case 2:
  mData = GAMEDATA2;
  break;
 case 3:
  mData = GAMEDATA3;
  break;
 case 4:
  mData = GAMEDATA4;
  break;
 case 0:
  mData = GAMEDATA2;
  break;

 }
 initCutData();
 Log.e("Matrix", "random :"+i);

 }


 /** 得到當(dāng)前坐標(biāo)上的文字 */
 public String getText(int x, int y){

 String index = mData[x][y]+"";

 if ("0".equals(index)) {
  index = "";
 }

 return index;

 }

 /** 判斷該坐標(biāo)是否可以點擊 */
 public boolean getOnClicked(int x, int y){

 if (mData[x][y] == 0) {
  return true;
 }
 return false;

 }

 /** 判斷該坐標(biāo)有哪些數(shù)不可用 */
 public int[] getFalseData(int x, int y){
 Set<Integer> set = new TreeSet<Integer>();

 // 檢查X 軸有哪些不能點

 for (int i = 0; i < 9; i++) {
  int d = mData[y][i];

  if (d!=0) {
  set.add(d);
//  LogUtils.e("x: "+d);
  }
 }
 // 檢查 y 軸有哪些不能點
 for (int i = 0; i < 9; i++) {
  int d = mData[i][x];
  if (d!=0) {
  set.add(d);
//  LogUtils.e("Y: "+d);
  }
 }

 // 檢查 3*3 方格哪些不能點

 x = x/3*3;
 y = y/3*3;

// LogUtils.e(" x "+x+" Y "+y);

 for (int i = x; i < x+3; i++) {
  for (int j = y; j < y+3; j++) {
  int d = mData[j][i];
  if (d!=0) {
   set.add(d);
//   LogUtils.e("i "+i+"j "+j+" xy: "+d);
  }
  }
 }


 Integer[] arr2 = set.toArray(new Integer[0]);
 // 數(shù)組的包裝類型不能轉(zhuǎn) 只能自己轉(zhuǎn);吧Integer轉(zhuǎn)為為int數(shù)組;
 int[] result = new int[arr2.length];
 for (int i = 0; i < result.length; i++) {
  result[i] = arr2[i];
 }
 System.out.println("false Number : "+Arrays.toString(result));


 return result;
 }



 /** 當(dāng)前棋盤數(shù)據(jù) */
 public void initCutData(){

 mCutData = new int[9][9];

 for (int i = 0; i < mData.length; i++) {
  for (int j = 0; j < mData[i].length; j++) {
   mCutData[i][j] = mData[i][j];
  }
 }


 for (int i = 0; i < mCutData.length; i++) {
  System.out.println(Arrays.toString(mCutData[i]));
 }


 }

 public void setCutData(int x, int y, int data){
 if (getOnClicked(x, y)) {
  mCutData[x][y] = data;
 }

 }


 public int getCutData(int x, int y){
 return mCutData[x][y];
 }
}

代碼 MainActivity 類

public class MainActivity extends Activity {

 private GameView gV;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 gV = (GameView) findViewById(R.id.game);
 }

 public void rePay(View v){
 gV.repeat();
 }
 public void newPay(View v){
 gV.play();

 }

acitivity_main.xml 文件

<LinearLayout 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:background="#0EC5A5"
 android:orientation="vertical" >

 <TextView
 android:layout_width="match_parent"
 android:layout_height="52dp"
 android:layout_marginTop="10dp"
 android:gravity="center"
 android:text="SUDOKU"
 android:textColor="@android:color/white"
 android:textSize="30sp" />

 <com.xuan.sudokugame.GameView
 android:id="@+id/game"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />

 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="60dp"
 android:padding="10dp"
 android:orientation="horizontal" >

 <Button
  android:layout_width="0dp"
  android:onClick="rePay"
  android:layout_height="match_parent"
  android:layout_weight="1" 
  android:layout_marginRight="10dp"
  android:text="重新開始"
  android:textColor="@android:color/white"
  android:background="@drawable/radius_border_gray"/>
 <Button
  android:onClick="newPay"
  android:layout_width="0dp"
  android:layout_height="match_parent"
  android:layout_weight="1" 
  android:text="再來一局"
  android:textColor="@android:color/white"
  android:background="@drawable/radius_border_gray"/>
 </LinearLayout>

</LinearLayout>

然后運行起來就是這個樣子的了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Native.js獲取監(jiān)聽開關(guān)等操作Android藍(lán)牙設(shè)備實例代碼

    Native.js獲取監(jiān)聽開關(guān)等操作Android藍(lán)牙設(shè)備實例代碼

    本文為大家分享了Native.js對Android藍(lán)牙設(shè)備的操作實例代碼包括:監(jiān)聽藍(lán)牙開關(guān)狀態(tài),開啟關(guān)閉藍(lán)牙,獲取藍(lán)牙設(shè)備列表,藍(lán)牙連接票據(jù)打印機(jī)
    2018-09-09
  • Kotlin語言使用WebView示例介紹

    Kotlin語言使用WebView示例介紹

    隨著后臺技術(shù)的不斷發(fā)展,App前端的應(yīng)用都布置了Web頁面的界面,這個界面就是由WebView組件渲染出來的。WebView由如下優(yōu)點:可以直接顯示和渲染W(wǎng)eb頁面或者網(wǎng)頁;可以直接調(diào)用網(wǎng)絡(luò)上或者本地的html文件,也可以和JavaScript交互使用
    2022-09-09
  • android自定義形狀的按鍵實例代碼

    android自定義形狀的按鍵實例代碼

    這篇文章主要介紹了android自定義形狀的按鍵實例代碼,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2018-05-05
  • Android Notification使用方法總結(jié)

    Android Notification使用方法總結(jié)

    這篇文章主要介紹了Android Notification使用方法總結(jié)的相關(guān)資料,這里提供了四種使用方法,需要的朋友可以參考下
    2017-09-09
  • Android中自定義控件的declare-styleable屬性重用方案

    Android中自定義控件的declare-styleable屬性重用方案

    這篇文章主要介紹了Android中自定義控件的declare-styleable屬性重用方案,本文給出了一個終極重用解決方案,需要的朋友可以參考下
    2015-01-01
  • Android模仿Toast實現(xiàn)提示框效果

    Android模仿Toast實現(xiàn)提示框效果

    這篇文章主要為大家詳細(xì)介紹了Android模仿Toast實現(xiàn)提示框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Android界面切換出現(xiàn)短暫黑屏的解決方法

    Android界面切換出現(xiàn)短暫黑屏的解決方法

    這篇文章主要介紹了Android界面切換出現(xiàn)短暫黑屏的解決方法,本文講解的是一個取巧方法,需要的朋友可以參考下
    2015-04-04
  • Flutter實現(xiàn)資源下載斷點續(xù)傳的示例代碼

    Flutter實現(xiàn)資源下載斷點續(xù)傳的示例代碼

    在項目開發(fā)中,特別是C端的產(chǎn)品,資源下載實現(xiàn)斷點續(xù)傳是非常有必要的。今天我們不講過多原理的知識,分享下簡單實用的資源斷點續(xù)傳
    2022-07-07
  • 用于cocos2d-x引擎(ndk)中為android項目生成編譯文件列表

    用于cocos2d-x引擎(ndk)中為android項目生成編譯文件列表

    在android的ndk項目中,添加很多源文件之后總要手動編寫makefile來添加所有的源文件, 很麻煩,所以寫了一個自動生成編譯源文件列表的小工具
    2014-05-05
  • Android SwipeRefreshLayout超詳細(xì)講解

    Android SwipeRefreshLayout超詳細(xì)講解

    在android開發(fā)中,使用最多的數(shù)據(jù)刷新方式就是下拉刷新了,而完成此功能我們使用最多的就是第三方的開源庫PullToRefresh?,F(xiàn)如今,google也忍不住推出了自己的下拉組件SwipeRefreshLayout,下面我們通過api文檔和源碼來分析學(xué)習(xí)如何使用SwipeRefreshLayout
    2022-11-11

最新評論