实现思路:因为手机传感器每隔一段时间会发送采集到的数据包, 首先获取第一个数据包所在的三个轴的加速度值,记录, 当过一段时间之后再次获取三个轴的加速度值,计算增量,将相邻两个点的增量进行汇总,当达到预先设定的阀值,说明手机摇晃了。
实现步骤:
1、记录第一个点的数据: 三个轴的加速度,为了屏蔽不同手机采样的时间间隔差异,将第一个点的时间也记录下 来。
2、选取第二个点的数据:当有新的传感器数据传递进来后,用当前的时间与第一个点的时间进行比对,判断时间间 隔,如果满足了时间间隔(经验值:100)的要求,认为是合格的第二个点,否则舍弃改数据包。
3、 进行增量的计算:获取到的新的加速度值与第一个点上的加速度值进行差值运算,获取到一点和二点之间的增量,将三个增量值进行汇总。
4、以此类推,获取到相邻两个点的增量,进行汇总。
5、通过汇总的值与之前设定好的阀值(经验值:200)进行比对,如果>=阀值,用户摇晃手机。否则记录当前点的数据(加速度的值 和 该点的时间)。
一、核心传感器监听代码:
package com.huang.mylottery.view.sensor;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.Vibrator;
/**
* 处理传感器监听
*
* @author wuseyukui
*
*/
public abstract class ShakeListener implements SensorEventListener {
// 判断手机摇晃的阈值
private final static float SWITH_VALUE = 200f;
private final static long DURATION = 100;
private Vibrator vibrator;
private float lastX;
private float lastY;
private float lastZ;
private long lastTime;
private float total;
public ShakeListener(Context context) {
super();
vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE );
}
private void initParam() {
lastX = 0;
lastY = 0;
lastZ = 0;
lastTime = 0;
total = 0;
}
@Override
public void onSensorChanged(SensorEvent event) {
// 判断 是否第一个点
if ( lastX == 0 && lastY == 0 && lastZ == 0 && lastTime == 0) {
// 记录三个轴的加速度值
float[] values = event. values;
lastX = values[0];
lastY = values[1];
lastZ = values[2];
lastTime = System. currentTimeMillis();
total = lastX + lastY + lastZ;
} else {
// 尽可能屏蔽掉不同手机传感器的差异
if (System. currentTimeMillis() - lastTime > DURATION) {
float[] values = event. values;
// 第二个点及以后
float x = values[0];
float y = values[1];
float z = values[2];
// 计算增量
float dx = Math. abs(x-lastX);
float dy = Math. abs(y-lastY);
float dz = Math. abs(z-lastZ);
// 尽量屏蔽掉微小的增量值
if (dx < 1) {
dx = 0;
}
if (dy < 1) {
dy = 0;
}
if (dz < 1) {
dz = 0;
}
// 极个别手机,静止状态 某个轴的增量会大于1,10以上,甚至100以上
if (dx == 0 && dy == 0 && dz == 0) {
initParam();
return;
}
// 汇总(一点和二点总得增量)
float shake = dx + dy + dz;
if(shake == 0) {
initParam();
return;
}
total += shake;
if ( total >= SWITH_VALUE) {
// 手机摇晃了
// 机选一注彩票
RandomCure();
// 提示用户
vibrator.vibrate(100);
// 所有的数据都要初始化
initParam();
} else {
lastX = x;
lastY = y;
lastZ = z;
lastTime = System. currentTimeMillis();
}
}
}
}
public abstract void RandomCure();
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
二、注册监听
listener = new ShakeListener(context){
@Override
public void RandomCure() {
//机选一注
randomSSQ();
}
};
// 注册传感器监听
sensor.registerListener( listener,
sensor.getDefaultSensor(Sensor. TYPE_ACCELEROMETER),
SensorManager. SENSOR_DELAY_FASTEST);
二、各种彩票的算法
package cn.com.soarmobile.lottery;
import android.content.res.TypedArray;
import cn.com.soarmobile.SoarEngine;
import cn.com.soarmobile.bean.LotteryCartItem;
import cn.com.soarmobile.util.CalculatorUtils;
/**
* Type代表彩种玩法(如:任选一、任选二); Mode代表选号类型(如:直选)
*
* @author Administrator
*
*/
public abstract class LotteryBase {
/**
* 彩种LOGO
*/
public int icon;
/**
* 彩种名字 例如排列三
*/
public String name;
/**
* 彩种名字编号 例如排列三:p3 双色球:ssq
*/
public String gameName;
/**
* 彩种代号 例如双色球:001 福彩3D:002
*/
public String code;
/**
* 官方规则
*/
public int officialrule;
/**
* 奖金说明
*/
public int prizeexplain;
/**
* 彩票期数 例如20110115
*/
public String issue;
/**
* 彩种简介,例如:天天排列3,不愁吃喝穿
*/
public String summary;
/**
* 购买一注的价格
*/
public int price;
/**
* 购买截止时间
*/
public String deadLine;
/**
* 红色选号区标签 如只有红色球 则显示选号 蓝球选号区域不显示
*/
public String redTag;
/**
* 蓝色选号区标签 如果木有蓝球 该区域不显示
*/
public String buleTag;
/**
* 最少要选择的红球数 例如双色球至少选6个红球
*/
public int redMin;
/**
* 最少要选择的蓝球数 例如双色球至少选1个蓝球 值可以为0
*/
public int blueMin;
/**
* 选号规则介绍 例如 请选择至少六个红球和一个蓝球
*/
public String[] rules;
/**
* 当前模式选号规则
*/
public String currentRule;
/**
* 彩种玩法,例如:任选一、任选二
*/
public String[] playType;
/**
* 当前彩种玩法 <br>
* 参照{@link #playType playType}
*/
protected String currentType;
/**
* 机选玩法,例如:二星、三星、五星 <br>
* 该玩法目前为{@link #playType playType}的子集
*/
public String[] autoPlayType = null;
/**
* 选号类型,例如:直选、组选、通选
*/
public String[] playMode;
/**
* 当前选号类型 <br>
* 参照{@link #playMode playMode}
*/
protected String currentMode;
/**
* 不同玩法 模式的注意事项提醒
*/
public String[] notices;
/**
* 当前模式注意事项
*/
public String currentNotice;
/**
* 是否允许追加
*/
public boolean allowAddTo = false;
/**
* 是否格式化显示号码 例如 双色球01,02,03
*/
public boolean format = false;
/**
* 获取红球选号池 例如 :排列三{0,1,2,3,4,5,6,7,8,9} 选号类型和选号模式影响改返回值
*
* @return
*/
/**
* 根据playtype和playmode计算出来当前索引
*/
public int currentIndex;
public abstract int[] getRedPool();
protected int[] getRedPool(int resId) {
String[] redrules = getStringArray(resId);
String temp = redrules[currentIndex];
String[] string = temp.split("-");
int count = Integer.parseInt(string[1]);
int start = Integer.parseInt(string[2]);
int end = Integer.parseInt(string[3]);
return CalculatorUtils.createBalls(count, start, end);
}
/**
* 红球选择区的显示时候的列数
*
* @return
*/
public abstract int getRedColumnCount();
protected int getRedColumnCount(int resId) {
String[] redrules = getStringArray(resId);
String temp = redrules[currentIndex];
String[] string = temp.split("-");
return Integer.parseInt(string[0]);
}
/**
* 获取蓝球选号池 例如排列三{0,1,2,3,4,5,6,7,8,9} 选号类型和选号模式影响改返回值
*
* @return
*/
public abstract int[] getBluePool();
protected int[] getBluePool(int resId) {
String[] redrules = getStringArray(resId);
String temp = redrules[currentIndex];
String[] string = temp.split("-");
int count = Integer.parseInt(string[1]);
int start = Integer.parseInt(string[2]);
int end = Integer.parseInt(string[3]);
return CalculatorUtils.createBalls(count, start, end);
}
/**
* 蓝球选择区的显示时候的列数
*
* @return
*/
public abstract int getBlueColumnCount();
protected int getBlueColumnCount(int resId) {
String[] redrules = getStringArray(resId);
String temp = redrules[currentIndex];
String[] string = temp.split("-");
return Integer.parseInt(string[0]);
}
/**
* 机选红球
*/
public abstract int[] getRandomRed();
/**
* 机选蓝球
*/
public abstract int[] getRandomBlue();
/**
* 机选n注号码
* 返回int[][]
*/
public abstract int[][] getRandom(int n);
/**
* 机选n注号码
* 返回String[]
* 这样就不用根据redMin blueMin判断填充那种颜色了,
* 减少彩种切换时对redMin和blueMin的管理
*/
public abstract String[] getRandomString(int n);
/**
* 判断当前选择是否合法
*
* @param red
* @param bule
* @return
*/
public abstract boolean isValid(int[] red, int[] bule);
/**
* 计算当前选了多少注 数学公式C(red,bule)或A(red,bule)
*
* @param red
* 当前选择的红球
* @param bule
* 当前选择的蓝球
* @return 计算出注数
*/
public abstract long calculatorBoxes(int[] red, int[] bule);
/**
* 重新为默认设置
*/
public abstract void reset(boolean isAutoToManual);
/**
* 根据plaype和playMode获取索引 例如 福彩3d {直选 复式}对应索引0 {直选 單式}对应索引1 {组三 复式}对应索引2
*/
public int getIndex(int resId) {
int n = 0;
for (int i = 0; i < playType.length; i++) {
String[] strings = CountModeByType(resId, i);
for (int j = 0; j < strings.length; j++) {
if (currentType.equals(playType[i])
&& currentMode.equals(strings[j])) {
return n;
}
n++;
}
}
for (int i = 0; i < playMode.length; i++) {
if (currentMode.equals(playMode[i])) {
return n;
}
n++;
}
return n;
}
/**
*
* @return 获取当前选择playType的索引 例如 福彩3d {直选,组三,组六}对应的索引分别为{0,1,2}
*/
public int getPlayTypeIndex() {
for (int i = 0; i < playType.length; i++) {
if (currentType.equals(playType[i])) {
return i;
}
}
return 0;
}
/**
*
* @param resId
* R.array.xx_playmodes
* @param index
* 当前选择playType的索引 例如 福彩3d {直选,组三,组六}对应的索引分别为{0,1,2}
* @return 对应plaype下的playmodes 例如 福彩3d直选 {复式 单式}
*/
public String[] CountModeByType(int resId, int index) {
TypedArray typedArray = SoarEngine.getInstance().getResources()
.obtainTypedArray(resId);
resId = typedArray.getResourceId(index, -1);
return getStringArray(resId);
}
/**
* 彩种playype发生变化 例如 福彩3d{直选 组三}
*/
public abstract void notifyPlayTypeChanged();
/**
* 当有的彩种的玩法类型改变时,其redMin或buleMin的值会相应的被改变, 这种情况下,在具体的彩种类中要重写该方法,使玩法类型与redMin
* 和buleMin相对应。例如,11选5的玩法,任选二 任选三等的最小 红球数不同,切换玩法类型时就要对redMin做相应的改变,否则在自选
* 和机选间切换时会出问题,因为机选显示号码个数时会用到以上量值。 {@link #setCurrentMode(String)
* setCurrentMode()}类似。
*
* @param currentType
*/
public void setCurrentType(String currentType) {
this.currentType = currentType;
notifyPlayTypeChanged();
}
public String getCurrentType() {
return currentType;
}
/**
* 彩种playMode发生变化 例如 福彩3d{单式 复式}
*/
public abstract void notifyPlayModeChanged();
/**
* 使用说明参考{@link #setCurrentType(String) setCurrentType}
*
* @return
*/
public void setCurrentMode(String currentMode) {
this.currentMode = currentMode;
notifyPlayModeChanged();
}
public String getCurrentMode() {
return currentMode;
}
/**
*
* @param resId
* R.arrat.xx_playmodes
* @return 当前PlayType对应的PlayMode 例如 福彩3d直选{复式,单式}
*/
public String[] getPlayModes(int resId) {
TypedArray typedArray = SoarEngine.getInstance().getResources()
.obtainTypedArray(resId);
resId = typedArray.getResourceId(getPlayTypeIndex(), -1);
return getStringArray(resId);
}
protected String getString(int resId) {
return SoarEngine.getInstance().getResources().getString(resId);
}
protected String[] getStringArray(int resId) {
return SoarEngine.getInstance().getResources().getStringArray(resId);
}
protected int getInteger(int resId) {
return SoarEngine.getInstance().getResources().getInteger(resId);
}
protected boolean getBoolean(int resId) {
return SoarEngine.getInstance().getResources().getBoolean(resId);
}
/**
* 判断当前想要选择的红球是否能被选选择
*
* @param selected
* 当前已经选中的红球
* @param index
* 想要选择的红球
* @return
*/
public abstract String canSelecteRed(int[] selected, int index);
/**
* 判断当前想要选择的蓝球是否能被选选择
*
* @param selected
* 当前已经选中的蓝球
* @param index
* 想要选择的蓝球
* @return
*/
public abstract String canSelecteBlue(int[] selected, int index);
/**
* 根据当前已选红球和想要选择的红球计算出新的选中状态
*
* @param selected
* 当前已经选中的红球
* @param index
* @return
*/
public abstract int[][] newRedBalls(int[] selected, int index,
boolean isCancel);
/**
* 根据当前已选红球和想要选择的蓝球计算出新的选中状态
*
* @param selected
* 当前已经选中的红球
* @param index
* @return
*/
public abstract int[][] newblueBalls(int[] selected, int index,
boolean isCancel);
/**
* 将当前已经选择的红球格式化为字符串 例如 已经选择3 6 7格式化为3,6,7
*
* @param text
* @param index
* @return
*/
public abstract String formatSelectedRed(String[] texts, int[] indexs);
/**
* 将当前已经选择的蓝球格式化为字符串 例如 已经选择3 6 7格式化为3,6,7
*
* @param text
* @param index
* @return
*/
public abstract String formatSelectedBlue(String[] texts, int[] indexs);
//根据当前选号情况创建代表当前选好的彩票订单项目
/**
* @param redpool 红球
* @param bluepool 蓝球
* @param result 方案信息(X注X元)
* @param zhuijia 是否追加
*/
public abstract LotteryCartItem createLotteryCartItem(String redpool,String bluepool,String result,boolean zhuijia);
public abstract int getTypeCodeByMode(String mode);
}
package cn.com.soarmobile.lottery;
import cn.com.soarmobile.R;
import cn.com.soarmobile.bean.LotteryCartItem;
import cn.com.soarmobile.util.CalculatorUtils;
import cn.com.soarmobile.util.StringUtil;
public class Lottery11x5 extends LotteryRed {
public Lottery11x5() {
icon = R.string.llx5_icon;
name = getString(R.string.llx5_name);
gameName = getString(R.string.llx5_game_name);
code = getString(R.string.llx5_code);
issue = getString(R.string.llx5_issue);
summary = getString(R.string.llx5_summary);
price = getInteger(R.integer.llx5_price);
deadLine = getString(R.string.llx5_deadline);
redTag = getString(R.string.llx5_redtag);
buleTag = getString(R.string.llx5_bluetag);
redMin = getInteger(R.integer.llx5_redmin);
blueMin = getInteger(R.integer.llx5_bluemin);
rules = getStringArray(R.array.llx5_rules);
notices = getStringArray(R.array.llx5_notices);
playType = getStringArray(R.array.llx5_playtypes);
currentType = getString(R.string.llx5_defaulttype);
playMode = getStringArray(R.array.llx5_playmodes);
currentMode = getString(R.string.llx5_defaultmode);
allowAddTo = getBoolean(R.integer.llx5_allowAdd);
format = getBoolean(R.integer.llx5_format);
officialrule = R.string.llx5_officialrule;
prizeexplain = R.string.llx5_prizeexplain;
autoPlayType = getStringArray(R.array.llx5_auto_playtypes);
notifyPlayTypeChanged();
}
@Override
public int[] getRedPool() {
return super.getRedPool(R.array.llx5_redpools);
}
@Override
public int getRedColumnCount() {
return super.getRedColumnCount(R.array.llx5_redpools);
}
@Override
public int[] getRandomRed() {
int n = getIndex(R.array.llx5_playmodes);
int column = getRedColumnCount();
switch (n) {
case 0:// 任一-直选
return CalculatorUtils.getRandomArrayNumber(1, 0, 10);
case 1:// 任二-直选
return CalculatorUtils.getRandomArrayNumber(2, 0, 10);
case 2:// 任三-直选
return CalculatorUtils.getRandomArrayNumber(3, 0, 10);
case 3:// 任四-直选
return CalculatorUtils.getRandomArrayNumber(4, 0, 10);
case 4:// 任五-直选
return CalculatorUtils.getRandomArrayNumber(5, 0, 10);
case 5:// 任六-直选
return CalculatorUtils.getRandomArrayNumber(6, 0, 10);
case 6:// 任七-直选
return CalculatorUtils.getRandomArrayNumber(7, 0, 10);
case 7:// 任八-直选
return CalculatorUtils.getRandomArrayNumber(8, 0, 10);
case 8:// 前二-直选
int[] reds = CalculatorUtils.getRandomArrayNumber(2, 0, 10);
for (int i = 0; i < reds.length; i++) {
reds[i] = reds[i] + column * i;
}
return reds;
case 9:// 前二-组选
return CalculatorUtils.getRandomArrayNumber(2, 0, 10);
case 10:// 前三-直选
reds = CalculatorUtils.getRandomArrayNumber(3, 0, 10);
for (int i = 0; i < reds.length; i++) {
reds[i] = reds[i] + column * i;
}
return reds;
case 11:// 前三-组选
return CalculatorUtils.getRandomArrayNumber(3, 0, 10);
}
return null;
}
@Override
public int[][] getRandom(int n) {
if (n < 1) {
n = 1;
}
int[][] result = new int[n][redMin];
for (int i = 0; i < n; i++) {
for (int j = 0; j < redMin; j++) {
result[i][j] = CalculatorUtils.getRandomNumber(1, 11);
}
}
return result;
}
@Override
public String[] getRandomString(int n) {
if (n < 1) {
n = 1;
}
String[] result = new String[n];
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < n; i++) {
sBuffer.delete(0, sBuffer.length());
int[] nums = CalculatorUtils.getRandomArrayNumber(redMin, 1, 11);
for (int j = 0; j < redMin; j++) {
sBuffer.append(StringUtil.format(nums[j]) + ",");
}
result[i] = sBuffer.toString().substring(0, sBuffer.length() - 1);
}
return result;
}
@Override
public boolean isValid(int[] red, int[] bule) {
if (red.length == 0)
return false;
switch (currentIndex) {
case 0:// 任一-直选
break;
case 1:// 任二-直选
break;
case 2:// 任三-直选
break;
case 3:// 任四-直选
break;
case 4:// 任五-直选
break;
case 5:// 任六-直选
break;
case 6:// 任七-直选
break;
case 7:// 任八-直选
break;
case 8:// 前二-直选
if (red[red.length - 1] / getRedColumnCount() != 1)
return false;
case 9:// 前二-组选
break;
case 10:// 前三-直选
if (red[red.length - 1] / getRedColumnCount() != 2)
return false;
case 11:// 前三-组选
break;
}
if (red.length < redMin)
return false;
return true;
}
@Override
public long calculatorBoxes(int[] red, int[] blue) {
if (!isValid(red, blue)) {
return -1;
}
int column = getRedColumnCount();
switch (currentIndex) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:// 任一-直选 到 任八-直选
return CalculatorUtils.calculatorCombination(red.length, redMin);
case 8:// 前二-直选
return CalculatorUtils.calculatorBoxs(red, column);
case 9:// 前二-组选
return CalculatorUtils.calculatorCombination(red.length, redMin);
case 10:// 前三-直选
return CalculatorUtils.calculatorBoxs(red, column);
case 11:// 前三-组选
return CalculatorUtils.calculatorCombination(red.length, redMin);
}
return 0;
}
@Override
public void reset(boolean isAutoToManual) {
currentType = getString(R.string.llx5_defaulttype);
if (isAutoToManual) {
notifyPlayTypeChanged();
}
}
@Override
public void notifyPlayTypeChanged() {
playMode = getPlayModes(R.array.llx5_playmodes);
currentMode = playMode[0];
notifyPlayModeChanged();
}
@Override
public void notifyPlayModeChanged() {
currentIndex = getIndex(R.array.llx5_playmodes);
if (!StringUtil.isEmpty(rules))
currentRule = rules[getIndex(R.array.llx5_playmodes)];
if (!StringUtil.isEmpty(notices))
currentNotice = notices[getIndex(R.array.llx5_playmodes)];
switch (currentIndex) {
case 0:// 任一-直选
redMin = 1;
break;
case 1:// 任二-直选
redMin = 2;
break;
case 2:// 任三-直选
redMin = 3;
break;
case 3:// 任四-直选
redMin = 4;
break;
case 4:// 任五-直选
redMin = 5;
break;
case 5:// 任六-直选
redMin = 6;
break;
case 6:// 任七-直选
redMin = 7;
break;
case 7:// 任八-直选
redMin = 8;
break;
case 8:// 前二-直选
redMin = 2;
break;
case 9:// 前二-组选
redMin = 2;
break;
case 10:// 前三-直选
redMin = 3;
break;
case 11:// 前三-组选
redMin = 3;
break;
}
}
@Override
public String canSelecteRed(int[] selected, int index) {
int column = getRedColumnCount();
switch (currentIndex) {
case 0:// 任一-直选
break;
case 1:// 任二-直选
break;
case 2:// 任三-直选
break;
case 3:// 任四-直选
break;
case 4:// 任五-直选
break;
case 5:// 任六-直选
break;
case 6:// 任七-直选
break;
case 7:// 任八-直选
if(selected.length>=8){
return "最多只能选8个号码!";
}
break;
case 8:// 前二-直选
if (index / column == 0) {
for (int i = 0; i < selected.length; i++) {
if (selected[i] == index + column) {
return "前二选号:各位不能重复";
}
}
} else if (index / column == 1) {
for (int i = 0; i < selected.length; i++) {
if (selected[i] == index - column) {
return "前二选号:各位不能重复";
}
}
}
break;
case 9:// 前二-组选
break;
case 10:// 前三-直选
if (index / column == 0) {
for (int i = 0; i < selected.length; i++) {
if (selected[i] == index + column
|| selected[i] == index + 2 * column) {
return "前三选号:各位不能重复";
}
}
} else if (index / column == 1) {
for (int i = 0; i < selected.length; i++) {
if (selected[i] == index - column
|| selected[i] == index + column) {
return "前三选号:各位不能重复";
}
}
} else if (index / column == 2) {
for (int i = 0; i < selected.length; i++) {
if (selected[i] == index - column
|| selected[i] == index - 2 * column) {
return "前三选号:各位不能重复";
}
}
}
break;
case 11:// 前三-组选
break;
}
return "yes";
}
public int[][] zhixuanrenyi(int[] selected, int index) {
int[][] state = new int[2][];
int[] remove = selected;
int[] add = new int[] { index };
state[0] = add;
state[1] = remove;
return state;
}
public int[][] zhixuan(int[] selected, int index) {
int[][] state = new int[2][];