您的位置:首页 > 其它

安卓开发_数独游戏基础

2014-08-26 20:00 190 查看
主要学习内容:

1、图形编程

2、自定义View类

3、FontMmetrics

4、单击触摸事件

5、碰撞检测

6、可用数据计算

图形编程基本概念:

1、颜色对象

Color 安卓系统中的颜色的表示方法

(1)、int color = Color.blue; //纯色

(2)、int color = Color.argb(188,255,255,255);//自定义颜色

(3)、在xml文件当中定义颜色

2、画笔对象

Paint 该类的对象用于控制画笔的风格和颜色等方面的信息

(1)、paint.setColor(Color.blue);

3、canvas 该类代表一块“画布”,可以在“画布”上绘制字符,图形和图片

(1)、canvas.drawcircle(300,400,100,paint);

自定义View的基本实现方法:

(1)、定义一个类,继承View

(2)、复写View的onDraw函数

(3)、在onDraw当中使用canvas和paint对象绘制图形

Paint的设置方法:

1、setAntiAlias:设置画笔的锯齿效果

2、setARGB:设置画笔的argb对象

3、setTextSize:设置字体尺寸

4、setColor:设置画笔颜色

5、setAlpha:设置透明度值

6、setStyle:设置画笔风格,空心或实心

7、getColor:得到画笔颜色

8、getApha:得到画笔的透明度值

public boolean onTouchEvent(MotionEvent event){

  //获得事件的种类

  event.getAction();

  //获取点击的坐标

  event.getX();

  event.getY();

}

直接上代码

总共四个类

一、ShuduView.java 游戏界面构画

package myview;

import xqx.shudu.Game;
import xqx.shudu.R;
import xqx.shudu.SelectDialog;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
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 Game game = new Game();
int selectx;
int selecty;
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
//1、绘制背景
Paint bgpaint = new Paint();
bgpaint.setColor(Color.GRAY);
//绘制背景色
canvas.drawRect(0, 0, getWidth(), getHeight(), bgpaint);

Paint drakpaint = new Paint();
drakpaint.setColor(Color.WHITE);

Paint whitepaint = new Paint();
whitepaint.setColor(Color.BLACK);

for (int i = 0; i < 9; i++) {
//绘制横向的单元格线
canvas.drawLine(0, i*height, getWidth(), i*height, whitepaint);
canvas.drawLine(0, i*height+1, getWidth(), i*height+1, whitepaint);
//绘制纵向的单元格的线
canvas.drawLine(i*width, 0, i*width, getHeight(), whitepaint);
canvas.drawLine(i*width+1, 0, i*width+1, getHeight(), whitepaint);
}
//绘制横竖各三条分割线
for (int i = 0; i < 9; i++) {
if(i%3!=0)
{
continue;
}
//绘制横向的单元格线
canvas.drawLine(0, i*height, getWidth(), i*height, drakpaint);
canvas.drawLine(0, i*height+1, getWidth(), i*height+1, drakpaint);
//绘制纵向的单元格的线
canvas.drawLine(i*width, 0, i*width, getHeight(), drakpaint);
canvas.drawLine(i*width+1, 0, i*width+1, getHeight(), drakpaint);
}
//绘制数字
Paint numberpaint = new Paint();
numberpaint.setColor(Color.BLACK);
numberpaint.setStyle(Style.STROKE);
numberpaint.setTextSize((float) (height*0.75));
numberpaint.setTextAlign(Align.CENTER);//居中对齐

FontMetrics fm = numberpaint.getFontMetrics();
float x = width/2;
float y = height/2-(fm.ascent-fm.descent)/2;
// 计算文字高度
float fontHeight = fm.bottom - fm.top;
// 计算文字baseline
float textBaseY = height - (height - fontHeight) / 2 - fm.bottom;
//canvas.drawText("1", 3*width+x, textBaseY, numberpaint);
//绘制数字
for(int i=0;i<9;i++)
{
for(int j=0; j<9;j++)
{
canvas.drawText(game.getTitlStringe(i,j), i*width+x, j*height+textBaseY, numberpaint);
}
}
super.onDraw(canvas);
}
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()!=MotionEvent.ACTION_DOWN)
{
return super.onTouchEvent(event);
}

//得到点击位置的x,y坐标
selectx = (int) (event.getX()/width);
selecty = (int) (event.getY()/height);

int used[] = game.getused(selectx,selecty);
StringBuffer strbuf = new StringBuffer();
for(int i=0;i<used.length;i++)
{
strbuf.append(used[i]+"、");
}

SelectDialog seldia = new SelectDialog(getContext(),used,this);
seldia.show();
return true;

}

//View类接受KeyDialog传递过来的数据,调用业务逻辑Game类,进行处理
public void setSelectTile(int tile)
{
if(game.setTileIfValid(selectx,selecty,tile))
{
invalidate();//重新绘制View对象
}
}
}


二、Game.java 用于处理数独数据

package xqx.shudu;

