基于Android的数独游戏-----用Java语言编写
16lz
2021-01-23
1、在src中有4个Java类:
其中代码分别是:
Game.java:
<pre name="code" class="java">package com.example.test1;import android.R.integer;public class Game { public final String str="360000000004230800000004200" +"070460003820000014500013020" +"001900000007048300000000045";/*public final String str="124576893"+"967348521"+"835291674"+ "259784316"+"316952748"+"748613902"+"582439160"+"493167285"+"671825430";*/ static int sudoku[]=new int [9*9]; private int used[][][]=new int[9][9][]; int sum=0; public int[] getSudoku(){ return sudoku; } public int sum(int a[]){ for(int i=0;i<a.length;i++) sum+=a[i]; return sum; } public Game() { sudoku=fromPuzzleString(str); calculateAllUesdTiles(); } // 根据九宫格中的坐标,返回该坐标,所应该返回的数字 public 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 calculateAllUesdTiles() { for(int x=0;x<9;x++) { for(int y=0;y<9;y++) { used[x][y]=calculateUesdTiles(x,y); } } } //取出某一单元格当中已经不可用的数据 public int[] getUsedTileByCoor(int x, int y) { return used[x][y]; } //计算某一单元格当中不可用的数据 private int[] calculateUesdTiles(int x,int y) { // TODO Auto-generated method stub 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; } } 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); calculateAllUesdTiles(); return true; } private 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.test1;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 myView; //构造函数的第二个参数当中保存着当前单元格已经使用过的数字 public KeyDialog(Context context,int[] used,ShuduView myView) { super(context); this.used=used; this.myView=myView; } //当一个Dialog第一次显示的时候,会调用Oncreate方法 @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //设置标题 setTitle("KeyDialog"); //用于为该Dialog设置布局文件 setContentView(R.layout.keypad); findViews(); //遍历整个used数组 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); } //通知MyView对象,刷新整个九宫格显示的数据 private void returnResult(int tile) { myView.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() { @Override public void onClick(View v) { // TODO Auto-generated method stub returnResult(t); } }); } }}ShuduView.java:
package com.example.test1;import android.R.integer;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetrics;import android.graphics.Paint.FontMetricsInt;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; int selectedX; int selectedY; private Game game=new Game(); public ShuduView(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 this.width=w/9f; this.height=h/9f; super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub //绘制背景颜色 Paint background_paint = new Paint(); background_paint.setColor(getResources().getColor(R.color.shudu_background)); canvas.drawRect(0, 0, getWidth(), getHeight(), background_paint); Paint white=new Paint(); white.setColor(getResources().getColor(R.color.shudu_hilite)); Paint light=new Paint(); light.setColor(getResources().getColor(R.color.shudu_light)); Paint dark=new Paint(); dark.setColor(getResources().getColor(R.color.shudu_dark)); for(int i=0;i<9;i++) { //画出横向的线 canvas.drawLine(0, i*height, getHeight(), i*height, light); canvas.drawLine(0, i*height+1, getHeight(), i*height+1, white); //画出纵向的线 canvas.drawLine( i*width,0, i*width,getHeight(), light); canvas.drawLine( i*width+1,0, i*width+1, getHeight(), white); } for(int i=0;i<9;i++) { if(i%3!=0) { continue; } canvas.drawLine(0, i*height, getHeight(), i*height, dark); canvas.drawLine(0, i*height+1, getHeight(), i*height+1, white); //画出纵向的线 canvas.drawLine( i*width,0, i*width,getHeight(), dark); canvas.drawLine( i*width+1,0, i*width+1, getHeight(), white); } Paint number_paint=new Paint(); number_paint.setColor(Color.BLACK); //number_paint.setStyle(Paint.Style.STROKE); number_paint.setTextSize(height*0.75f); number_paint.setTextAlign(Paint.Align.CENTER); FontMetrics fm=number_paint.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), width*i+x, height*j+y, number_paint); } } super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub if(event.getAction()!=MotionEvent.ACTION_DOWN) { return super.onTouchEvent(event); } selectedX=(int)(event.getX()/width); selectedY=(int)(event.getY()/height); int used[]=game.getUsedTileByCoor(selectedX, selectedY); int sum=0; int sumNumber=0; sumNumber=game.sum(game.getSudoku()); if(sumNumber==45*9){ AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); builder.setMessage("Success!") .setPositiveButton("Exit", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface arg0, int arg1) {arg0.cancel();}}); AlertDialog alertDialog=builder.create(); alertDialog.show(); } else { for(int i=0;i<used.length;i++){ sum+=used[i]; } if(sum==45){ AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); builder.setMessage("No Number!") .setNegativeButton("Exit", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { arg0.cancel(); } }); AlertDialog alertDialog=builder.create(); alertDialog.show(); } else { StringBuffer sb=new StringBuffer(); for(int i=0;i<used.length;i++) { sb.append(used[i]);// System.out.println(used[i]); } KeyDialog keyDialog= new KeyDialog(getContext(),used,this); keyDialog.show(); }} /*StringBuffer sb=new StringBuffer(); for(int i=0;i<used.length;i++) { sb.append(used[i]);// System.out.println(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) { // TODO Auto-generated method stub if(game.setTileIfValid(selectedX,selectedY,tile)){ invalidate(); } }}
MainActivity.java:
package com.example.test1;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); ShuduView sView=new ShuduView(this); setContentView(sView); //setContentView(R.layout.activity_main); } @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; } }
2、布局Layout中的配置文件:
其中activity_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>
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>
<?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" > </LinearLayout> --><TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/keypad" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:stretchColumns="*"> <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>
3、values中的配置文件
就只有color.xml是自己写的,另外三个都是自动生成
color.xml
<?xml version="1.0" encoding="utf-8"?><resources> <color name="shudu_background">#ffe6f0ff</color> <color name="shudu_dark">#64ff0000</color> <color name="shudu_light">#64ffffff</color> <color name="shudu_hilite">#6400ff00</color></resources>
4、一切就绪直接运行就0k
更多相关文章
- Android实现读写JSON数据的方法
- Android时间对话框
- android 检测sqlite数据表和表中字段(列)是否存在 (转)
- android sqlite 自增数据类型
- android打开数据连接(目测最稳定方式)
- Android SQLite数据库存储实现
- android对话框的进一步使用
- Android与C++ 使用socket传输数据