zoukankan      html  css  js  c++  java
  • 数独游戏设计与实现之第三篇——项目开发的过程

    分成四个类: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();
             }
    	}
    }
    
  • 相关阅读:
    31天重构指南之二十:提取子类
    31天重构指南之二十二:分解方法
    大叔手记(17):大叔2011年读过的书及2012年即将要读的书
    深入理解JavaScript系列(5):强大的原型和原型链
    深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)
    深入理解JavaScript系列(11):执行上下文(Execution Contexts)
    深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
    深入理解JavaScript系列(4):立即调用的函数表达式
    深入理解JavaScript系列(3):全面解析Module模式
    深入理解JavaScript系列(7):S.O.L.I.D五大原则之开闭原则OCP
  • 原文地址:https://www.cnblogs.com/liaozhuoshen/p/4839192.html
Copyright © 2011-2022 走看看