Android图形编程基本概念

  1. 颜色对象

    Color 类

    int color = Color.bule    //蓝色

    int color = Color.argb(255,255,255,255);        //透明度,红,绿,蓝

    在XML文件中定义颜色

  2. 画笔对象

    Paint 类

    Paint.setColor(Color.blue);

  3. 画布对象

    Canvas 类

    Canvas.drawCircle(300, 400, 100, paint);

自定义View的基本实现方法

  1. 定义一个类,继承View
  2. 复写View中的onDraw()方法
  3. 在onDraw()中使用Canvas和Paint绘制图形

    矩形。圆形、空心、实心、线、文字、……

@Override

protected void onDraw(Canvas canvas) {

Paint paint = new Paint();

paint.setARGB(255, 0, 255, 0);

paint.setStyle(Paint.Style.STROKE);// 空心

paint.setStrokeWidth(10);// 边的宽度

canvas.drawRect(100, 100, 500, 500, paint);// 矩形

paint.setStyle(Paint.Style.FILL);// 实心

paint.setColor(Color.CYAN);

canvas.drawCircle(500, 500, 100, paint);// 圆形

paint.setTextSize(100);

paint.setColor(Color.BLUE);

canvas.drawText("Apple ggGG", 50, 800, paint);

paint.setColor(Color.RED);

paint.setStrokeWidth(5);// 边的宽度

canvas.drawLine(0, 800, 720, 800, paint);

canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),

R.drawable.ic_launcher), 200, 200, paint);

super.onDraw(canvas);

}

绘制九宫格

@Override

protected void onDraw(Canvas canvas) {

// 首先取得屏幕的宽度和高度

width = this.getWidth();

cell_width = width / 9f;

height = this.getHeight();

cell_height = height / 9f;

// 首先画出背景

Paint bgPaint = new Paint();// 用于绘制背景

bgPaint.setColor(getResources().getColor(R.color.shudu_background));

canvas.drawRect(0, 0, width, height, bgPaint);

// 画出九宫格

Paint darkPaint = new Paint();// 暗色

darkPaint.setColor(getResources().getColor(R.color.shudu_dark));

Paint lightPaint = new Paint();// 亮色

darkPaint.setColor(getResources().getColor(R.color.shudu_light));

Paint hilitePaint = new Paint();// 线条

darkPaint.setColor(getResources().getColor(R.color.shudu_hilite));

for (int i = 0; i < 9; i++) {

if (i % 3 == 0) {

canvas.drawLine(0, i * cell_height, width, i * cell_height,

lightPaint);

canvas.drawLine(i * cell_width, 0, i * cell_width, height,

lightPaint);

} else {

canvas.drawLine(0, i * cell_height, width, i * cell_height,

darkPaint);

canvas.drawLine(i * cell_width, 0, i * cell_width, height,

darkPaint);

}

canvas.drawLine(0, i * cell_height + 1, width, i * cell_height + 1,

hilitePaint);

canvas.drawLine(i * cell_width + 1, 0, i * cell_width + 1, height,

hilitePaint);

}

// 绘制文字

Paint numPaint = new Paint();

numPaint.setColor(Color.BLUE);

numPaint.setStyle(Paint.Style.STROKE);

numPaint.setTextSize(cell_height * 0.25f);

numPaint.setTextAlign(Paint.Align.CENTER);

float x = cell_width / 2;

float y = cell_height / 2;

for (int i = 0; i < 9; i++) {

for (int j = 0; j < 9; j++) {

canvas.drawText("" + i + "," + j, i * cell_width

+ x, j * cell_height + y, numPaint);

}

}

super.onDraw(canvas);

}

文字居中显示

FontMtrics类

FontMetrics fontMetrics = paint.get FontMetrics();

FontMetrics fm = numPaint.getFontMetrics();

float x = cell_width / 2;

float y = cell_height / 2 - (fm.ascent + fm.descent) / 2;

显示数据

把逻辑处理放在Activity外部,新建一个类

package com.arlen.android.game.shudu03;

public class Game {

private final String str = "450890000000000000008700090607005030090020040040900102070006300000000000000048016";

private int shuduku[] = new int[81];

public Game() {

shuduku = fromPuzzleString(str);

}

private int getTitle(int x, int y) {

return shuduku[y * 9 + x];

}

public String getTitleString(int x, int y) {

int v = getTitle(x, y);

if (v == 0) {

return "";

} else {

return String.valueOf(v);

}

}

protected int[] fromPuzzleString(String src) {

int sudu[] = new int[src.length()];

for (int i = 0; i < sudu.length; i++) {

sudu[i] = src.charAt(i) - '0';

}

return sudu;

}

}

在View中调用

for (int i = 0; i < 9; i++) {

for (int j = 0; j < 9; j++) {

canvas.drawText(game.getTitleString(i, j), i * cell_width + x,

j * cell_height + y, numPaint);

}

}

单点触摸事件

在为初始化数字的空格中点击,然后输入数字

public Boolean onTouchEvent(MotionEvent event){

//获取事件的类型

event.getAction();

//获取点击坐标

Event.getX();

Event.getY();

}

// 生成一个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.textViewUsedId);

// 设置textView的内容

textView.setText(sb.toString());

// 生成一个对话框的builder对象

AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());

// 设置地对话框所要显示的内容

builder.setView(layoutView);

// 生成对话框对象并将其显示出来

AlertDialog dialog = builder.create();

dialog.show();

碰撞检测

用户点击屏幕之后,确定用户点击的位置属于哪一个格子

取得用户点击的坐标,判断是否在startX、startY与stopX、stopY之间

@Override

public boolean onTouchEvent(MotionEvent event) {

if (event.getAction() != MotionEvent.ACTION_DOWN) {

return super.onTouchEvent(event);

}

int selectX = (int) (event.getX() / cell_width);

int selectY = (int) (event.getY() / cell_height);

int used[] = game.getUsedTileByCoor(selectY, selectY);

for (int i = 0; i < used.length; i++) {

System.out.println(used[i]);

}

return true;

}

可用数据计算

在每一行、每一列、每一个小的九宫格中已有的数据禁止重复输入,

//用于计算所有单元格对应的不可用的数据

public void calculateAllUsedTitles() {

for (int x = 0; x < 9; x++) {

for (int y = 0; y < 9; y++) {

used[x][y] = calculateUsedTiles(x, y);

}

}

}

//取出某一单元格已经不可用的数据

public int[] getUsedTileByCoor(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 = getTitle(x, i);

if (t != 0) {

c[t - 1] = t;

}

}

for (int i = 0; i < 9; i++) {

if (i == x) {

continue;

}

int t = getTitle(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 = getTitle(i, y);

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;

}

弹出交互对话框

布局文件

<?xml version="1.0" encoding="utf-8"?>

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/keypad"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical" >

<TableRow>

<Button

android:id="@+id/button1"

android:text="1" />

<Button

android:id="@+id/button2"

android:text="2" />

<Button

android:id="@+id/button3"

android:text="3" />

</TableRow>

<TableRow>

<Button

android:id="@+id/button4"

android:text="4" />

<Button

android:id="@+id/button5"

android:text="5" />

<Button

android:id="@+id/button6"

android:text="6" />

</TableRow>

<TableRow>

<Button

android:id="@+id/button7"

android:text="7" />

<Button

android:id="@+id/button8"

android:text="8" />

<Button

android:id="@+id/button9"

android:text="9" />

</TableRow>

</TableLayout>

根据点击的位置不同,弹出的窗口不同

package com.arlen.android.game.shudu03;

import android.app.Dialog;

import android.content.Context;

import android.os.Bundle;

import android.view.View;

public class KeyDialog extends Dialog {

// 用来存放代表对话框中按钮的对象

private final View keys[] = new View[9];

private final int used[];

// 构造函数的第二个参数保存当前单元格已经用过的数据

public KeyDialog(Context context, int[] used) {

super(context);

this.used = used;

}

// 当对话框第一次被调用的时候,会调用其onCreate方法

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 标题

this.setTitle("Key Dialog");

// 为该对话框设置布局文件

this.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);

}

}

}

private void findViews() {

keys[0] = findViewById(R.id.button1);

keys[1] = findViewById(R.id.button2);

keys[2] = findViewById(R.id.button3);

keys[3] = findViewById(R.id.button4);

keys[4] = findViewById(R.id.button5);

keys[5] = findViewById(R.id.button6);

keys[6] = findViewById(R.id.button7);

keys[7] = findViewById(R.id.button8);

keys[8] = findViewById(R.id.button9);

}

}

Android 数独游戏 记录的更多相关文章

  1. android数独游戏

    最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...

  2. android开发——数独游戏

    最近研究了一下android,写了一个数独游戏,具体如下: 游戏界面需要重写一个ShuduView继承View, 然后自定义一个Dialog: 1.需要继承 Dialog 类, 2.并要定义一个有参构 ...

  3. iOS开发 Swift开发数独游戏(一)

    一.前言 我姥姥是一名退休数学老师,一直很喜欢玩数独游戏.我以前答应过她要给她写一个数独游戏.本来计划是写一个Android应用的,但恰好我学了好长时间iOS开发一直没做什么"大项目&quo ...

  4. 用html5 canvas和JS写个数独游戏

    为啥要写这个游戏? 因为我儿子二年级数字下册最后一章讲到了数独.他想玩儿. 因为我也想玩有提示功能的数独. 因为我也正想决定要把HTML5和JS搞搞熟.熟悉一个编程平台,最好的办法,就是了解其原理与思 ...

  5. Scrum4.0+5.0 数独游戏

    1.题目: 1.准备看板. 形式参考图4. 2.任务认领,并把认领人标注在看板上的任务标签上. 先由个人主动领任务,PM根据具体情况进行任务的平衡. 然后每个人都着手实现自己的任务. 3.为了团队合作 ...

  6. C语言学习 数独游戏

    摘要:花了1周多时间学习了C语言,开始练手写解数独游戏的程序. C语言学习 数独游戏 作者:乌龙哈里 时间:2015-11-22 平台:Window7 64bit,TCC 0.9.26(x86-64 ...

  7. Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高!

    Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高! 群英传的最后一章,我大致的看了一下这个例子,发现鸿洋大神也做过,就参考两个人的设计逻辑,感觉都差不多,就这样实现起来了 ...

  8. 【DFS】数独游戏

    DFS(深度优先搜索): 深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法. 沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所在 ...

  9. 创建随机的9x9数独游戏终盘并打印

    创建随机的9x9数独游戏终盘并打印 项目github地址 1. 项目相关要求 1.1 要求 利用程序随机构造出N个已解答的9x9数独棋盘 . 输入 数独棋盘题目个数N(0<N<=10000 ...

随机推荐

  1. Linux远程文件传输

    linux系统中,难免会遇到一些要将某文件通过网络传送给其他主机的情况,而恰好两台主机 都是linux系统的时候,我们就可以直接使用scp命令来传输文件到另一台主机了. scp命令用于在网络中安全的传 ...

  2. apache-hadoop-1.2.1、hbase、hive、mahout、nutch、solr安装教程

    1 软件环境: VMware8.0 Ubuntu-12.10-desktop-i386 jdk-7u40-linux-i586.tar.gz hadoop-1.2.1.tar.gz eclipse-d ...

  3. Cocos2dx+lua中Color参数的坑

    cocos2x的lua中有如下几种颜色定义 --Color3B function cc.c3b( _r,_g,_b ) return { r = _r, g = _g, b = _b } end -- ...

  4. word2vec——高效word特征提取

    继上次分享了经典统计语言模型,最近公众号中有很多做NLP朋友问到了关于word2vec的相关内容, 本文就在这里整理一下做以分享. 本文分为 概括word2vec 相关工作 模型结构 Count-ba ...

  5. linux 僵死进程

    僵死进程简而言之就是:子进程退出时,父进程并未对其发出的SIGCHILD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程. 在fork()/execve( ...

  6. testNG中@Factory详解

    @Factory注解从字面意思上来讲就是采用工厂的方法来创建测试数据并配合完成测试,其主要应对的场景是:对于某一个测试用例或方法,我们需要输入多个测试数据进行测试,并且这些测试数据可以是有一定关系(可 ...

  7. dojo 六 使用query dojo/query

    要使用query,就要引入dojo/query包.query可以根据Dom里节点的标签名.id名.class名来检索一个或多个节点.---------------------------------- ...

  8. spring3定时器简单配置

    最近在做oa项目中写到一个功能,就是员工每天的签到和签退.当时想了很久都没有想出来,后来自己上网查了一下spring的定时器,然后就有了思路. 下面我贴上自己用到的这个定时器的配置.希望能够和大家一起 ...

  9. BZOJ 2727 双十字(树状数组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2727 题意: 思路:思路来自这里.首先对于每个位置(i,j)用C[i][j]表示该位置同 ...

  10. hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等

    hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...