public class Game {
//数独数据初始化
private final String str = "360000000" +
"004230800" +
"000004200" +
"070460003" +
"820000014" +
"500013020" +
"001900000" +
"007048300" +
"000000045";
private int shuduku[]=new int[9*9];
//用来存储每个单元格不可填写的数字
//1维 x坐标 2维 y坐标 3维 不可填写数字
private int used[][][]=new int[9][9][];
public Game(){
shuduku = fromPuzzleString(str);
calAllused();
}

//根据字符串数据生成整型数组
public int[] fromPuzzleString(String str2) {
// TODO Auto-generated method stub
int shudu[] = new int[str2.length()];
for(int i=0;i<shudu.length;i++)
{
shudu[i]=str2.charAt(i)-'0'; //吧字符转换为数字
}
return shudu;
}

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

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

//计算某单元格已经不可填写的数字
public int[] calUsed(int x,int y){
int c[]= new int[9];

//判断y这一列,如果遍历他自己 ,跳过,如果遍历单元格数字不为0,则放入数组中
for(int i=0;i<9;i++)
{
if(i==y)
continue;
int t = getTitile(x, i);
if(t!=0)
c[t-1]=t;
}
//判断x这一行,如果遍历他自己 ,跳过,如果遍历单元格数字不为0,则放入数组中
for(int i=0;i<9;i++)
{
if(i==x)
continue;
int t = getTitile(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 = getTitile(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 c;
}

//计算所有单元格不可用数字数组
public void calAllused(){
for(int x=0;x<9;x++)
{
for(int y=0;y<9;y++){
used[x][y]=calUsed(x, y);
}
}
}

//得到该单元格不可用数字
public int[] getused(int x,int y){
return used[x][y];
}
//接收KeyDialog中点击的数字
public boolean setTileIfValid(int x, int y, int value)
{
int[] tiles = getused(x, y);//得到不可用的数据

if (value != 0)
{
for (int t : tiles)
{
if (t == value)
return false;
}
}
setSelectNum(x, y, value);//将对应的值value绘制在xy对应的格子中
calAllused();//重新计算所有格子的不可用数据

return true;
}

//在数独数组中更改填写后的数字
private void setSelectNum(int x, int y, int num) {
// TODO Auto-generated method stub
shuduku[y*9+x]=num;
}
}


三、SelectDialog.java 用于设置填写数字的对话框

package xqx.shudu;

import myview.ShuduView;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class SelectDialog extends Dialog{
int q;
//当dialog第一次显示时会调用其onCreate方法
//用来存放对话框中按钮对象
private ShuduView shuduview;
private  View key[] = new View[9];
private  int used[];
public SelectDialog(Context context, int used[],ShuduView shuduview) {

super(context);
this.used=used;
this.shuduview = shuduview;
// TODO Auto-generated constructor stub
}

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setTitle("选择填入的数字");
setContentView(R.layout.shudu_diolag);//设置布局文件
findView();

for(int i=0;i<used.length;i++)
{
if(used[i]!=0)
{
key[used[i]-1].setVisibility(View.INVISIBLE);
}
}
//为对话框中所有内容设置监听器
setListener();
}

//为按钮设置监听器
public void setListener()
{
for(int i = 0; i<key.length; i++)
{
final int t = i+1;
key[i].setOnClickListener(new View.OnClickListener()
{

@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
returnResult(t);
}
});
}
}

//对话框将选择的数据传递给View对象,让其处理业务逻辑
public void returnResult(int tile)
{
shuduview.setSelectTile(tile);
dismiss();
}

private void findView() {
// TODO Auto-generated method stub
key[0] = findViewById(R.id.btn_1);
key[1] = findViewById(R.id.btn_2);
key[2] = findViewById(R.id.btn_3);
key[3] = findViewById(R.id.btn_4);
key[4] = findViewById(R.id.btn_5);
key[5] = findViewById(R.id.btn_6);
key[6] = findViewById(R.id.btn_7);
key[7] = findViewById(R.id.btn_8);
key[8] = findViewById(R.id.btn_9);
}
}


四、MainActivty.java 在主类中调用MyView对象

package xqx.shudu;
import myview.*;
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);
setContentView(new ShuduView(this));
//        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;
}

}


五:布局文件

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:stretchColumns="*"
android:orientation="vertical" >

<TableRow >
<Button android:id="@+id/btn_1"
android:text="1"/>
<Button android:id="@+id/btn_2"
android:text="2"/>
<Button android:id="@+id/btn_3"
android:text="3"/>
</TableRow>
<TableRow >
<Button android:id="@+id/btn_4"
android:text="4"/>
<Button android:id="@+id/btn_5"
android:text="5"/>
<Button android:id="@+id/btn_6"
android:text="6"/>
</TableRow>
<TableRow >
<Button android:id="@+id/btn_7"
android:text="7"/>
<Button android:id="@+id/btn_8"
android:text="8"/>
<Button android:id="@+id/btn_9"
android:text="9"/>
</TableRow>

<Button
android:id="@+id/btn_cannel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />

</TableLayout>


效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: