Android实战源码--围住神经猫
最终效果:

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.caobotao.crazycat" > <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
MainActivity.java
package com.example.caobotao.crazycat; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new PlayGround(this));
}
}
Dot.java
package com.example.caobotao.crazycat; /**
* Created by caobotao on 15/11/9.
*/
public class Dot {
private int x;
private int y;
private int status;
static final int STATUS_ON = 1;//障碍的圆圈状态
static final int STATUS_OFF = 0;//可点击的圆圈状态
static final int STATUS_IN = 9;//猫所在的圆圈状态
public Dot(){}
//实例化时每个圆圈都是可点击的状态
public Dot(int x,int y){
this.x = x;
this.y = y;
status = STATUS_OFF;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} public int getStatus() {
return status;
} public void setStatus(int status) {
this.status = status;
} public void setXY(int x,int y){
this.x = x;
this.y = y;
}
}
PlayGround.java
package com.example.caobotao.crazycat; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast; import java.util.HashMap;
import java.util.Vector; /**
* Created by caobotao on 15/11/9.
*/
public class PlayGround extends SurfaceView implements OnTouchListener{
private static int WIDTH = 45;//圆圈宽度
private static final int ROW = 10;//每行显示的圆圈数
private static final int COL = 10;//每列显示的圆圈数
private static final int Blocks = 13;//初始化障碍的个数
private Dot matrix[][];
private Dot cat;
public PlayGround(Context context) {
super(context);
getHolder().addCallback(callback);
//声明ROW x COL的圆圈矩阵并初始化
matrix = new Dot[ROW][COL];
for (int i = 0;i < ROW;i ++){
for (int j = 0;j < ROW;j ++){
matrix[i][j] = new Dot(j,i);
}
}
initGame();
setOnTouchListener(this);
}
private void redraw(){
//初始化画板
Canvas canvas = getHolder().lockCanvas();
// Log.i("info", "222222");
//设置画板背景色
canvas.drawColor(Color.LTGRAY);
Paint p = new Paint();
p.setFlags(Paint.ANTI_ALIAS_FLAG);
//设置不同状态的圆圈的颜色,并绘制
for (int i = 0;i < ROW;i ++){
int offset = 0;
//如果为偶数行,设置半个圆圈宽度的偏移量
if (i % 2 != 0){
offset = WIDTH / 2;
}
for (int j = 0;j < COL; j ++){
Dot one = getDot(j, i);
switch (one.getStatus()){
case Dot.STATUS_OFF:
p.setColor(0xFFEEEEEE);
break;
case Dot.STATUS_ON:
p.setColor(0xFFFFAA00);
break;
case Dot.STATUS_IN:
p.setColor(0xFFFF0000);
break;
}
RectF rectF = new RectF(one.getX() * WIDTH + offset, one.getY() * WIDTH,
(one.getX() + 1) * WIDTH + offset, (one.getY() + 1) * WIDTH);;
// if(i % 2 ==0) {
// rectF = new RectF((one.getX() + 1) * WIDTH, (one.getY() + 2) * WIDTH, (one.getX() + 2) * WIDTH, (one.getY() + 2) * WIDTH);
// }
canvas.drawOval(rectF,p);
}
}
getHolder().unlockCanvasAndPost(canvas);
}
private void initGame(){
//将每个圆圈初始化为可点击状态
for (int i = 0;i < ROW;i ++){
for (int j = 0;j < ROW;j ++){
matrix[i][j].setStatus(Dot.STATUS_OFF);
}
}
//将(4,5)设置初始化为猫所在的圆圈,并将状态设置为猫所在
cat = getDot(4,5);
cat.setStatus(Dot.STATUS_IN);
//随机设置Blocks个障碍
for (int i = 0 ;i < Blocks;){
int x = (int) ((Math.random() * 1000)%COL);
int y = (int) ((Math.random() * 1000)%ROW);
if(getDot(x,y).getStatus() == Dot.STATUS_OFF){
getDot(x,y).setStatus(Dot.STATUS_ON);
i ++;
}
} }
private boolean isAtEdge(Dot dot){
//判断某个圆圈是否在边缘
if(dot.getX() * dot.getY() == 0 || dot.getX()+1 == ROW || dot.getY() + 1 == COL){
return true;
}
return false;
}
//获取某个圆圈的左起1,2,3,4,5,6方向的相邻的圆圈
private Dot neighbour(Dot dot,int dir){
int x = -1;
int y = -1;
switch (dir){
case 1:
//return getDot(dot.getX()-1,dot.getY());
x = dot.getX()-1;
y = dot.getY();
break;
case 2:
if(dot.getY() % 2 == 0){
x = dot.getX() - 1;
y = dot.getY() - 1;
}
else {
x = dot.getX();
y = dot.getY() - 1;
}
break;
case 3:
if(dot.getY() % 2 == 0){
x = dot.getX() ;
y = dot.getY() - 1;
}
else {
x = dot.getX() + 1;
y = dot.getY() - 1;
}
break;
case 4:
x = dot.getX() + 1;
y = dot.getY();
break;
case 5:
if(dot.getY() % 2 == 0){
x = dot.getX() ;
y = dot.getY() + 1;
}
else {
x = dot.getX() + 1;
y = dot.getY() + 1;
}
break;
case 6:
if(dot.getY() % 2 == 0){
x = dot.getX() - 1;
y = dot.getY() + 1;
}
else {
x = dot.getX();
y = dot.getY() + 1;
}
break;
}
if (x != -1 || y != -1){
return getDot(x,y);
}
return null;
}
//获取某个圆圈在某个方向到矩阵边缘或到障碍的距离,如果是到边缘,返回正值,如果是到障碍,返回负值
private int getDistance(Dot dot,int dir){
int distance = 0;
if (isAtEdge(dot)){
return 1;
}
Dot ori = dot;
Dot next;
while (true){
next = neighbour(ori,dir);
if (next.getStatus() == Dot.STATUS_ON){
return distance * -1;
}
if (isAtEdge(next)){
distance ++;
return distance;
}
distance ++;
ori = next;
}
}
//将猫移动到某个圆圈
private void moveTo(Dot dot){
Dot temp = new Dot();
temp = dot;
dot = cat;
cat = temp;
cat.setStatus(Dot.STATUS_IN);
dot.setStatus(Dot.STATUS_OFF);
//如果移动后猫已在矩阵边缘,则游戏失败
if (isAtEdge(cat)){
lose();
}
// getDot(cat.getX(),cat.getY()).setStatus(Dot.STATUS_OFF);
// dot.setStatus(Dot.STATUS_IN);
// cat.setXY(dot.getX(), dot.getY());
}
private Dot getDot(int x,int y){
return matrix[y][x];
}
Callback callback = new Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
redraw();
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//根据屏幕自适应每个圆圈的宽度
WIDTH = width / (COL + 1);
redraw();
} @Override
public void surfaceDestroyed(SurfaceHolder holder) { }
}; @Override
public boolean onTouch(View v, MotionEvent event) {
// Log.i("info","33333"); if (event.getAction() == MotionEvent.ACTION_UP){
// Log.i("info", "44444");
// Toast.makeText(getContext(),event.getX() + ":" + event.getY(),Toast.LENGTH_SHORT).show();
int x,y;
//获取点击点所在的列数
y = (int) (event.getY() / WIDTH);
//获取点击点所在的行数
if (y % 2 == 0){
x = (int) (event.getX() / WIDTH);
}
else {
x = (int) ((event.getX() - WIDTH/2) / WIDTH);
}
//如果点击点不在矩阵范围内,重新初始化游戏
if (x + 1 > COL || y + 1 > ROW){
initGame();
}
//否则如果点击的圆圈的状态是可点击的,就将此圆圈的状态设置为障碍,并将猫进行移动
else if (getDot(x,y).getStatus() == Dot.STATUS_OFF){
getDot(x,y).setStatus(Dot.STATUS_ON);
move();
}
redraw();
//
}
return true;
} private void move() {
//如果猫已在矩阵边缘,则游戏失败
if (isAtEdge(cat)){
lose();
return;
}
//猫可以移动的圆圈
Vector<Dot> available = new Vector<Dot>();
//猫可以移动的到矩阵边缘没有障碍的圆圈
Vector<Dot> positive = new Vector<Dot>();
HashMap<Dot,Integer> al = new HashMap<Dot,Integer>();
for (int i =1;i<7;i++){
Dot n = neighbour(cat,i);
if(n.getStatus() == Dot.STATUS_OFF){
available.add(n);
al.put(n,i);
if (getDistance(n,i) > 0){
positive.add(n);
}
}
}
//如果猫没有可以移动的圆圈,则游戏成功
if (available.size() == 0){
win();
}
//如果猫只有一个可以移动的圆圈,则移动到此圆圈
else if (available.size() == 1){
moveTo(available.get(0));
}
//否则选最优的圆圈进行移动
else{
Dot best = null;
//如果存在可以直接到达屏幕边缘的走向
if (positive.size() != 0){
System.out.println("向前进");
int min = 999;
for (int i = 0;i < positive.size();i ++){
int a = getDistance(positive.get(i), al.get(positive.get(i)));
if (a < min){
min = a;
best = positive.get(i);
}
}
}
//所有路径均有路障
else{
System.out.println("躲路障");
int max = 0;
for (int i = 0; i < available.size();i ++){
int k = getDistance(available.get(i),al.get(available.get(i)));
if (k < max){
max = k;
best = available.get(i);
}
}
} if(best != null) {
moveTo(best);
}
else{
moveTo(available.get(0));
} // Dot d = available.get(0);
// for (int i = 1;i<available.size();i++){
// if ( Math.min(available.get(i).getX(), available.get(i).getY()) < Math.min(d.getX(),d.getY()) ){
// d = available.get(i);
// }
// }
// moveTo(d);
}
}
//赢得游戏
private void win() {
Toast.makeText(getContext(),"YOU HAVE WON THE GAME!",Toast.LENGTH_SHORT).show();
}
//游戏失败
private void lose() {
Toast.makeText(getContext(),"YOU HAVE LOST THE GAME!",Toast.LENGTH_SHORT).show();
}
} 注:由于本项目只是用于简单学习交流,代码中难免会有bug出现,请自行调试修改。
Android实战源码--围住神经猫的更多相关文章
- Android项目源码分享
http://blog.csdn.net/gao_chun/article/details/47263063 Android项目源码分享 给大家分享几个Android开发项目源码,大部分功能相信可以在 ...
- 45个android实例源码
分享45个android实例源码,很好很强大http://www.apkbus.com/android-20978-1-1.html andriod闹钟源代码http://www.apkbus.com ...
- 分享45个android实例源码,很好很强大
分享45个android实例源码,很好很强大 http://www.apkbus.com/android-20978-1-1.html 分享45个android实例源码,很好很强大http://www ...
- 将Android系统源码导入ecplise
Android系统源码中带有个IDE的配置文件,目录为:development/ide/ 如果要用eclipse导入查看系统源码,则将development/ide/eclipse/.classpat ...
- Android 如何在Eclipse中查看Android API源码 及 support包源码
当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都是已经写好的方法和控件,可是我们只是在搬来使用,不知道它的原理,它是如何被实现的.android系统是开源的,所以谷歌官方 ...
- Android之源码之模块编译和调试
Android之源码之模块编译调试 (一) 进行源码模块修改进行编译的调试 1.首先是从git或者svn上拉一套完整的工程下来,然后全编一下,一般这个时间比较长,大概会得2,3个小时左右, 2,编译成 ...
- 关于查看Android系统源码【Written By KillerLegend】
可能你会想下载Android系统源码,但是我不知道你会看多少系统的源码,如果你对源码只是偶尔看一次的话,推荐你在线看Android的系统源码,下面提供几种查看android系统源码的方法. 1:打开这 ...
- 【转】Android 如何在Eclipse中查看Android API源码 及 support包源码
原文网址:http://blog.csdn.net/vipzjyno1/article/details/22954775 当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都 ...
- 将android Settings 源码 导入到 eclipse工程
1. 新建 android 项目 拷贝源码/packages/apps/Settings到你的其它目录. 在eclipse中,新建项目,但是要从exitting source选择: 2. 导入相关的 ...
随机推荐
- Softmax && Cross-entropy Error
softmax 函数,被称为 归一化指数函数,是sigmoid函数的推广. 它将向量等比压缩到[0, 1]之间,所有元素和为1. 图解: Example: softmax([1, 2, 3, 4, 1 ...
- Bayes’s formula for Conditional Probability
Conditional Probability Example:In a batch, there are 80% C programmers, and 40% are Java and C prog ...
- 1.The Necessity of a Broad Education 全面教育的必要性
1.The Necessity of a Broad Education 全面教育的必要性 (1) According to a survey,which was based on the respo ...
- Win7 VS2015环境编译NanoVG
书接上回,Cairo编译好使用后,发现简单的每帧画100条随机线段就卡得不行,装了个gooreplacer( http://liujiacai.net/gooreplacer/ )上stackover ...
- windows socket扩展函数
1.AcceptEx() AcceptEx()用于异步接收连接,可以取得客户程序发送的第一块数据. BOOL AcceptEx( _In_ SOCKET sListenSocket, ...
- s4-2 ALOHA 协议
多路访问协议 随机访问协议(Random Access) 特点:站点争用信道,可能出现站点之间的冲突 典型的随机访问协议 • ALOHA协议 • CSMA协议 • CSMA/CD协议(以太网采 ...
- hibernate4.3.5,Final hibernate.cfg.xml的配置
今天是接触hibernate的第二天,用来练习的是hibernate最新的版本hibernate-release-4.3.5.Final 要使用hibernate,则先要引入它的jar包,要引入的ja ...
- 好文推荐系列--------(2)GruntJS——重复乏味的工作总会有人做(反正我不做)
GruntJS 是基于JavaScript的命令行构建工具,它可以帮助开发者们自动化重复性的工作.你可以把它看成是JavaScript下的Make或者Ant.它可以完成诸如精简.编译.单元测试.lin ...
- AngularJS的select设置默认值
AngularJS的select设置默认值 在使用Angular时候使用select标签时会遇到绑定数据指定默认显示值可这样实现 <!DOCTYPE html> <html ng-a ...
- REST WebService与SOAP WebService的比较
在SOA的基础技术实现方式中WebService占据了很重要的地位,通常我们提到WebService第一想法就是SOAP消息在各种传输协议上交互.近几年REST的思想伴随着SOA逐渐被大家接受,同时各 ...