本次作业的要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2232
本次作业代码的github地址:https://github.com/Hongnnn/ruanjiangongcheng.git
一、前言
本次作业为结对项目,要求两个人一组完成小学四则运算 “软件”之升级版,本次结对同伴的学号:201608030062,姓名:黄宏娜,同伴的博客地址为:http://www.cnblogs.com/hongna/p/9869892.html
二、开发环境:Android Studio
首先,我们是用Android Stuodio做的小学四则运算 app,本次项目代码已经提交到github的da文件,可运行 apk位于pubulic文件夹下。
三、App功能
从个人项目出发,将程序改装成一个单机带用户界面(不是控制台)的程序,这个程序最基本要达到:
- 生成题目,单个题目最多不能超过4个运算符,操作数小于100。
- 用户可以输入答案
- 若用户输入答案正确,则提示正确;若答案错误,则提示错误,并要提示正确答案是多少。
下面附有 8 个相互独立的可以扩展的方向,橙色字体的为选取的扩展方向并加以实现的功能。
- 程序可以出带括号的正整数四则运算,支持分数,除法保留两位小数,如:(1/3+1)*2 = 2.67,特别注意:这里是2.67而非2.66
- 可以出表达式里含有负整数(负整数最小不小于-100)的题目,且负数需要带括号,用户输入的结果不用带括号。如: 2*(-4) = -8
- 用户答题结束以后,程序可以显示用户答题所用的时间
- 用户可以选择出题的个数(最多不能超过5个题目),答题结束可以显示用户答错的题目个数和答对的题目个数
- 用户在第一次答题时,需要用户输入用户名,用户下次启动后,程序需要记住用户前一次输入的用户名
- 程序可以出单个整数阶乘的题目:如:4!=24
- 程序可以设置答题时间,时间设置为整数,单位为秒,最大不能超过120秒,若超过了答题时间未答题,则提示:时间已到,不能答题。
- 程序可以设置皮肤功能,可以改变界面的颜色即可。
四、小学四则运算 “软件”之升级版实现
1.需求分析
2.功能实现
我主要实现的是登录、注册以及整数阶乘的题目,其余功能实现在我同伴的博客随笔中,同伴的地址在前言中已给出。
(1)登录功能
用户可以在此界面输入用户名和密码登录进入小学四则运算中,在此界面,若用户输入的用户名或密码为空,则提示用户输入用户名和密码;若用户输入的用户名和密码正确,则进入到小学四则运算app是首页中;若输入的用户名不存在,则提示用户输入的用户名不存在。其实现代码如下所示:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/screen" android:background="@mipmap/one" android:orientation="vertical" tools:context="com.hhn.asus.da.MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:text="登录界面" android:gravity="center" android:textSize="30sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/item_height_normal" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large" android:layout_marginTop="@dimen/dp_120"> <ImageView android:id="@+id/img_account" android:layout_width="@dimen/dp_19" android:layout_height="@dimen/dp_20" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_tiny" android:scaleType="fitXY" android:src="@mipmap/icon_login_account"/> <EditText android:id="@+id/et_account" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_account" android:background="@null" android:hint="@string/account" android:maxLines="1" android:textColor="@android:color/black" android:textColorHint="@color/tv_gray_deep" android:textSize="@dimen/text_size_normal"/> <View android:layout_width="match_parent" android:layout_height="@dimen/line_height" android:layout_alignParentBottom="true" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_account" android:background="@color/orange_light"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/item_height_normal" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large"> <ImageView android:id="@+id/img_pw" android:layout_width="@dimen/dp_18" android:layout_height="@dimen/dp_20" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_tiny" android:scaleType="fitXY" android:src="@drawable/icon_login_pw"/> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw" android:background="@null" android:hint="@string/password" android:inputType="textPassword" android:maxLines="1" android:textColor="@android:color/black" android:textColorHint="@color/tv_gray_deep" android:textSize="@dimen/text_size_normal"/> <ImageView android:id="@+id/iv_see_password" android:layout_width="@dimen/image_height_litter" android:layout_height="@dimen/image_height_litter" android:src="@drawable/image_password_bg" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:scaleType="fitXY" /> <View android:layout_width="match_parent" android:layout_height="@dimen/line_height" android:layout_alignParentBottom="true" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw" android:background="@color/orange_light"/> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:orientation="horizontal"> <Button android:id="@+id/btn_login" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="60dp" android:layout_marginRight="60dp" android:layout_marginTop="@dimen/dp_15" android:layout_weight="1" android:background="@drawable/btn_orange_selector" android:paddingBottom="@dimen/margin_small" android:paddingTop="@dimen/margin_small" android:text="@string/login" android:textColor="@android:color/background_light" android:textSize="@dimen/text_size_normal" /> <Button android:id="@+id/btn_zhu" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="45dp" android:layout_marginRight="45dp" android:layout_marginTop="15dp" android:layout_weight="1" android:background="@drawable/btn_orange_selector" android:paddingBottom="4dp" android:paddingTop="4dp" android:text="@string/zhu" android:textColor="@android:color/white" android:textSize="@dimen/text_size_normal" /> </LinearLayout> </LinearLayout>
MainActivity.java
package com.hhn.asus.da; import android.app.Activity; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.InputType; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadPoolExecutor; import db.Sqlite; import db.User; class PublicWay { public static List<Activity> activityList = new ArrayList<Activity>(); } public class MainActivity extends AppCompatActivity { private Button reg; private Button login; private EditText count; private EditText pwd; private ImageView seepassword; private List<User> userList; private List<User> dataList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); PublicWay.activityList.add(this); reg= (Button) findViewById(R.id.btn_zhu); login= (Button) findViewById(R.id.btn_login); count= (EditText) findViewById(R.id.et_account); pwd= (EditText) findViewById(R.id.et_password); seepassword=(ImageView)findViewById(R.id.iv_see_password); seepassword.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { setPasswordVisibility(); } }); reg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(MainActivity.this,RegisterActivity.class); startActivityForResult(intent,1); } }); login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String name=count.getText().toString().trim(); String pass=pwd.getText().toString().trim(); //userList=SqliteDB.getInstance(getApplicationContext()).loadUser(); int result=Sqlite.getInstance(getApplicationContext()).Quer(pass,name); if (result==1) { Toast.makeText(MainActivity.this,"登录成功",Toast.LENGTH_LONG).show(); Intent intent=new Intent(); intent.setClass(MainActivity.this,one.class); startActivity(intent); } else if (result==0){ Toast.makeText(MainActivity.this,"用户名不存在",Toast.LENGTH_LONG).show(); } else if(result==-1) { Toast.makeText(MainActivity.this,"密码错误",Toast.LENGTH_LONG).show(); } /* for (User user : userList) { if (user.getUsername().equals(name)) { if (user.getUserpwd().equals(pass)) { state.setText("登录成功!"); }else { state.setText("密码错误!"); } } else { state.setText("用户名不存在!"); } }*/ } });} private void setPasswordVisibility() { if(seepassword.isSelected()){ seepassword.setSelected(false); pwd.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); } else { seepassword.setSelected(true); pwd.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); } } @Override protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if(data!=null){ String username=data.getStringExtra("name"); if(!TextUtils.isEmpty(username)){ count.setText(username); count.setSelection(username.length()); } } } }
页面运行结果如下所示:
(2)注册功能
用户可以在此界面输入用户名和密码进行注册,在此界面,若用户输入的用户名或密码为空,则提示用户输入用户名和密码;若用户输入的用户名和密码格式正确,则注册成功;若输入的用户名已存在,则提示用户输入的用户名已存在。其实现代码如下所示:
register_activity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/screen" android:background="@mipmap/one" android:orientation="vertical" tools:context="com.hhn.asus.da.MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:text="注册界面" android:gravity="center" android:textSize="30sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/item_height_normal" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large" android:layout_marginTop="@dimen/dp_120"> <ImageView android:id="@+id/img_account" android:layout_width="@dimen/dp_19" android:layout_height="@dimen/dp_20" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_tiny" android:scaleType="fitXY" android:src="@mipmap/icon_login_account"/> <EditText android:id="@+id/et_account" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_account" android:background="@null" android:hint="@string/account" android:maxLines="1" android:textColor="@android:color/black" android:textColorHint="@color/tv_gray_deep" android:textSize="@dimen/text_size_normal"/> <View android:layout_width="match_parent" android:layout_height="@dimen/line_height" android:layout_alignParentBottom="true" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_account" android:background="@color/orange_light"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/item_height_normal" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large"> <ImageView android:id="@+id/img_pw" android:layout_width="@dimen/dp_18" android:layout_height="@dimen/dp_20" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_tiny" android:scaleType="fitXY" android:src="@drawable/icon_login_pw"/> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw" android:background="@null" android:hint="@string/password" android:inputType="textPassword" android:maxLines="1" android:textColor="@android:color/black" android:textColorHint="@color/tv_gray_deep" android:textSize="@dimen/text_size_normal"/> <View android:layout_width="match_parent" android:layout_height="@dimen/line_height" android:layout_alignParentBottom="true" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw" android:background="@color/orange_light"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/item_height_normal" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large"> <ImageView android:id="@+id/img_pw_again" android:layout_width="@dimen/dp_18" android:layout_height="@dimen/dp_20" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_tiny" android:scaleType="fitXY" android:src="@drawable/icon_login_pw"/> <EditText android:id="@+id/et_password_again" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="@dimen/margin_tiny" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw_again" android:background="@null" android:hint="请再次输入登录密码" android:inputType="textPassword" android:maxLines="1" android:textColor="@android:color/black" android:textColorHint="@color/tv_gray_deep" android:textSize="@dimen/text_size_normal" /> <View android:layout_width="match_parent" android:layout_height="@dimen/line_height" android:layout_alignParentBottom="true" android:layout_marginLeft="@dimen/margin_normal" android:layout_toRightOf="@+id/img_pw_again" android:background="@color/orange_light"/> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="67dp" android:layout_gravity="center" android:layout_marginTop="15dp" android:gravity="center_vertical|center" android:orientation="horizontal" android:weightSum="1"> <Button android:id="@+id/btn_register" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_orange_selector" android:paddingBottom="@dimen/margin_small" android:paddingTop="@dimen/margin_small" android:text="注册" android:textColor="@android:color/background_light" android:textSize="@dimen/text_size_normal" /> </LinearLayout> </LinearLayout>
RegisterActivity.java
package com.hhn.asus.da; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import db.Sqlite; import db.User; public class RegisterActivity extends AppCompatActivity { //用户名 private ImageView img_account; private EditText et_account; //密码 private ImageView img_pw; private EditText et_password; //再次输入密码 private ImageView img_pw_again; private EditText et_password_again; //注册按钮 private Button btn_register; private String name,pass,passAgain; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); init(); btn_register.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getEditString(); User user=new User(); user.setUsername(name); user.setUserpwd(pass); int result= Sqlite.getInstance(getApplicationContext()).saveUser(user); if (TextUtils.isEmpty(name)) { Toast.makeText(RegisterActivity.this,"请输入用户名",Toast.LENGTH_SHORT).show(); return; }else if(TextUtils.isEmpty(pass)){ Toast.makeText(RegisterActivity.this,"请输入密码",Toast.LENGTH_SHORT).show(); return; }else if(TextUtils.isEmpty(passAgain)){ Toast.makeText(RegisterActivity.this,"请再次输入密码",Toast.LENGTH_SHORT).show(); return; }else if(!pass.equals(passAgain)){ Toast.makeText(RegisterActivity.this,"两次输入的密码不一致",Toast.LENGTH_SHORT).show(); return; }else if(result==-1){ Toast.makeText(RegisterActivity.this,"此用户名已存在",Toast.LENGTH_SHORT).show(); return; }else { Toast.makeText(RegisterActivity.this,"注册成功",Toast.LENGTH_SHORT).show(); RegisterActivity.this.finish(); } } }); } private void init(){//控件初始化 img_account=(ImageView)findViewById(R.id.img_account); et_account=(EditText)findViewById(R.id.et_account); img_pw=(ImageView)findViewById(R.id.img_pw); et_password=(EditText)findViewById(R.id.et_password); img_pw_again=(ImageView)findViewById(R.id.img_pw_again); et_password_again=(EditText)findViewById(R.id.et_password_again); btn_register=(Button)findViewById(R.id.btn_register); } private void getEditString(){//获取控件中的字符串 name=et_account.getText().toString().trim(); pass=et_password.getText().toString().trim(); passAgain=et_password_again.getText().toString().trim(); } }
页面运行结果如下所示:
(3)阶乘运算
阶乘计算这一部分我用的是随机出1-10的数的阶乘,因为在刚开始设计这一部分时,我本来用的是100以内的数,但是后面发现计算量太大,所以改成10以内的数比较合理。
two.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/two"> <TextView android:id="@+id/timee" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="100dp" android:textColor="@color/ti" android:textSize="30dp" /> <TextView android:id="@+id/tv_question" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/editText" android:layout_centerHorizontal="true" android:layout_marginBottom="46dp" android:textSize="25dp" /> <EditText android:id="@+id/editText" android:layout_width="280dp" android:layout_height="50dp" android:layout_above="@+id/button" android:layout_centerHorizontal="true" android:layout_marginBottom="36dp" android:gravity="bottom" android:hint="请输入答案" android:inputType="number"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="确定" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="95dp"/> </RelativeLayout>
two.java
package com.hhn.asus.da; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.util.Random; /** * Created by ASUS on 2018/6/24. */ public class two extends AppCompatActivity{ private TextView timee, question; private Button button; private EditText editText; String aa = "1"; private MyCount mc; String da; int time; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.one); button = (Button) findViewById(R.id.button); editText = (EditText) findViewById(R.id.editText); timee = (TextView) findViewById(R.id.timee); question = (TextView) findViewById(R.id.question); PublicWay.activityList.add(this); mc = new two.MyCount(10000, 1000); mc.start(); final float result = question(); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { float answer = Float.parseFloat(editText.getText().toString()); //float answer=editText.getText().toString(); if (answer == result) { Toast.makeText(two.this, "你答对了", Toast.LENGTH_LONG).show(); return; } else { Toast.makeText(two.this, "答错了", Toast.LENGTH_LONG).show(); } } }); } ; class MyCount extends CountDownTimer { public MyCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onTick(long l) { time = (int) l / 1000; timee.setText("倒计时:" + time); } @Override public void onFinish() { Intent fail = new Intent(); fail.setClass(two.this, fail.class); startActivity(fail); } } public float question() { final Random random = new Random(); float result = 1; final int num1 = random.nextInt(10) + 1;//数字的随机生成 for (int i = 1; i <= num1; i++) { result = i * result; } question.setText(num1 + "!" + "="); return result; } @Override protected void onDestroy() { super.onDestroy(); if ("1".equals(aa)) { mc.cancel(); mc = null; } else if ((!"1".equals(aa)) && "0".equals(time)) { Intent fail = new Intent(); fail.setClass(two.this, fail.class); startActivity(fail); } } }
页面运行结果如下:
五、结对编程软件过程耗时估计与统计表
PSP2.1 | Personal Software Process Stages | Time |
Planning | 计划 | 10 |
·Estimate | 估计这个任务需要多少时间 | 20 |
Development | 开发 | 15 |
·Analysis | 需求分析 (包括学习新技术) | 1 |
·Design Spec | 生成设计文档 | 1 |
· Design Review | 设计复审 | 1 |
· Coding Standard | 代码规范 | 1.5 |
· Design | 具体设计 | 4.5 |
· Coding | 具体编码 | 16 |
· Code Review | 代码复审 | 1.5 |
· Test | 测试(自我测试,修改代码,提交修改) | 1 |
·Reporting | 报告 | 3 |
· | 测试报告 | 0 |
· | 计算工作量 | 1 |
· | 并提出过程改进计划 | 1 |
六、总结
通过本次做这个app,使得我对于Android Studio的编程变得更加熟练,同时也更加深刻的理解了四则运算的功能,虽然本次做这个app花了不少时间,但是在后期调试时还是会发现不少Bug。对于本次作业我觉得我们小组有一点很重要的地方没有做到的是命名的规范化,等到我们已经做完了才发现这个问题时改起来会比较困难,对于这个问题我们下次会注意的。