游戏之数独之最终的结果


color.xml:目的是达到颜色的重用

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="shudu_background">#ffe6f0ff</color>
   <color name="shudu_hilite">#ffffffff</color>
   <color name="shudu_light">#64c6d4ef</color>
   <color name="shudu_dark">#6456648f</color>
</resources>

dialog.xml:

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

keypad.xml:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keypad"
    android:stretchColumns="*"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    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>


</LinearLayout>


MainActivity .java:

package com.example.shudu_1;
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);

                 //自定义的view
//setContentView(R.layout.activity_main);
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;
}
}


ShuduView .java:

package com.example.shudu_1;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.support.v4.view.PagerAdapter;
import android.text.style.LineHeightSpan.WithDensity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;


public class ShuduView extends View{


//单元格的宽度和高度
private float width;
private float height;
private int selectedX;
private int selectedY;

private Game game = new Game();

public ShuduView(Context context) {
super(context);
}



@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));
for(int i = 0; i < 9 ;i++){
//一下两行代码用户绘制横向的单元格线
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);
}

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]);
}

KeyDialog keyDialog = new KeyDialog(getContext(), used,this);
keyDialog.show();
//LayoutInflater layoutInflater = LayoutInflater.from(this.getContext());
//View layoutView = layoutInflater.inflate(R.layout.keypad, null);
//TextView textView =(TextView)layoutView.findViewById(R.id.usedTextId);
//textView.setText(sb.toString());
//AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
//builder.setView(layoutView);
//AlertDialog dialog = builder.create();
//dialog.show();
return true;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selectedX, selectedY, tile)) {
invalidate();

}
}


Game.java:

package com.example.shudu_1;


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();
}


// 根据九宫格当中的坐标,返回该坐标所应该填写的数字
private int getTile(int x, int y) {
return sudoku[y * 9 + x];
}


public String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0) {
return "";
} else
return String.valueOf(v);
}


// 根据一个字符串数据,生成一个整形数组,所谓数独游戏的初始化数据
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);
}
}
}


//取出某一单元格当中已经不可用得到数据
public int[] getUsedTilesByCoor(int x,int y){
return used[x][y];
}


//计算某一单元格当中已经不可用的数据
public int[] calculateUsedTiles(int x, int y) {
int c[] = new int[9];

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;
}
}
// 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;
}

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);
calculateAllUsedTiles();
return true;
}

protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}

private void setTile(int x, int y, int value) {
sudoku[y * 9 + x] = value;
}}



KeyDialog.java:

package com.example.shudu_1;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;

//该类用于实现Dialog,实现自定义的对话框功能
public class KeyDialog extends Dialog {
//用来存放代表对话框当中按钮的对象
private final View keys [] = new View[9];
private final int used[];
private ShuduView shuduView;


//构造函数的第二个参数当中保存着当前单元格已经使用过的数字
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.keypad);
findViews();
//便利整个used数组
for (int i = 0; i <used.length; i++) {
if(used[i] != 0){
System.out.println(used[i]);
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对象,刷新整个九宫格显示的数据
private void returnResult(int tile) {
shuduView.setSelectedTile(tile);
//取消对话框的显示
dismiss();
}
private void setListeners() {
//遍历整个keys数组
for (int i = 0; i < keys.length; i++) {
final int t = i + 1;
keys[i].setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
returnResult(t);
}
});
}
}
}

你可能感兴趣的:(游戏之数独之最终的结果)