zoukankan      html  css  js  c++  java
  • 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出现,请自行调试修改。
    作者:caobotao
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    菜鸟笔记 -- Chapter 6.2.6 内部类
    菜鸟笔记 -- Chapter 6 面向对象
    菜鸟笔记 -- Chapter 6.1 面向对象概述
    菜鸟笔记 -- Chapter 4.7 代码注释与编码规范
    菜鸟笔记 -- Chapter 4 Java语言基础
    小白袍 -- Chapter 1.4.1.1 URL编码的理论解读
    小白袍 -- Chapter 1.1 避不开的编解码
    小白袍 -- Chapter 1 Java中的Encode与Decode
    菜鸟崛起 Ajax
    软件测试
  • 原文地址:https://www.cnblogs.com/caobotao/p/4966663.html
Copyright © 2011-2022 走看看