软件工程 Android小游戏 猜拳大战

一、前言

最近学校举办的大学生程序设计竞赛,自己利用课余时间写了一个小游戏,最近一直在忙这个写这个小游戏,参加比赛,最终是老师说自己写的简单,可以做的更复杂的点的。加油

二、内容简介

自己玩过Android系统下的节奏大师,自己也就考虑做一个类似的,然后自己写技术水平有限,还是在学习Android阶段,自己就想到可以写一个猜拳的比较小游戏。

这是一款基于Android平台小游戏—猜拳大战,简单,易操作,趣味强,训练反应速度,内存小,没有广告,安全。

最大的特点:训练人的反应速度。

游戏规则:在30秒内,通过随机屏幕左右两边随机出现的石头剪刀布,判断哪一边获胜或平局。根据随机出现后迅速点击你判断的结果,然后继续判断下一题。点击判断结果速度越快每一题得到的分数也会越高。最终根据你的分数多少判断最后的等级(A,B,C,D,E,F)。

设计游戏里的逻辑规则:在0.6秒之内点击,加3分,在0.6-1秒之间点击,加2分,在1秒之后点击的,加1分。机器每一次自动产生石头剪刀布时间是1秒,人的反应时间是1秒,所以最多我们需要判断15次,最高分是45分。

结果分析:当自己的分数达到35分以上,得到是A,分数在30-35分,得到是B,分数在20-30分,得到是C,分数在15-20分,得到是D,分数在10-15分,得到是E,分数小于10分,得到是F。

三、效果图

四、设计分析

人在紧张和神经衰弱状态对外界对外界变化有时做出错误的判断,所以考虑开发一款训练人的快速反应的APP,积眼,手,脑同时对外界变化做出正确判断。

整个游戏由布局部分和实现部分组成。(一)布局Layout部分由主要有三部分组成,一个是进入界面,一个是游戏界面,一个是关于界面。(二)实现部分主要由View工具类和Activity两部分组成。

布局部分采用的是先设计自己的logo和游戏背景图,给人一种清新的感觉,一个start的界面,进入App的第一个界面,采用的是线性布局,工整漂亮。一个游戏的界面,进入后游戏界面,在倒计时3,2,1之后就开始了游戏,采用的嵌套线性布局和相对布局,在布局文件中定义ImageButton组件。一个about的关于的界面,介绍自己的版本以及其他信息介绍。

实现部分的(1)View部分,是采用的是使用Android 图形2D的Canvas类;通过setImageDrawable方法来设置按钮要显示的图标,同时对按钮设置事件监听 setOnClickListener,以此来捕捉事件并处理;在数字集合中使用随机函数,每一个数字对应的是个picture,所以就可以随机产生石头剪刀布。(2) Activity部分有三个界面触发,Appstart采用的是Handler类来实现线程UI界面更新,使用自己写的类Handle_Delay来控制更新时间,设定多长时间换下一张picture,同时使用的是一种是实现Runnable接口实现多线程操作。

代码部分:

(1)Appstart部分:实现动态实现的时候使用的是Handle_Delay类。

package com.jk.diy;

import com.jk.fingerGame.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ImageView;

public class Appstart extends Activity  {

    private ImageView caiquan;

    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.appstart);

        caiquan = (ImageView) findViewById(R.id.caiquan);

        caiquan.setBackgroundResource(R.drawable.cq_back_1);
/*延迟器,当apk启动后,
1、首先加载的是cq_back_1
2、在延迟一秒后市出现下一张照片,在android机上的时间1000=现实中的1秒
3、Handle_Delay这个类是自己定义的*/
        Handle_Delay(0, 1000);
        Handle_Delay(1, 1300);
        Handle_Delay(2, 1600);
        Handle_Delay(3, 2000);
        Handle_Delay(4, 2400);
        Handle_Delay(5, 2700);
        Handle_Delay(6, 3000);
        Handle_Delay(7, 3100);
        Handle_Delay(8, 3200);
        Handle_Delay(9, 2300);
        Handle_Delay(10, 3400);
        Handle_Delay(11, 3500);

    }

    private void Handle_Delay(int chage, int time) {

        final int _Chage = chage;
        Handler _Animal_Handler = new Handler();
        _Animal_Handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                if (_Chage == 0) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_2);
                } else if (_Chage == 1) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_3);
                } else if (_Chage == 2) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_4);
                }else if (_Chage == 3) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_5);
                }
                else if (_Chage == 4) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_6);
                }
                else if (_Chage == 5) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_1);
                }
                else if (_Chage == 6) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_2);
                }
                else if (_Chage == 7) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_3);
                }
                else if (_Chage == 8) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_4);
                }
                else if (_Chage == 9) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_5);
                }
                else if (_Chage == 10) {
                    caiquan.setBackgroundResource(R.drawable.cq_back_6);
                }
                else {
                    Intent intent = new Intent(Appstart.this, ButtonLongActivity.class);
                    startActivity(intent);
                    finish();
                }
            }
        }, time);//这个时间是在appstart启动后在这个界面停留的时间。
    }
}
    

