分成四个类:CrosswordsActivity,DialogView,Game,MainView
CrosswordsActivity(主类):
package com.Crosswords.Activity;
import android.app.Activity;
import android.os.Bundle;
public class CrosswordsActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MainView(this));
}
}
DialogView(对话框的一个类):
package com.Crosswords.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
public class DialogView extends Dialog{
MainView mainview;
// View []views=new View[9];
View[] views=new View[12];
int []used;
public DialogView(Context context,int []used,MainView mainview) {
super(context);
this.used=used;
this.mainview=mainview;
}
@Override
public void onCreate(Bundle buildle){
super.onCreate(buildle);
setTitle("请输入数字");
setContentView(R.layout.dialog);
this.getView();
for(int i=0;i<used.length;i++){
if(used[i]!=0){
views[used[i]-1].setVisibility(View.INVISIBLE);
}
}
views[9].setVisibility(View.INVISIBLE);
views[11].setVisibility(View.INVISIBLE);
setListener();
}
public void getView(){
views[0]=findViewById(R.id.keypad_1);
views[1]=findViewById(R.id.keypad_2);
views[2]=findViewById(R.id.keypad_3);
views[3]=findViewById(R.id.keypad_4);
views[4]=findViewById(R.id.keypad_5);
views[5]=findViewById(R.id.keypad_6);
views[6]=findViewById(R.id.keypad_7);
views[7]=findViewById(R.id.keypad_8);
views[8]=findViewById(R.id.keypad_9);
views[9]=findViewById(R.id.keypad_10);
views[10]=findViewById(R.id.keypad_11);
views[11]=findViewById(R.id.keypad_12);
}
public void ReturnResult(int title){
mainview.SetSelectTitle(title);
dismiss();
}
public void setListener(){
for(int i=0;i<views.length;i++){
//次数的t为真实的数字
final int t=i+1;
views[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ReturnResult(t);
}
});
}
}
}
Game(数独的算法类):
package com.Crosswords.Activity;
public class Game {
String str=
"500200008"+
"700008400"+
"000390060"+
"001630009"+
"000000654"+
"968400000"+
"005006071"+
"609005803"+
"080903046";
//全部的数字
int []crosswords=new int[9*9];
//各个坐标已经使用的数字
int [][][]usedwords=new int[9][9][];
//用来标记能够修改
int [][]flag =new int[9][9];
public Game() {
// TODO Auto-generated constructor stub
crosswords=getCrossword(str);
flag=getflag();
//GetAllUsed();
}
//得到所有已经使用数组
public void GetAllUsed(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
usedwords[i][j]=getUsedWords(i, j);
}
}
}
//用来计算单元格中已经使用的格子
public int[] getUsedWords(int x,int y){
int [] c=new int[9];
//计算一行
int temp;
for(int i=0;i<9;i++){
temp=gettitle(i, y);
if(x==i){
continue;
}else{
if(temp!=0){
c[temp-1]=temp;
}
}
}
//计算一列
for(int i=0;i<9;i++){
temp=gettitle(x, i);
if(y==i){
continue;
}else{
if(temp!=0){
c[temp-1]=temp;
}
}
}
//计算单元格
//这个表达式是为了求出点击事件的具体大方块位置
int stax=(x/3)*3;
int stay=(y/3)*3;
for(int i=stax;i<stax+3;i++){
for(int j=stay;j<stay+3;j++){
temp=gettitle(i, j);
if(x==i&&y==j){
continue;
}else{
if(temp!=0){
c[temp-1]=temp;
}
}
}
}
//进行冗余处理
int sum=0;
for(int temp1:c){//此处必须重新声明temp1
if(temp1!=0)
sum++;
}
int []usedword=new int [sum];
sum=0;
for(int temp2:c){
if(temp2!=0){
usedword[sum]=temp2;
sum++;
}
}
return usedword;
}
//得到数字板的数独
public int[] getCrossword(String str){
int []sodu=new int[str.length()];
for(int i=0;i<str.length();i++){
//减去0的编码用来算出具体的值
sodu[i]=str.charAt(i)-'0';
}
return sodu;
}
public String gettitleString(int x,int y){
String a=null;
//此处不能直接调用方法 会报错
int b=gettitle(x, y);
if(b==0){
a="";
}
else{
a=String.valueOf(b);
}
return a;
}
//得到对应坐标的数字
public int gettitle(int x,int y){
int temp=crosswords[y*9+x];
return temp;
}
//分析哪些坐标不能改变
public int[][] getflag(){
int temp;
int flag[][]=new int[9][9];
for(int i=0;i<str.length();i++){
//减去0的编码用来算出具体的值
temp=str.charAt(i)-'0';
if(temp==0){
flag[i%9][i/9]=1;
//System.out.println("此处可以填写:"+i%9+" "+i/9);
}
}
return flag;
}
//得到标记
public int flag(int x,int y){
return flag[x][y];
}
//用来在改变数字的时候进行更新
public void settitle(int x,int y,int title){
crosswords[y*9+x]=title;
}
//
public boolean SetTitleValid(int staX,int staY,int title){
int temp[]=getUsedWords(staX, staY);
//用来判断是不是清空按钮
if(title<=9){
for(int t:temp){
//为什么要判断
if(t==title){
System.out.println("==================="+t);
return false;
}
}
settitle(staX,staY,title);
}else{
settitle(staX,staY,0);
}
return true;
}
}
MainView(计算单元格的一个类):
package com.Crosswords.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.text.style.LineBackgroundSpan;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug.FlagToString;
import android.widget.TextView;
public class MainView extends View{
float width;
float height;
int selectedX;
int selectedY;
Game game=new Game();
//画笔不能重用
public MainView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
//计算单元格
width=w/9;
height=h/9;
}
//画笔事件
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint backgroundpaint=new Paint();
backgroundpaint.setColor(Color.parseColor("#C2E7C2"));
canvas.drawRect(0,0,getWidth(),getHeight(), backgroundpaint);
//#BFCDDB小格子颜色
Paint linepaint1=new Paint();
linepaint1.setColor(Color.parseColor("#BFCDDB"));
for (int i = 0; i < 10; i++) {
canvas.drawLine(0,i*getHeight()/9, getWidth(), i*getHeight()/9, linepaint1);
canvas.drawLine(i*getWidth()/9, 0, i*getWidth()/9, getHeight(), linepaint1);
}
Paint linepaint2=new Paint();
linepaint2.setColor(Color.parseColor("#3399FF"));
for(int i=0;i<4;i++){
canvas.drawLine(0, i*getHeight()/3, getWidth(), i*getHeight()/3, linepaint2);
canvas.drawLine(i*getWidth()/3, 0, i*getWidth()/3, getHeight(), linepaint2);
}
Paint numberpaint=new Paint();
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;
String text;
for (int i = 0; i < 9; i++) {
for(int j=0;j<9;j++){
text=game.gettitleString(i, j);
if(game.flag(i,j)==1){
numberpaint.setColor(Color.BLACK);
canvas.drawText(text, width*i+x, height*j+y, numberpaint);
}else{
numberpaint.setColor(Color.parseColor("#6B6743"));
canvas.drawText(text, width*i+x, height*j+y, numberpaint);
}
}
}
}
//监听点击面板事件
@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 [] usedwords=game.getUsedWords(selectedX, selectedY);
StringBuffer usedstr=new StringBuffer();
for(int x:usedwords){
usedstr.append(x+" ");
}
//使用自定义的对话框
/*
LayoutInflater inflater=LayoutInflater.from(this.getContext());
View view=inflater.inflate(R.layout.dialog, null);
TextView text=(TextView)view.findViewById(R.id.used);
text.setText(usedstr.toString());
AlertDialog.Builder builder=new AlertDialog.Builder(this.getContext());
builder.setView(view);
AlertDialog dialog=builder.create();
dialog.show();
*/
//判断坐标是否是原来的数独
if(game.flag(selectedX, selectedY)==1){
DialogView dialog=new DialogView(getContext(), usedwords,this);
dialog.show();
}
return true;
}
public void SetSelectTitle(int title){
if(game.SetTitleValid(selectedX, selectedY, title)){
//刷新页面
invalidate();
}
}
}