(2)获取分数部分

public void getMark() {

        if (endTime - beginTime <= 600) {
            mark = mark + 3;
            markImg.setVisibility(View.VISIBLE);
            markImg.setBackgroundResource(R.drawable.j3);
            markImg.startAnimation(myAnimation_Alpha);
            new Thread(r).start();
        } else if (endTime - beginTime > 600 && endTime - beginTime <= 1000) {
            mark = mark + 2;
            markImg.setVisibility(View.VISIBLE);
            markImg.setBackgroundResource(R.drawable.j2);
            markImg.startAnimation(myAnimation_Alpha);
            new Thread(r).start();
        } else if (endTime - beginTime >= 1000) {
            mark = mark + 1;
            markImg.setVisibility(View.VISIBLE);
            markImg.setBackgroundResource(R.drawable.j1);
            markImg.startAnimation(myAnimation_Alpha);
            new Thread(r).start();
        }
        fs.setText("分数:" + mark);
    }

(3)随机猜拳实现(特点:两个石头剪刀布不是同时实现,一个先后)

/*    1、获得两个随机数
 * 2、在得到两个随机数的时候是一个先得到,一个后得到*/
    public void changeImg() {
        getRandomNumber();
        if (number1 == 1) {
            p1.setBackgroundResource(R.drawable.jd);
        } else if (number1 == 2) {
            p1.setBackgroundResource(R.drawable.st);
        } else if (number1 == 3) {
            p1.setBackgroundResource(R.drawable.bu);
        }
        if (number2 == 1) {
            p2.setBackgroundResource(R.drawable.zjd);
        } else if (number2 == 2) {
            p2.setBackgroundResource(R.drawable.zst);
        } else if (number2 == 3) {
            p2.setBackgroundResource(R.drawable.zbu);
        }
    }

(4)计数部分

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //给画笔设置
           mPaint.setColor(Color.BLUE);
           canvas.drawRect(0,1 , getWidth(),getHeight() , mPaint);
           mPaint.setColor(Color.YELLOW);
           mPaint.setTextSize(30);
           String text = String.valueOf(mCount);
           mPaint.getTextBounds(text, 0, text.length(), mBounds);
           float  textwidth=mBounds.width();
           float  texthight=mBounds.height();
           canvas.drawText(text, getWidth() / 2 - textwidth / 2, getHeight() / 2 + texthight / 2, mPaint);
    }   public void onClick(View arg0) {	 mCount++;	 invalidate();	}

(5)重复点击ImageButton实现

package com.jk.view;

import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;

public class RepeatingImageButton extends ImageButton {
    private long mStartTime; // 记录长按开始
    private int mRepeatCount; // 重复次数计数
    private RepeatListener mListener;
    private long mInterval = 500; // Timer触发间隔,即每0.5秒算一次按下

    public RepeatingImageButton(Context context) {
        this(context, null);
    }

    public RepeatingImageButton(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.imageButtonStyle);
    }

    public RepeatingImageButton(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        setFocusable(true); // 允许获得焦点
        setLongClickable(true); // 启用长按事件
    }

    public void setRepeatListener(RepeatListener l, long interval) {
        // 实现重复按下事件listener
        mListener = l;
        mInterval = interval;
    }

    @Override
    public boolean performLongClick() {
        mStartTime = SystemClock.elapsedRealtime();
        mRepeatCount = 0;
        post(mRepeater);
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            // 本方法原理同onKeyUp的一样,这里处理屏幕事件,下面的onKeyUp处理Android手机上的物理按键事件
            removeCallbacks(mRepeater);
            if (mStartTime != 0) {
                doRepeat(true);
                mStartTime = 0;
            }
        }
        return super.onTouchEvent(event);
    }

    // 处理导航键事件的中键或轨迹球按下事件
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
        case KeyEvent.KEYCODE_ENTER:

            super.onKeyDown(keyCode, event);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    // 当按键弹起通知长按结束
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
        case KeyEvent.KEYCODE_ENTER:

            removeCallbacks(mRepeater); // 取消重复listener捕获
            if (mStartTime != 0) {
                doRepeat(true); // 如果长按事件累计时间不为0则说明长按了
                mStartTime = 0; // 重置长按计时器
            }
        }
        return super.onKeyUp(keyCode, event);
    }

    private Runnable mRepeater = new Runnable() { // 在线程中判断重复
        public void run() {
            doRepeat(false);
            if (isPressed()) {
                postDelayed(this, mInterval); // 计算长按后延迟下一次累加
            }
        }
    };

    private void doRepeat(boolean last) {
        long now = SystemClock.elapsedRealtime();
        if (mListener != null) {
            mListener.onRepeat(this, now - mStartTime, last ? -1
                    : mRepeatCount++);
        }
    }

    // 下面是重复Button
    // Listener接口的定义,调用时在Button中先使用setRepeatListener()方法实现RepeatListener接口

    public interface RepeatListener {
        void onRepeat(View v, long duration, int repeatcount); // 参数一为用户传入的Button对象,参数二为延迟的毫秒数,第三位重复次数回调。
    }
}

(6)用Handler类来实现“跨越线程(Activity)更新UI。

Handler handle = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            switch (msg.what) {
            case 4:
                img.setBackgroundResource(R.drawable.s3);
                break;
            case 3:
                img.setBackgroundResource(R.drawable.s2);
                break;
            case 2:
                img.setBackgroundResource(R.drawable.s1);
                break;
            case 1:
                img.setBackgroundResource(R.drawable.play);
                break;
            case 0:
                kaishi();
                break;
            case 11:
                if (sumTime != 0) {
                    sj.setText(((sumTime) / 1000 + "." + (sumTime) % 1000 / 10)  + "秒");
                } else {
                    sj.setText("时间到");
                    l1.setVisibility(View.GONE);
                    l2.setVisibility(View.VISIBLE);
                    if (35 <= mark) {
                        img.setBackgroundResource(R.drawable.a);
                    } else if (30 <= mark && mark < 35) {
                        img.setBackgroundResource(R.drawable.b);
                    } else if (20 <= mark && mark < 30) {
                        img.setBackgroundResource(R.drawable.c);
                    } else if (15 <= mark && mark < 20) {
                        img.setBackgroundResource(R.drawable.d);
                    } else if (10 <= mark && mark < 15) {
                        img.setBackgroundResource(R.drawable.e);
                    } else if (mark < 10) {
                        img.setBackgroundResource(R.drawable.f);
                    }
                    dj2.setVisibility(View.VISIBLE);
                    dj1.setVisibility(View.GONE);
                }
                break;
            case 12:
                changeImg();
                break;
            case 13:

                markImg.setVisibility(View.GONE);
                break;
            default:
                break;
            }
        }
    };

Normal
0

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-font-kerning:1.0pt;}

五、设计重点和难点

1、在实现多线程的UI界面更新时,开始选用的是继承Thread类,同时覆写了本类中的run()方法,后来发现可以使用Handler类运行更流畅。

2、在实现画图时,使用的Android 图形2D的Canvas类,在设置设置每个图形的显示区域时,以为跟使用Java的Rectangle是一样的,后来发现跟MFC中的RECT结构一样。

APK的下载地址:http://pan.baidu.com/s/1hs4h544

提取码:yd4k

Normal
0

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-font-kerning:1.0pt;}

时间: 2024-10-25 00:03:15

软件工程 Android小游戏 猜拳大战的相关文章

android小游戏模版—重力感应

好久没更新博客了,今天来谈谈android小游戏---重力感应,一般在游戏里运用的比较多,比如这类游戏有:神庙逃亡,极品飞车,平衡球,三围重力迷宫,重力赛车等. 首先什么是重力感应,重力感应是指现在手机中常用的一个器件,及加速度传感器.当手机静止时,加速度就是重力,所以一般也叫做重力传感器.这个硬件可以感应加速度的变化,转化为数据提供给系统.还有一种传感器是陀螺仪,检测围绕某轴的旋转动作,是利用有质量的刚体的在做旋转或震动时,如果发生垂直于旋转或震动轴的旋转,因为惯性会产生垂直于旋转或震动轴的柯

android 小游戏 ---- 数独(一)

segment 1 android 小游戏 ----  数独(一) 规则:在9X9的棋盘中,每个横行和竖列中的9个格子都包含数字1至9,不重复, 且每个黑色粗实线围住的9个格子都包含数字1至9,不重复. 既然涉及到棋盘,那就少不了绘图,我们知道在android中绘图的工作是由UI线程完成的, 一般是指主线程,而android系统设定UI绘图线程超过5秒不响应就会报异常,所以一般在 子线程中进行数据的计算,然后将消息发给UI线程,使之更新界面. 在Java中我们可以通过View来绘图,在默认情况下

android 小游戏 ---- 数独(四)

segment 4 android 小游戏 ----  数独(四) 好的,棋盘绘制出来了.那么我们如何在空白方格中填写数字呢? 这时按钮就发挥出来它的作用了. 我们在控制器类game中设置一个标志,标示当前用户想要填写的数字, 可以通过监听器监听当前用户点击是哪个按钮,然后用game的set方法设置一下. 首先在MainActivity.java 中设置一下监听器. public class MainActivity extends Activity { private Game game; p

android 小游戏 ---- 数独(三)

segment 3 android 小游戏 ----  数独(三) 好的,既然要把数独棋盘中初始提示数字绘制出来,我们就要先了解数独的一些特点. 数独棋盘中总共是81个数字,那我们是否可以用一个数组来代表整个棋盘对应的数字呢想象我们初始化一个9x9的数组,private int[] sudoku = new int[9*9] //初始化数据 private int[] sudoku = new int[9*9]; 这里使用一维数组,当然使用二维数组更加明了直接,这个随个人喜好. 那么我们可以让

原生JS实现的h5小游戏-植物大战僵尸

代码地址如下:http://www.demodashi.com/demo/12755.html 项目介绍 本项目是利用原生js实现的h5小游戏-植物大战僵尸,主要结合了一下自己对于h5小游戏的理解,结合面向对象的编程思想进行开发,在实现时使用了部分es6语法,对于es6语法不太熟悉的小伙伴可以先查阅相关资料了解一下. 如有需要,可根据自己的需求修改源码样式.源码配置属性代码,实现个性化定制. 以下为文件目录结构示意图,核心代码在js文件夹下的四个common.js.main.js.game.js

Android开发系列(十六):【Android小游戏成语连连看】第二篇

写的晚了,在分工个Z市高中的一个成绩查询的系统,原系统竟然是用VB写的,我不得不佩服原本写系统的那位哥们真能耐得住. 明天搭建下SVN就等着先发工程款然后开始项目了,想想有工资进账,心里也为我那干瘪的钱包小兴奋了一把. 闲话不多说了,今天我们来分析下这个小游戏的工作原理以及核心代码的解析: 工作原理: "主界面"以及"关卡界面"不多说了,这两个是直接写了xml文件, 然后,我们在"游戏界面"的搭建是: 用java代码动态生成了这个界面,在界面中通

介绍一款Android小游戏--交互式人机对战五子棋

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6589025 学习Android系统开发之余,编写了一个小游戏--交互式人机对战五子棋,自娱自乐.之所以称之为交互式人机对战五子棋,一是因为在进入人机对战模式这前,你可以任意设置好开局,同时,在对战过程中,你可以看到机器的思考过程,还可以标识出每一个落子点的优劣势:二是因为可以为机器增加游戏经验,使得机器越来越聪明.希望喜欢五子棋的同学能够喜欢,

JS小游戏----猜拳小游戏

这周学习了JS 的基础数据 函数 和 对象 每一个都是很多的属性和方法 下面是对象做的Xmind 有很多方法 创建对象的方法 遍历对象 添加删除对象中的属性 访问对象的方法 点 中括号 访问法 猜拳游戏 实际原理其实很简单  规则大家全世界都通用 所以 这个游戏 短短几行 switch就可以 把简易的原理实现出来 但是要做的 像一个小游戏一样 能应对各种情况 和 前进 和 后退的操作 加了一些switch 语句 让分支语句更多  是考虑到的情况更加全面  然后用 函数包装 功能模块 列如 判断模

Android开发系列(十五):【Android小游戏成语连连看】第一篇

学了一个多月安卓,因为暑假的时候要给朋友说写个小游戏,而且也想检测下自己的能力,所以说从7号开始就着手写这个小游戏了,前前后后带上课到今天总算是写完了,但是写的这个小游戏还是有很多问题,但是还好,勉强能跑起来,一些瑕疵就不要在乎太多了,毕竟咱又不准备发布供别人下载. APK安装包下载链接(我给放在百度云盘了,可以直接点击下载):http://pan.baidu.com/s/1bnxpQrH 代码文件下载:(放在CSDN的下载那里了,不需要积分):http://download.csdn.net/