赞
踩
本人一直想找时间系统整理一下之前做过的一些实验,便于后续用到的时候可以尽快的使用,po出来也便于大家交流学习,有问题欢迎交流指正,与诸君共勉!
这次是Java的课程设计,现在看起来更像是一个安卓开发的课程设计。设计了一个贪吃蛇游戏,有友好的GUI界面和较为全面的功能。
图1 开始动画
图2 登录界面
下载GreedySnake软件并打开后,首次使用需要点击登陆界面的“没有账号?点此注册”按钮进入GamePlayer用户注册界面进行用户注册,如图3。
按提示输入账号:用户名/手机号/邮箱,并设置密码:数字组合,如图4。
注册成功后弹出提示:注册成功,并跳转至登录界面,如图5。
图3 注册界面
图4 用户注册
图5 注册成功
登陆界面输入用户名和密码,勾选“我同意用户服务协议和隐私政策”,点击登录按钮,进入游戏菜单界面,如图7。
图7 游戏菜单界面
从游戏菜单界面点击“新游戏“,进入贪吃蛇游戏初始界面,如图9,小蛇初始身长为4。默认开始播放游戏背景音乐。
单击“开始游戏“按钮,进入游戏主界面,如图10。用户可点击“向右”、“向左”、“向上”、“向下”四个按钮控制小蛇爬动的方向,食物随机出现在游戏界面中,食物种类从下图六种水果中随机产生。
图8 六种食物种类
游戏中,默认背景音乐暂停,小蛇每吃到食物一次,会播放相应音效。
图9 游戏初始界面
图10 游戏中
游戏中,点击”游戏暂停“按钮,会播放按钮点击音效并默认继续播放背景音乐,屏幕中央提示”点击按钮,继续游戏“字样,如图11。
单击主界面右上角喇叭图标,图标更换为静音模式,如图12。按钮音效和背景音乐将切换至静音模式。
图11 游戏中点击“游戏暂停”按钮
图12 游戏切换为静音模式
游戏过程中,根据不同得分,将展示不同效果,具体规则如下:
小蛇吃到一次食物加10分,每吃到一个食物,播放win音效;
得分小于250,分数每增加50,播放一次鼓掌音效;
得分大于等于300,小于400,分数每增加20,播放一次鼓掌音效;
得分大于等于400,分数每增加10,播放一次鼓掌音效,屏幕中央显示提示字样“YOU ARE A WINNER!”,中央”游戏暂停”按钮字样变为“WIN”。
分数达到500,自动跳转最终胜利界面,如图13。
每轮游戏过后,若本轮得分超过本用户历史最高分数,将自动更新历史最高分数。在游戏菜单界面点击“查看历史最高分数”可查看最高分数记录,如图14。
在游戏菜单界面点击“退出游戏“按钮,可返回GamePlayer登录界面。
本客户端无服务器,故用户账户密码数据、历史最高分数数据、游戏界面静音状态数据均存放在手机本地文件与数据库中。
对于用户注册信息,将用户密码使用国家密码管理局发布的SM4.0密码算法进行加密后存储,增强用户信息安全性。在Android Studio平台模拟运行,注册后,可看到日志信息如图15,用户密码已被加密处理。
图15 注册账户Log信息
用户账号密码数据统一存储在snakeUser.db数据库的user表中。
图16 snakeUser.db数据库
用户历史最高分数、静音按键状态信息分别存储在文件名为“用户名+scorefile.xml”、“用户名+VolumeFile.xml”的文件中,如图17。
图17 最高分数、音量文件信息
共设计16个Java文件:
Macro:用于定义游戏界面中的固定参数、文件名称等
User:用于创建用户信息
UserService:用于用户注册、登录功能实现
StartActivity:用于软件开始动画的3秒显示
MainActivity: 用于主游戏界面小蛇移动、游戏进行状态、静音状态、得分反应的逻辑控制;
MyDatabaseHelper:用于连接SQLite数据库,创建user表,存储用户信息
SharedPre:用于用户历史最高分数、静音按钮状态信息存储的文件操作
RegisterActivity:用于注册界面的显示及按钮事件响应
LoginActivity:用于登录界面的显示及按钮事件的响应
FinalwinActivity:用于用户最终胜利界面的显示
SM4:用于国密SM4算法的工具类
Encryption:用于国密SM4算法的加解密
Images:用于游戏主界面的小蛇、食物等动态构件绘制
ChooseActivity:游戏菜单界面的显示及按钮事件响应
SoundPlay:用于游戏中的按钮音效、吃到食物音效、游戏失败音效的短音频控制
BGMServer:用于游戏中的背景音乐(长音频)控制
共设计6个布局文件:
activity_beginning.xml:开始动画界面布局
activity_finalwin.xml:最终胜利界面布局
activity_login.xml:登录界面布局
activity_main.xml:游戏主界面布局
activity_register.xml:注册界面布局
activity_start_view.xml:游戏菜单界面布局
- BGMServer.java
- package com.example.android_snake;
-
- import android.content.Context;
- import android.media.MediaPlayer;
-
- /**
- * 贪吃蛇背景音乐工具类
- */
- public class BGMserver {
- private static MediaPlayer mp =null;
- public static void play(Context context, int resource){
- stop(context);
- mp = MediaPlayer.create(context, resource);
- mp.setLooping(true);
- mp.start();
- }
- public static void stop(Context context) {
- // TODO Auto-generated method stub
- if(mp!= null){
- mp.stop();
- mp.release();
- mp = null;
- }
- }
-
- }
- ChooseActivity.java
- package com.example.android_snake;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- import android.content.Context;
- import android.content.Intent;
- import android.media.AudioManager;
- import android.media.SoundPool;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
-
- import java.util.HashMap;
-
-
- /**
- * The type Star view:游戏开始界面
- */
- public class ChooseActivity extends AppCompatActivity implements View.OnClickListener {
-
- private Button Startbutton,Sbutton,Backbutton;
- private String usern;
- /**
- * The Shared:实例化存储对象
- */
- SharedPre shared;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_start_view);
- Init();
-
- }
-
- /**
- * Init:初始化该活动界面信息
- */
- void Init(){
- usern = LoginActivity.usern;
- Startbutton =findViewById(R.id.star_game);
- Sbutton=findViewById(R.id.MostBUtton);
- Backbutton=findViewById(R.id.BackButton);
- shared=new SharedPre(usern,this);
- //soundp = new SoundPlay();
- //soundp.initSoundPool();//初始化声音池
- Startbutton.setOnClickListener(this);
- Sbutton.setOnClickListener(this);
- Backbutton.setOnClickListener(this);
- }
- /**
- * onClick:该界面按钮监听事件
- */
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.star_game:
- //sp.playSound(1, 0);//播放1号声音资源button,且播放一次
- Intent intent=new Intent(ChooseActivity.this,MainActivity.class);
- startActivity(intent);
- break;
- case R.id.BackButton:
- //sp.playSound(1, 0);//播放1号声音资源button,且播放一次
- finish();
- break;
- case R.id.MostBUtton:
- //sp.playSound(1, 0);//播放1号声音资源button,且播放一次
- Sbutton.setText(Macro.H_MOST_SCORE+shared.read());
- break;
- }
- }
- }
- SM4.java
- package com.example.android_snake;
-
-
- import java.util.Arrays;
-
- public class SM4 {
-
- private static SM4 mSm4 = null;
-
- public static SM4 getInstance() {
- if (mSm4 == null) {
- mSm4 = new SM4();
- }
- return mSm4;
- }
-
-
- public static final int DECRYPT = 0; // 解密
- public static final int ENCRYPT = 1; // 加密
- public static final int ROUND = 32;
- private static final int BLOCK = 16;
-
- private byte[] Sbox = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
- (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
- 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
- (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
- (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
- (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
- (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
- (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
- (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
- (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
- 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
- (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
- 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
- 0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
- (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
- (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
- (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
- (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
- 0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
- (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
- (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
- (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
- (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
- (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
- 0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
- (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
- 0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
- (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
- (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
- 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
- (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
- 0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
- (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
- 0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
- (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
- (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
- (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
- 0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
- (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
-
- private int[] CK = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
- 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5,
- 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81,
- 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d,
- 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
- 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25,
- 0x2c333a41, 0x484f565d, 0x646b7279 };
-
- private int Rotl(int x, int y) {
- return x << y | x >>> (32 - y);
- }
-
- private int ByteSub(int A) {
- return (Sbox[A >>> 24 & 0xFF] & 0xFF) << 24
- | (Sbox[A >>> 16 & 0xFF] & 0xFF) << 16
- | (Sbox[A >>> 8 & 0xFF] & 0xFF) << 8 | (Sbox[A & 0xFF] & 0xFF);
- }
-
- private int L1(int B) {
- return B ^ Rotl(B, 2) ^ Rotl(B, 10) ^ Rotl(B, 18) ^ Rotl(B, 24);
- // return B^(B<<2|B>>>30)^(B<<10|B>>>22)^(B<<18|B>>>14)^(B<<24|B>>>8);
- }
-
- private int L2(int B) {
- return B ^ Rotl(B, 13) ^ Rotl(B, 23);
- // return B^(B<<13|B>>>19)^(B<<23|B>>>9);
- }
-
- void SMS4Crypt(byte[] Input, byte[] Output, int[] rk) {
- int r, mid;
- int[] x = new int[4];
- int[] tmp = new int[4];
- for (int i = 0; i < 4; i++) {
- tmp[0] = Input[0 + 4 * i] & 0xff;
- tmp[1] = Input[1 + 4 * i] & 0xff;
- tmp[2] = Input[2 + 4 * i] & 0xff;
- tmp[3] = Input[3 + 4 * i] & 0xff;
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- // x[i]=(Input[0+4*i]<<24|Input[1+4*i]<<16|Input[2+4*i]<<8|Input[3+4*i]);
- }
- for (r = 0; r < 32; r += 4) {
- mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0];
- mid = ByteSub(mid);
- x[0] = x[0] ^ L1(mid); // x4
-
- mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1];
- mid = ByteSub(mid);
- x[1] = x[1] ^ L1(mid); // x5
-
- mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2];
- mid = ByteSub(mid);
- x[2] = x[2] ^ L1(mid); // x6
-
- mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3];
- mid = ByteSub(mid);
- x[3] = x[3] ^ L1(mid); // x7
- }
-
- // Reverse
- for (int j = 0; j < 16; j += 4) {
- Output[j] = (byte) (x[3 - j / 4] >>> 24 & 0xFF);
- Output[j + 1] = (byte) (x[3 - j / 4] >>> 16 & 0xFF);
- Output[j + 2] = (byte) (x[3 - j / 4] >>> 8 & 0xFF);
- Output[j + 3] = (byte) (x[3 - j / 4] & 0xFF);
- }
- }
-
- private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) {
- int r, mid;
- int[] x = new int[4];
- int[] tmp = new int[4];
- for (int i = 0; i < 4; i++) {
- tmp[0] = Key[0 + 4 * i] & 0xFF;
- tmp[1] = Key[1 + 4 * i] & 0xff;
- tmp[2] = Key[2 + 4 * i] & 0xff;
- tmp[3] = Key[3 + 4 * i] & 0xff;
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
- }
- x[0] ^= 0xa3b1bac6;
- x[1] ^= 0x56aa3350;
- x[2] ^= 0x677d9197;
- x[3] ^= 0xb27022dc;
- for (r = 0; r < 32; r += 4) {
- mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
- mid = ByteSub(mid);
- rk[r + 0] = x[0] ^= L2(mid); // rk0=K4
-
- mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
- mid = ByteSub(mid);
- rk[r + 1] = x[1] ^= L2(mid); // rk1=K5
-
- mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
- mid = ByteSub(mid);
- rk[r + 2] = x[2] ^= L2(mid); // rk2=K6
-
- mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
- mid = ByteSub(mid);
- rk[r + 3] = x[3] ^= L2(mid); // rk3=K7
- }
-
- // 解密时轮密钥使用顺序:rk31,rk30,...,rk0 //解密时轮密钥反向
- if (CryptFlag == DECRYPT) {
- for (r = 0; r < 16; r++) {
- mid = rk[r];
- rk[r] = rk[31 - r];
- rk[31 - r] = mid;
- }
- }
- }
-
- public int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) {
- int point = 0;
- int[] round_key = new int[ROUND];
- SMS4KeyExt(key, round_key, CryptFlag);
- byte[] input = new byte[16];
- byte[] output = new byte[16];
-
- while (inLen >= BLOCK) {
- input = Arrays.copyOfRange(in, point, point + 16);
- SMS4Crypt(input, output, round_key);
- System.arraycopy(output, 0, out, point, BLOCK);
- inLen -= BLOCK;
- point += BLOCK;
- }
- return 0;
- }
- }
- Encryption.java
- package com.example.android_snake;
-
- import android.util.Log;
-
- public class Encryption {
-
- /**
- * SM4加解密封装
- * @param data 传入参数
- * @param flag 加密为1&解密为0
- * @param key 16字节密钥
- * @return 加解密结果
- */
- public static String deal(String data, int flag, byte[] key)
- {
- StringBuilder builder = new StringBuilder();
- SM4 sm4 = SM4.getInstance();
- String strData = "";
- byte[] bInData;
- byte[] bOutData = new byte[16];
- int nIndex;
- int nDataLen = data.length();
- int nCount = 0;
- int nLastLen = nDataLen%32;
- if (nLastLen > 0) {
- nCount = nDataLen/32 + 1;
- if (flag ==0) {
- Log.i("SM4", "数据长度不正确,需解密数据应是32的倍数");
- }
- } else {
- nCount = nDataLen/32;
- }
- for (int i = 0; i < nCount; i++) {
- if ((i+1) == nCount && nLastLen > 0) {
- nIndex = i*32;
- strData = data.substring(nIndex, nIndex+nLastLen);
- strData = zero(strData);
- bInData = hexStringToBytes(strData);
- sm4.sms4(bInData,bInData.length,key,bOutData,flag);
- strData = bytesToHexString(bOutData,0,16);
- builder.append(strData);
- } else {
- nIndex = i*32;
- strData = data.substring(nIndex, nIndex+32);
- bInData = hexStringToBytes(strData);
- sm4.sms4(bInData,bInData.length,key,bOutData,flag);
- strData = bytesToHexString(bOutData,0,16);
- builder.append(strData);
- }
- }
- return builder.toString();
- }
-
- /**
- * 补位方法,SM4 分块加密 ,每块16字节,此处不足补0. 扩展说明:有得规则是首字节补80,之后补00,还有区分左补和右补,如果此加解密不能满足要求,可以往这方面去做
- * @param data 需补位的数据
- * @return 补位后的字符串
- */
- public static String zero(String data) {
- StringBuilder builder = new StringBuilder();
- builder.append(data);
- int nLen = data.length();
- while (nLen < 32) {
- builder.append("0");
- nLen++;
- }
- return builder.toString();
- }
-
- /**
- * hexString转byte[]数组
- * @param str 字符串,原串为“112233”
- * @return 转换后的数据, 转换后为 0x11,0x22,0x33
- */
- public static byte[] hexStringToBytes(String str) {
- int charIndex, value;
- int datalen = str.length() / 2;
- byte[] data = new byte[datalen];
- for (int i = 0; i < datalen; i++) {
- charIndex = i * 2;
- value = Integer.parseInt(str.substring(charIndex, charIndex + 2), 16);
- data[i] = (byte) value;
- }
-
- return data;
- }
-
- /**
- * byte[]数组转hexString
- * @param data 需转换的数组 0x11,0x22,0x33
- * @param offset 需转换开始位置
- * @param len 需转换长度
- * @return 转换后的字符传为“112233”
- */
- public static String bytesToHexString(byte[] data, int offset, int len) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < len; i++)
- sb.append(String.format("%02X", data[i + offset] & 0xff));
- return sb.toString();
- }
-
- }
- FinalwinActivity.java
- package com.example.android_snake;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.Window;
- import android.view.WindowManager;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- public class FinalwinActivity extends AppCompatActivity {
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏以及状态栏
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_finalwin);
- }
- }
- Images.java
- package com.example.android_snake;
-
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.view.View;
- import android.view.WindowManager;
- import android.util.DisplayMetrics;
-
- import java.util.Random;
-
- public class Images extends View {
-
- private int BitmapX,BitmapY;
- private int FoodX,FoodY;
- private int[] snakeX =new int[Macro.MAX_LENGTH];
- private int[] snakeY =new int[Macro.MAX_LENGTH];
- private int length;
- private int direction;
- private boolean islive;//是否存活 状态
- private Bitmap rbitmaphead,lbitmaphead,ubitmaphead,dbitmaphead,bitmapbody,bitmapfood;//四个方向的头及蛇的身体、食物
- private Bitmap bitmapfoods[] = new Bitmap [6];
- private Bitmap bling;
-
- public boolean isIslive() {
- return islive;
- }
-
- public void setIslive(boolean islive) {
- this.islive = islive;
- }
-
- public int getFoodX() {
- return FoodX;
- }
-
- public void setFoodX(int foodX) {
- FoodX = foodX;
- }
- public void setBitmapfood(int x){
- if(x < 6 && x >= 0)
- bitmapfood = bitmapfoods[x];
- }
-
- public int getFoodY() {
- return FoodY;
- }
-
- public void setFoodY(int foodY) {
- FoodY = foodY;
- }
-
- public int getDirection() {
- return direction;
- }
-
- public void setDirection(int direction) {
- this.direction = direction;
- }
-
- public int getLength() {
- return length;
- }
-
- public void setLength(int length) {
- this.length = length;
- }
-
- public int getBitmapX() {
- return BitmapX;
- }
-
- public void setBitmapX(int bitmapX) {
- BitmapX = bitmapX;
- }
-
- public int getBitmapY() {
- return BitmapY;
- }
-
- public void setBitmapY(int bitmapY) {
- BitmapY = bitmapY;
- }
-
- public Images(Context context) {
- super(context);
- }
-
- /**
- * 小蛇初始化
- */
- public void Init(){
-
- BitmapX=Macro.INIT_SNAKEX;
- // BitmapX = MainActivity.screenWidth/2; //手机屏幕宽度的一半
- BitmapY=Macro.INIT_SNAKEY;
- FoodX=Macro.INIT_FOODX;
- FoodY=Macro.INIT_FOODY;//初始坐标
- Random r = new Random(); //用于生成随机数
- int randomN = r.nextInt(3);//随机生成[0,3)的整数
- snakeX[0]=BitmapX;
- snakeY[0]=BitmapY;//蛇头的位置
- length =Macro.INIT_LENGHT;//蛇的初始长度
- islive=true;
-
- switch (randomN){//设置蛇的初始状态
- case 0://初始方向向右
- direction=Macro.Right;//蛇的初始方向
- //画出初始的蛇身
- for(int i = 1; i< length; i++){
- snakeX[i]= snakeX[i-1]-Macro.UNIT;
- snakeY[i]= snakeY[0]; //初始状态
- }
- break;
-
- case 1://初始方向向上
- direction=Macro.Up;//蛇的初始方向
- //画出初始的蛇身
- for(int i = 1; i< length; i++){
- snakeY[i]= snakeY[i-1]+Macro.UNIT;
- snakeX[i]= snakeX[0]; //初始状态
- }
- break;
- case 2://初始方向向下
- direction=Macro.Down;//蛇的初始方向
- //画出初始的蛇身
- for(int i = 1; i< length; i++){
- snakeY[i]= snakeY[i-1]-Macro.UNIT;
- snakeX[i]= snakeX[0]; //初始状态
- }
- break;
- }
-
- }
-
-
- /**
- * 引用小蛇图片,并设置图片大小
- */
- public void Size(){
-
- //避免大图片解析问题--头部
- BitmapFactory.Options headoptions = new BitmapFactory.Options();
- //调整
- headoptions.inSampleSize= Macro.IMAGE_HEAD_SIZE; //蛇头缩放倍数
- headoptions.inJustDecodeBounds=false;
-
- //避免大图片解析问题--身体
- BitmapFactory.Options bodyoptions = new BitmapFactory.Options();
- bodyoptions.inSampleSize=Macro.IMAGE_BODY_SIZE; //蛇身的缩放倍数
- bodyoptions.inJustDecodeBounds=false;
-
-
- //六种食物随机产生
- bitmapfoods[0]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food);
- bitmapfoods[1]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food1);
- bitmapfoods[2]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food2);
- bitmapfoods[3]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food3);
- bitmapfoods[4]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food4);
- bitmapfoods[5]= BitmapFactory.decodeResource(this.getResources(),R.drawable.food50);
-
- rbitmaphead= BitmapFactory.decodeResource(this.getResources(),R.drawable.rhead0, headoptions); //
- ubitmaphead= BitmapFactory.decodeResource(this.getResources(),R.drawable.uhead0, headoptions);
- lbitmaphead= BitmapFactory.decodeResource(this.getResources(),R.drawable.lhead0, headoptions);
- dbitmaphead= BitmapFactory.decodeResource(this.getResources(),R.drawable.dhead0, headoptions);
- bitmapbody= BitmapFactory.decodeResource(this.getResources(),R.drawable.body_0, bodyoptions);
- Random r = new Random(); //用于生成随机数
- int randomN = r.nextInt(6);//随机生成[0,6)的整数
- bitmapfood= bitmapfoods[randomN];
-
- }
-
-
- /**
- * 画蛇,将蛇画在屏幕上 canvas用于绘制背景的画布
- * Canvas 画布
- * Paint 画笔
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas); //Canvas(画纸,通常称为画布)
- Paint paint=new Paint(); //生成一个画笔对象
- //画食物
-
- /**
- * @param bitmap The bitmap to be drawn
- * @param left The position of the left side of the bitmap being drawn
- * @param top The position of the top side of the bitmap being drawn
- * @param paint The paint used to draw the bitmap (may be null)
- */
-
-
- canvas.drawBitmap(bitmapfood, FoodX, FoodY, paint);//画第一食物, 第一个参数为要绘制的bitmap对象,第四个参数为Paint对象。
-
-
- snakeX[0]=BitmapX;
- snakeY[0]=BitmapY;
- switch (direction){
- case Macro.Right:
- canvas.drawBitmap(rbitmaphead, snakeX[0], snakeY[0],paint);//蛇头往右,读取x、y坐标,填充画笔
- //canvas.drawBitmap(bling, snakeX[0], snakeY[0],paint);
- break;
- case Macro.Up:
- canvas.drawBitmap(ubitmaphead, snakeX[0], snakeY[0],paint);
- // canvas.drawBitmap(bling, snakeX[0], snakeY[0],paint);//蛇头往右,读取x、y坐标,填充画笔
- break;
- case Macro.Left:
- canvas.drawBitmap(lbitmaphead, snakeX[0], snakeY[0],paint);
- break;
- case Macro.Down:
- canvas.drawBitmap(dbitmaphead, snakeX[0], snakeY[0],paint);
- break;
- }
- //画出小蛇身体的位置
- for(int i = 1; i< length; i++) {
- canvas.drawBitmap(bitmapbody, snakeX[i], snakeY[i], paint);
- }
- //小蛇咬住身体了 生存位置零
- for(int i = 1; i< length; i++){
- if(snakeX[0]== snakeX[i]&& snakeY[0]== snakeY[i]){
- islive=false;
- }
- }
- //身体从最后一节向前一节位置移动
- for(int i = length; i>0; i--){
- snakeX[i]= snakeX[i-1];
- snakeY[i]= snakeY[i-1];
- }
- /**
- * Returns true if this bitmap has been recycled. If so, then it is an error
- * to try to access its pixels, and the bitmap will not draw.
- **如果该位图已被回收,则返回true。如果是,则是false
- * *试图访问其像素,位图将不会绘制。
- * *如果位图已经被回收,返回true
- * @return true if the bitmap has been recycled
- */
-
- //图片回收
- if(rbitmaphead.isRecycled()){
- rbitmaphead.recycle();
- }
- if(bitmapbody.isRecycled()){
- bitmapbody.recycle();
- }
- if(ubitmaphead.isRecycled()){
- rbitmaphead.recycle();
- }
- if(lbitmaphead.isRecycled()){
- rbitmaphead.recycle();
- }
- if(dbitmaphead.isRecycled()){
- rbitmaphead.recycle();
- }
- }
- }
- LoginActivity.java
- package com.example.android_snake;
-
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- public class LoginActivity extends AppCompatActivity{
- /**
- * 定义私有成员文本 账号密码etc
- */
- private EditText username;
- private EditText password;
- private int remarks;//初始值为0
- private Button Loginbutton; //登录按钮
- private Button goRegisterButton;//打开注册界面
- static public String usern; //工具字符串,用于用户分数信息存储文件命名
- private Button Rbtlogin;
- boolean agree = false;//是否同意用户协议 标志位
-
- private void findViews(){
- username = (EditText) findViewById(R.id.username_login);
- password = (EditText) findViewById(R.id.password_login);
- //remarks = 0;//初始化为0
- Loginbutton = (Button) findViewById(R.id.bt_login);
- goRegisterButton =(Button) findViewById(R.id.bt_goRegister);
- Rbtlogin = (Button) findViewById(R.id.rbt_login);
- }
-
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_login);//即activity_login.xml
- findViews();
-
-
- //设置按钮点击监听器
- Rbtlogin.setOnClickListener(new View.OnClickListener() {
- //按钮点击
- @Override
- public void onClick(View view) {
-
- if (view.getId() == R.id.rbt_login) {//同意协议
- Log.i("TAG","同意用户协议");
- agree = true;
- }
- }
- });
-
- Loginbutton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-
- //MainActivity.playSound();
- if(!agree) {//未勾选同意用户协议
- Toast.makeText(LoginActivity.this,"请先勾选同意用户协议",Toast.LENGTH_LONG).show();
- return;
- }
- String name = username.getText().toString().trim();
- //System.out.println(name);
- String pass = password.getText().toString().trim();
- //System.out.println(pass);
-
- //对密码进行国密SM4加密,密文与用户数据库中数据表字段比较
- String strKey = "0123456789abcdeffedcba9876543210";//密钥
- byte[] bKey = Encryption.hexStringToBytes(strKey);
- String CPass = Encryption.deal(pass,SM4.ENCRYPT,bKey);//密码加密后的密文CPass
-
- Log.i("TAG","username_"+name+"_ CPassword_"+CPass);
-
- UserService uService = new UserService(LoginActivity.this);
- boolean flag = uService.login(name,CPass);
- if(flag){
- Log.i("TAG","登陆成功");
- Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_LONG).show();
- usern = name;//便于用户最高分数文件存储 ,为了安全性,只赋值用户名
- //登录成功,跳转游戏选择界面
- Intent intent = new Intent(LoginActivity.this,ChooseActivity.class);
- startActivity(intent);
- }else{
- Log.i("TAG","登陆失败");
- Toast.makeText(LoginActivity.this,"登录失败",Toast.LENGTH_LONG).show();
- }
- }
- });
-
- goRegisterButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {//跳转注册界面
- startActivity(new Intent(LoginActivity.this,RegisterActivity.class));
-
- }
- });
- }
-
- }
-
- Macro.java
- package com.example.android_snake;
-
- import android.content.Context;
- import android.util.DisplayMetrics;
- import android.view.WindowManager;
-
- /**
- * The type Macro:宏的定义
- */
- public class Macro {
- /**
- * The constant Up:定义小蛇头部方向向上
- */
- public static final int Up=0x11;
- /**
- * The constant :定义小蛇头部方向向下
- */
- public static final int Down=0x12;
- /**
- * The constant Left:定义小蛇头部方向向左
- */
- public static final int Left=0x13;
- /**
- * The constant Right:定义小蛇头部方向向右
- */
- public static final int Right=0x14;
- /**
- * The constant UNIT:定义小蛇移动的基本单位
- */
- public static final int UNIT=50;
- /**
- * The constant LEAST_SIZE:小蛇生活区最小单位
- */
- public static final int LEAST_SIZE=1;
- /**
- * The constant DELAY:定时器响应run延时
- */
- public static final int DELAY=100;
- /**
- * The constant PERIOD:定时器启动的间隔时间
- */
- public static final int PERIOD=300;
- /**
- * The constant INIT_SNAKEX:小蛇初始头部的X坐标
- */
- // public static final int INIT_SNAKEX =600;
- public static final int INIT_SNAKEX =MainActivity.screenWidth/2;
- /**
- * The constant INIT_SNAKEY:小蛇初始头部的Y坐标
- */
- public static final int INIT_SNAKEY =400;
- /**
- * The constant INIT_FOODX:食物初始的X坐标
- */
- public static final int INIT_FOODX=400;
- /**
- * The constant INIT_FOODY:食物初始的Y坐标
- */
- public static final int INIT_FOODY=500;
- /**
- * The constant INIT_LENGHT:小蛇初始长度
- */
- public static final int INIT_LENGHT=4;
- /**
- * The constant IMAGE_HEAD_SIZE:小蛇头图片缩小倍数
- */
- //public static final int IMAGE_HEAD_SIZE=20;
- public static final int IMAGE_HEAD_SIZE=1;
- /**
- * The constant IMAGE_BODY_SIZE:小蛇身体图片缩小倍数
- */
- //public static final int IMAGE_BODY_SIZE=46;
- public static final int IMAGE_BODY_SIZE=1;
- /**
- * The constant SCORE_UNIT:每次加分
- */
- public static final int SCORE_UNIT=10;
- /**
- * The constant MAX_LENGTH:小蛇最大长度
- */
- public static final int MAX_LENGTH =900;
- /**
- * The constant SPEED:小蛇的初始速度
- */
- public static final int SPEED=20;
- /**
- * The constant FOOD:小蛇吃到食物就会加速的基本单位
- */
- public static final int FOOD=40;
- /**
- * The constant MAX_SPEED:小蛇移动的最大速度
- */
- public static final int MAX_SPEED =270;
- /**
- * The constant SCORE:此局的分数显示
- */
- public static final String SCORE="当前分数:";
- /**
- * The constant MOST_SCORE:历史最高分数显示
- */
- public static final String MOST_SCORE="最高分数:";
- /**
- * The constant H_MOST_SCORE:主界面查询分数显示
- */
- public static final String H_MOST_SCORE="最高分数(点击更新):";
- /**
- * The constant Pname:分数存储文件名统一名称后缀
- */
- public static final String Pname="scorefile";
- /**
- * The constant Pname:静音选中存储文件名统一名称后缀
- */
- public static final String PnameFlag="Volumefile";
-
-
- /**
- * 获得屏幕的宽度
- * @param ctx
- * @return
- */
- public static int getScreenWidth(Context ctx) {
- // 从系统服务中获取窗口管理器
- WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics dm = new DisplayMetrics();
- // 从默认显示器中获取显示参数保存到dm对象中
- wm.getDefaultDisplay().getMetrics(dm);
- return dm.widthPixels; // 返回屏幕的宽度数值
-
- }
-
- /**
- * 获得屏幕的高度
- */
- public static int getScreenHeight(Context ctx) {
- // 从系统服务中获取窗口管理器
- WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics dm = new DisplayMetrics();
- // 从默认显示器中获取显示参数保存到dm对象中
- wm.getDefaultDisplay().getMetrics(dm);
- return dm.heightPixels; // 返回屏幕的高度数值
- }
-
- }
- MainActivity.java
- package com.example.android_snake;
-
- import static com.example.android_snake.BGMserver.play;
- import static com.example.android_snake.BGMserver.stop;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.content.Intent;
- import android.media.AudioManager;
- import android.media.SoundPool;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import android.view.View;
- import android.widget.Button;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- import android.widget.RelativeLayout;
- import android.widget.TextView;
- import java.util.HashMap;
- import java.util.Random;
- import java.util.Timer;
- import java.util.TimerTask;
-
- /**
- * The type Main activity:小蛇移动及方向控制逻辑处理
- */
- public class MainActivity extends AppCompatActivity implements View.OnClickListener {
-
- private String usern;
- private FrameLayout Living_Space;
- private boolean isstart =false;
- private boolean volumeflag = true;
- private Timer timer;
- private Button BT_isstar,BT_RIGHT,BT_UP,BT_DOWN,BT_LEFT,BT_Volume;
- private TextView prompt;
- private TextView ScoreView;
- private int direction;
- private int weight,height;
- public static int screenWidth,screenHeight;
- private int countVolume;//计数点击音量按键的次数 判断奇偶性
- private boolean islive;
- private int score,time,mostscore;
- Images images;
- MoveSnake movesnake;
- SharedPre shared;
- private Handler handler;
- // RelativeLayout frameLayout_add_imageview;
-
- SoundPool sp;//声明SoundPool的引用
- HashMap<Integer, Integer> hm;//声明HashMap来存放声音文件
- int currStaeamId;//当前正播放的streamId
-
- private void initSoundPool() {//初始化声音池
- sp = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);//创建SoundPool对象
- hm = new HashMap<Integer, Integer>();//创建HashMap对象
- //加载声音文件,并且设置为1号 2号 3号声音放入hm中
- hm.put(1, sp.load(this, R.raw.button0, 1));
- hm.put(2, sp.load(this, R.raw.win, 1));
- hm.put(3, sp.load(this, R.raw.fail, 1));
- hm.put(4, sp.load(this, R.raw.applause, 1));
-
- }
-
- private void playSound(int sound, int loop) {//获取AudioManager引用
- AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
- //获取当前音量
- float streamVolumeCurrent = am.getStreamVolume(AudioManager.STREAM_MUSIC);
- //获取系统最大音量
- float streamVolumeMax = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
- //计算得到播放音量
- float volume = streamVolumeCurrent / streamVolumeMax;
- //调用SoundPool的play方法来播放声音文件
- currStaeamId = sp.play(hm.get(sound), volume, volume, 1, loop, 1.0f);
- }
-
-
- //BGM设置工具函数
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- stop(this);
- }
- //BGM设置工具函数
- protected void onResume() {
- // TODO Auto-generated method stub
- super.onResume();
- play(this, R.raw.bgm);
- }
-
- class MoveSnake extends Thread{
- @SuppressLint("HandlerLeak")
- // @Override
- public void run() {
- Looper.prepare();//调用 Looper.prepare()来给线程创建消息循环
- handler=new Handler(){
- public void handleMessage(Message msg) {
- if(isstart ==true&& islive==true){
- //方向控制
- if(msg.what==Macro.Right) {
- images.setBitmapX(images.getBitmapX() + Macro.UNIT);//The constant UNIT:定义小蛇移动的基本单位,x轴+一个移动单位
- images.setBitmapY(images.getBitmapY());
- }
- if(msg.what==Macro.Up) {
- images.setBitmapY(images.getBitmapY()-Macro.UNIT);
- images.setBitmapX(images.getBitmapX());
- }
- if(msg.what==Macro.Left) {
- images.setBitmapX(images.getBitmapX()-Macro.UNIT);
- images.setBitmapY(images.getBitmapY());
- }
- if(msg.what==Macro.Down) {
- images.setBitmapY(images.getBitmapY()+Macro.UNIT);
- images.setBitmapX(images.getBitmapX());
- }
- //吃掉食物处理
- if((images.getBitmapX()==images.getFoodX())&&(images.getBitmapY()==images.getFoodY())){
-
- //加吃到食物的光效
- // ImageView imageView = new ImageView(MainActivity.this);
- // imageView.setImageResource(R.drawable.bling);
- // FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(100,
- // 30);//为添加图片的大小
- // imageView.setLayoutParams(params);
- // //imageView.setBackgroundColor();
- // frameLayout_add_imageview.addView(imageView);
-
- // if(shared.readVolumeFlag()==1) playSound(2, 0);//播放2号声音资源win,且播放一次
-
- if(volumeflag) playSound(2, 0);//播放2号声音资源win,且播放一次
- images.setLength(images.getLength()+1);//蛇身长度加1
- int FoodX=(int)(Math.random()*(weight/Macro.UNIT))*Macro.UNIT; //食物随机位置出现
- int FoodY=(int)(Math.random()*(height/Macro.UNIT))*Macro.UNIT;
- if(FoodX==images.getBitmapX()&&FoodY==images.getBitmapY()){
- FoodX= FoodX+Macro.UNIT;
- FoodY= FoodY-Macro.UNIT;
- }
- Random r = new Random(); //用于生成随机数
- int randomN = r.nextInt(6);//随机生成[0,6)的整数
- images.setBitmapfood(randomN);//随机生成食物种类
- images.setFoodX(FoodX);
- images.setFoodY(FoodY);
- score+=Macro.SCORE_UNIT;
- if(score%Macro.FOOD==0){
- timer.cancel();
- if(time<=Macro.MAX_SPEED)
- time+=Macro.SPEED;
- StartView(time); //循环任务, sendmessage
- }
- }
- images.invalidate();//invalidate()方法是用来刷新重绘当前的View的,如果当前View的布局尺寸、位置没有变化,仅仅是绘制内容变化了,那么我们就可以调用invalidate()方法。
-
- //线程中更新控件,用来计分
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- ScoreView.setText(Macro.SCORE+String.valueOf(score));
- if(shared.readVolumeFlag()==0) onPause();
- //if(!volumeflag)onPause();//检测到静音设置,停止播放背景音
-
- if(score % 50 == 0 && score > 0 && score < 250 && shared.readVolumeFlag()==1) //250分以下,每满50分 掌声响起一次
- playSound(4, 0);//播放2号声音资源applause,且播放一次
- if(score >= 300 && score < 400 && score%20==0 && shared.readVolumeFlag()==1) //分数满300分,小于400分 每20分 掌声响起一次
- {
- playSound(4, 0);//播放声音资源applause,且播放一次
- }
- if(score >= 400 ) //分数大于四百 提示胜利祝贺 每10分掌声响一次
- {
- if(shared.readVolumeFlag()==1) playSound(4, 0);//播放2号声音资源applause,且播放一次
- prompt.setText(R.string.congratulations);//屏幕提示:YOU ARE A WINNER!
- prompt.setVisibility(View.VISIBLE);
- BT_isstar.setText("WIN!");
-
- }
- if(score == 500 ) //分数等于五百 提示奖励祝贺
- {
- //游戏胜利,跳转奖励界面!
- Intent intent = new Intent(MainActivity.this,FinalwinActivity.class);
- startActivity(intent);
- }
- }
- });
-
- //死亡判断
- if(images.getBitmapX()>=weight||images.getBitmapX()<0
- ||images.getBitmapY()<0||images.getBitmapY()>=height
- ||images.isIslive()==false){
- islive=false;
- //小蛇死亡提醒
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if(shared.readVolumeFlag()==1) playSound(3, 0);//播放3号声音资源fail,且播放一次
- BT_isstar.setText("重新开始");
- prompt.setText(R.string.promptrestar);
- prompt.setVisibility(View.VISIBLE);
- if(score>mostscore)
- mostscore=score;
- shared.save(usern,mostscore);//创分数新纪录 存入文件
- }
- });
- }
- }
- super.handleMessage(msg);
- }
-
-
- };
- Looper.loop();
- }
- }
-
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- MoveSnake movesnake =new MoveSnake();
- movesnake.start(); //启动一个线程
- Init();
- StartView(time);
-
- if(shared.readVolumeFlag()==1)onResume();//播放BGM
-
-
- screenWidth = Macro.getScreenWidth(MainActivity.this);
- screenHeight = Macro.getScreenHeight(MainActivity.this);
- //将图片加载到布局中
- Living_Space.addView(images);
- //获取活动空间的宽和高
- Living_Space.post(new Runnable() {
- @Override
- public void run() {
- weight=Living_Space.getWidth();
- height=Living_Space.getHeight();
- }
- });
-
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- handler.removeCallbacksAndMessages(null);
- timer.cancel();
- }
-
- /**
- * Init:初始化该界面控件及参数
- */
- //初始化
- void Init(){
-
- initSoundPool();//初始化声音池的方法
-
-
- usern = LoginActivity.usern;
- Living_Space=findViewById(R.id.framelayout);
- BT_isstar=findViewById(R.id.isstar);
- BT_RIGHT=findViewById(R.id.Right);
- BT_UP=findViewById(R.id.Up);
- BT_DOWN=findViewById(R.id.Down);
- BT_LEFT=findViewById(R.id.Left);
- BT_Volume = findViewById(R.id.Volume);
- prompt=findViewById(R.id.prompt);
- ScoreView=findViewById(R.id.Score);
- TextView mostScore = findViewById(R.id.MostScore);
-
- // if(shared.readVolumeFlag()==1){
- // volumeflag = true;
- // //BT_Volume.setBackground(R.drawable.volumeon);
- // }else{
- // volumeflag = false;
- // BT_Volume.setBackgroundDrawable(getResources().getDrawable(R.drawable.volumeoff));//背景设置为静音
- // }
-
- countVolume = 0;
- images=new Images(MainActivity.this);
- shared=new SharedPre(usern,MainActivity.this);
- direction=Macro.Right;
- images.Init();
- //direction = images.getDirection();
-
- images.Size();
- islive=true;
- score=0;
- mostscore=shared.read();
- time=0;
-
- if(shared.readVolumeFlag()==1)onResume();
-
- BT_isstar.setOnClickListener(this);
- BT_RIGHT.setOnClickListener(this);
- BT_UP.setOnClickListener(this);
- BT_LEFT.setOnClickListener(this);
- BT_DOWN.setOnClickListener(this);
- BT_Volume.setOnClickListener(this);
- mostScore.setText(Macro.MOST_SCORE+shared.read());
- }
-
- /**
- * onClick:该界面按钮监听事件
- */
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- //游戏的开始、暂停按钮
- case R.id.isstar:
-
- if(volumeflag)onResume();
- if(volumeflag)playSound(1, 0);//播放1号声音资源,且播放一次
- //提示播放即时音效
- //Toast.makeText(MainActivity.this, "播放音效", Toast.LENGTH_SHORT).show();
-
- isstart =!isstart;
- if(isstart &&islive) {
- BT_isstar.setText(R.string.stop);
- onPause();//bgm停止
- prompt.setVisibility(View.GONE);
- }
- else if(isstart ==false&&islive==true){
- BT_isstar.setText("继续游戏");
- prompt.setText("点击按钮继续游戏");
- prompt.setVisibility(View.VISIBLE);
- }
- else if(islive==false){
- // finish();
- Intent intent=new Intent(MainActivity.this,MainActivity.class);
- startActivity(intent);
- }
- break;
- //控制小蛇方向向右
- case R.id.Right:
- if(isstart &&direction!=Macro.Left) {
- direction = Macro.Right;
- images.setDirection(direction);
- }
- break;
- //控制小蛇方向向上
- case R.id.Up:
- if(isstart &&direction!=Macro.Down) {
- direction = Macro.Up;
- images.setDirection(direction);
- }
- break;
- //控制小蛇方向向左
- case R.id.Left:
- if(isstart &&direction!=Macro.Right) {
- direction = Macro.Left;
- images.setDirection(direction);
- }
- break;
- //控制小蛇方向向下
- case R.id.Down:
- if(isstart &&direction!=Macro.Up) {
- direction = Macro.Down;
- images.setDirection(direction);
- }
- break;
- case R.id.Volume:
- countVolume++;
- if(countVolume%2!=0){
- volumeflag = false;
- shared.saveFlag(volumeflag); //存入文件
- BT_Volume.setBackgroundDrawable(getResources().getDrawable(R.drawable.volumeoff));//背景设置为静音
- }
- else
- {
- volumeflag = true;
- shared.saveFlag(volumeflag); //存入文件
- BT_Volume.setBackgroundDrawable(getResources().getDrawable(R.drawable.volumeon));//背景设置
- }
-
- }
- }
-
-
- /**
- * 定时器,定时发送小蛇方向信息,控制小蛇速度
- * @param time
- */
-
- void StartView(int time) {
- timer=new Timer();
- TimerTask task = new TimerTask() {
- @Override
- public void run() {
- handler.sendEmptyMessage(direction);
- }
- };
- timer.schedule(task,Macro.DELAY,Macro.PERIOD-time);
- }
- }
-
- MydatabaseHelper.java
- package com.example.android_snake;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.content.Context;
- import android.widget.Toast;
-
- public class MyDatabaseHelper extends SQLiteOpenHelper {
- public static final String CREATE_User = "create table user ("
- + "id integer primary key autoincrement, "
- + "userName varchar(20), "
- + "Password varchar(40), "
- + "Remarks integer)";
- private Context mContext;
- static int dbVersion = 1;//版本
- static String name = "snakeUser.db";//数据库名
-
- /**
- *
- * @param context
- */
- public MyDatabaseHelper( Context context) {
- super(context, name, null, dbVersion);
- mContext = context;
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(CREATE_User);
- // Toast.makeText(mContext, "用户信息创建成功", Toast.LENGTH_SHORT).show();
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
- }
- }
- RegisterActivity.java
- package com.example.android_snake;
-
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- public class RegisterActivity extends AppCompatActivity {
- private EditText username;
- private EditText password;
- private Button register;
-
- private void findViews(){
- username = (EditText) findViewById(R.id.username_register);
- password = (EditText) findViewById(R.id.password_register);
- register = (Button) findViewById(R.id.registerButton);
- }
-
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_register);
- findViews();
- register.setOnClickListener(new View.OnClickListener(){
- public void onClick(View v){
- //MainActivity.playSound();
- String name = username.getText().toString().trim();
- String pass = password.getText().toString().trim();
-
- //对密码进行国密SM4加密,密文存入数据库
- String strKey = "0123456789abcdeffedcba9876543210";//密钥
- //String strKey = "0123456789abcdef";//密钥
- byte[] bKey = Encryption.hexStringToBytes(strKey);
- String CPass = Encryption.deal(pass,SM4.ENCRYPT,bKey);//密码加密后的密文CPass
-
- int remarks = 0;
- Log.i("TAG","username_"+name+"_ CPassword_"+CPass);
- Log.i("TAG","注册成功");
- UserService uService = new UserService(RegisterActivity.this);
- User user = new User();
- user.setUsername(name);
- user.setPassword(CPass);
- uService.register(user);
- Toast.makeText(RegisterActivity.this,"注册成功",Toast.LENGTH_LONG).show();
- //注册成功,跳转登录界面
- Intent intent = new Intent(RegisterActivity.this,LoginActivity.class);
- startActivity(intent);
- }
- });
- }
-
-
- }
- SharedPre.java
- package com.example.android_snake;
-
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.SharedPreferences;
- import android.database.sqlite.SQLiteDatabase;
-
-
- /**
- * 用户最高分数记录信息
- */
- public class SharedPre {
- private int mostscore;
- private Context context;
- String FileName;
- String FileNameVolume;
- private boolean volumeflag;//是否选中静音
-
- public SharedPre() {
- }
-
- public SharedPre(String usern,Context context) {
- FileName = usern+Macro.Pname; //文件名:用户名加scorefile
- FileNameVolume = usern+Macro.PnameFlag; //文件名:用户名加VolumeFile
- this.context = context;
- volumeflag = true; //默认选中
- }
-
- public void setvolumeFlag(boolean flag){
- volumeflag = flag;
- }
-
-
- /**
- * 存储最高游戏分数记录
- * @param usern 用户名
- * @param mscore 最高分数
- */
- public void save(String usern,int mscore) {
- SharedPreferences sp = context.getSharedPreferences(FileName, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sp.edit();
- editor.putInt("score",mscore);
- editor.apply();//文件存储结束
-
- //更新用户数据库
- UserService uService = new UserService(context);
- uService.updateRemarks(usern,mscore);
-
- // //更新用户数据库
- // MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
- //
- // SQLiteDatabase db = dbHelper.getWritableDatabase();
- // /*实例化内容值*/
- // ContentValues values = new ContentValues();
- //
- // /*在values中添加内容*/
- // values.put("Remarks", mscore);
- // /*修改条件*/
- // String whereClause = "userName=?";
- // /*修改添加参数*/
- // String[] whereArgs = {usern};
- // /*修改*/
- // db.update("user", values, whereClause, whereArgs);
- // db.close();
-
- }
-
- //读出并显示最高游戏分数记录
- public int read(){
- SharedPreferences sharedPreferences=context.getSharedPreferences(FileName,Context.MODE_PRIVATE);
- mostscore=sharedPreferences.getInt("score",0);
- return mostscore;
- }
-
-
-
- /**
- * 存储静音开关是否选中信息
- * @param flag
- */
- public void saveFlag(boolean flag) {
- SharedPreferences sp = context.getSharedPreferences(FileNameVolume, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sp.edit();
- if(flag) editor.putInt("state",1);//选中存1
- else editor.putInt("state",0);
- editor.apply();//文件存储结束
-
- }
-
- /**
- * 读出静音开关状态
- * @return
- */
- public int readVolumeFlag(){
- SharedPreferences sharedPreferences=context.getSharedPreferences(FileNameVolume,Context.MODE_PRIVATE);
- int state=sharedPreferences.getInt("state",1);//默认1
- return state;
- }
- }
-
- SoundPlay.java
- package com.example.android_snake;
-
- import android.content.Context;
- import android.media.AudioManager;
- import android.media.SoundPool;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- import java.util.HashMap;
-
- /**
- * 贪吃蛇button/win/fail音效工具类
- */
- public class SoundPlay extends AppCompatActivity {
-
- static SoundPool sp;//声明SoundPool的引用
- static HashMap<Integer, Integer> hm;//声明HashMap来存放声音文件
- static int currStaeamId;//当前正播放的streamId
-
- public void initSoundPool() {//初始化声音池
- sp = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);//创建SoundPool对象
- hm = new HashMap<Integer, Integer>();//创建HashMap对象
- //加载声音文件,并且设置为1号 2号 3号声音放入hm中
- hm.put(1, sp.load(this, R.raw.button0, 1));
- hm.put(2, sp.load(this, R.raw.win, 1));
- hm.put(3, sp.load(this, R.raw.fail, 1));
- hm.put(4, sp.load(this, R.raw.applause, 1));
- }
-
- public void playSound(int sound, int loop) {//获取AudioManager引用
- AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
- //获取当前音量
- float streamVolumeCurrent = am.getStreamVolume(AudioManager.STREAM_MUSIC);
- //获取系统最大音量
- float streamVolumeMax = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
- //计算得到播放音量
- float volume = streamVolumeCurrent / streamVolumeMax;
- //调用SoundPool的play方法来播放声音文件
- currStaeamId = sp.play(hm.get(sound), volume, volume, 1, loop, 1.0f);
- }
-
-
- }
-
- StartActivity.java
- package com.example.android_snake;
-
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.Handler;
- import android.view.Window;
- import android.view.WindowManager;
-
-
- public class StartActivity extends Activity {
- private final int SPLASH_DISPLAY_LENGHT = 3000; //延迟3秒
-
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- //隐藏标题栏以及状态栏
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_beginning);
-
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- Intent intent = new Intent(StartActivity.this, LoginActivity.class);
- StartActivity.this.startActivity(intent);
- StartActivity.this.finish();
- }
- }, SPLASH_DISPLAY_LENGHT);
- }
-
- // private Handler handler = new Handler() {
- // @Override
- // public void handleMessage(Message msg) {
- // super.handleMessage(msg);
- // }
- // };
-
- /**
- * 跳转至选择界面
- */
- public void getHome(){
- Intent intent = new Intent(StartActivity.this, ChooseActivity.class);
- startActivity(intent);
- finish();
- }
-
- }
-
- User.java
- package com.example.android_snake;
-
- import java.io.Serializable;
-
- public class User implements Serializable {
- private int id;
- private String username;
- private String password;
- private int remarks;
-
- public User(){
- super();
- }
- public User(String username,String password,int remarks){
- super();
- this.username = username;
- this.password = password;
- this.remarks = remarks;
- }
- public int getId(){
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername(){
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword(){
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public int getRemarks(){
- return remarks;
- }
-
- public void setRemarks(int remarks) {
- this.remarks = remarks;
- }
-
- /**
- * 描述用户信息
- * @return
- */
- public String desString(){
- return "User [id="+id+",username=" + username +",password="
- +password+",remarks="+remarks+"]";
- }
- }
-
- UserService.java
- package com.example.android_snake;
-
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
-
- /**
- * 本类用于用户注册登录/更新数据库user表中最高分数功能的实现
- */
- public class UserService {
- private MyDatabaseHelper dbHelper;
- public UserService(Context context){
- dbHelper = new MyDatabaseHelper(context);
- }
-
- public boolean login(String username,String password){
- SQLiteDatabase sdb = dbHelper.getReadableDatabase();
- String sql = "select * from user where username=? and password=?";
- Cursor cursor = sdb.rawQuery(sql, new String[]{username,password});
- if(cursor.moveToFirst()==true){
- cursor.close();
- return true;
- }
- return false;
- }
-
- public boolean register(User user){
- SQLiteDatabase sdb = dbHelper.getReadableDatabase();
- String sql = "insert into user(username,password,remarks) values(?,?,?)";
- Object[] obj = {user.getUsername(),user.getPassword(),user.getRemarks()};
- sdb.execSQL(sql,obj);
- return true;
-
- }
-
- public void updateRemarks(String username,int remarks){
- SQLiteDatabase sdb = dbHelper.getReadableDatabase();
- String remarksS = String.valueOf(remarks);
- String updateSql = "update user set Remarks=? where userName=?";
- sdb.execSQL(updateSql, new String[]{remarksS, username});
-
- }
-
- }
- activity_beginning.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"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:background="@drawable/cover_02">
-
- <ImageView
- android:id="@+id/imageView6"
- android:layout_width="match_parent"
- android:layout_height="575dp"
- app:srcCompat="@drawable/cover_02" />
-
- <!-- <TextView-->
- <!-- android:id="@+id/textView2"-->
- <!-- android:layout_width="match_parent"-->
- <!-- android:layout_height="200dp"-->
- <!-- android:layout_weight="1"-->
- <!-- android:text="Play games to please yourself!"-->
- <!-- android:textColor="@color/black"-->
- <!-- android:textSize="25dp" />-->
-
- <TextView
- android:id="@+id/txt_1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="70dp"
- android:text="Game player ⭐⭐⭐小游戏"
- android:textSize="30sp"
- android:textColor="@color/white"/>
-
-
- </LinearLayout>
- Activity_finalwin.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ImageView
- android:id="@+id/imageView"
- android:layout_width="252dp"
- android:layout_height="445dp"
- android:layout_centerInParent="true"
- android:layout_weight="1"
- app:srcCompat="@drawable/finalwin" />
-
- <TextView
- android:id="@+id/textView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/finalwin"
- android:layout_centerHorizontal="true"
- android:textColor="@color/purple_500"
- android:textSize="22sp" />
- </RelativeLayout>
- activity_login.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:id="@+id/top_login"
- android:layout_width="match_parent"
- android:layout_height="180dp"
- android:background="@drawable/pic_top2" />
-
- <TextView
- android:id="@+id/login_tip"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="70dp"
- android:text="@string/welcome"
- android:textSize="25sp" />
-
- <EditText
- android:id="@+id/username_login"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/top_login"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="20dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/input_line1"
- android:hint="@string/login_tip1"
- android:inputType="text"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:textSize="18sp"
- tools:ignore="autofill" />
-
- <EditText
- android:id="@+id/password_login"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/username_login"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="10dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/input_line1"
- android:hint="@string/login_tip2"
- android:inputType="textPassword"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:textSize="18sp"
- tools:ignore="autofill" />
-
- <Button
- android:id="@+id/bt_login"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/password_login"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="15dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/start_button"
- android:text="@string/login_tip3"
- android:textColor="@color/white" />
-
- <RadioButton
- android:id="@+id/rbt_login"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/bt_login"
- android:layout_marginStart="25dp"
- android:layout_marginLeft="25dp"
- android:layout_marginTop="10dp"
- android:checked="false"
- android:text="@string/login_tip5"
- android:textSize="14sp" />
-
- <Button
- android:id="@+id/bt_goRegister"
- android:layout_width="match_parent"
- android:layout_height="18dp"
- android:layout_below="@id/rbt_login"
- android:layout_marginLeft="145dp"
- android:layout_marginTop="19dp"
- android:layout_marginRight="35dp"
- android:background="@null"
- android:text="@string/login_tip6"
- android:textColor="@color/grey"
- android:textSize="14sp" />
-
- <TextView
- android:id="@+id/txt_loginother"
- android:layout_width="match_parent"
- android:layout_height="25dp"
- android:layout_below="@id/rbt_login"
- android:layout_centerVertical="true"
- android:layout_gravity="center"
- android:layout_marginLeft="65dp"
- android:layout_marginTop="145dp"
- android:layout_marginRight="65dp"
- android:gravity="center"
- android:text="@string/login_tip4"
- android:textSize="14sp" />
-
- <Button
- android:id="@+id/bt_wechat"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:layout_below="@id/txt_loginother"
- android:layout_marginStart="65dp"
- android:layout_marginTop="30dp"
- android:background="@drawable/logo_login4"
- android:layout_marginLeft="65dp" />
-
- <Button
- android:id="@+id/bt_QQ"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:layout_below="@id/txt_loginother"
- android:layout_marginStart="55dp"
- android:layout_marginLeft="55dp"
- android:layout_marginTop="30dp"
- android:layout_toEndOf="@id/bt_wechat"
- android:layout_toRightOf="@id/bt_wechat"
- android:background="@drawable/logo_login5" />
- <Button
- android:id="@+id/bt_weibo"
- android:layout_width="55dp"
- android:layout_height="55dp"
- android:layout_below="@id/txt_loginother"
- android:layout_toEndOf="@id/bt_QQ"
- android:layout_marginStart="55dp"
- android:layout_marginTop="30dp"
- android:background="@drawable/logo_login1"
- android:layout_toRightOf="@id/bt_QQ"
- android:layout_marginLeft="55dp" />
-
-
-
- </RelativeLayout>
-
- activity_main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/main_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/white"
- android:orientation="vertical"
- tools:context="com.example.android_snake.MainActivity">
-
- <FrameLayout
- android:id="@+id/framelayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignBottom="@id/RelativeLayout"
- android:layout_marginBottom="145dp"
- android:background="@color/pink_1">
-
- <TextView
- android:id="@+id/prompt"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="点击按钮,开始游戏!"
- android:textColor="@color/red_1"
- android:textSize="25sp" />
-
- <TextView
- android:id="@+id/Score"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="当前分数"
- android:textColor="#000000"
- android:textSize="20sp" />
-
- <TextView
- android:id="@+id/MostScore"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="200dp"
- android:text="@string/MOSTSCORE"
- android:textColor="#000000"
- android:textSize="20sp" />
-
- <Button
- android:id="@+id/Volume"
- android:layout_width="30dp"
- android:layout_height="30dp"
- android:layout_marginLeft="350dp"
- android:background="@drawable/volumeon" />
-
- <RelativeLayout
- android:id="@+id/addBling"
- android:layout_width="110dp"
- android:layout_height="60dp"
- android:layout_marginTop="70dp"
- />
-
-
- </FrameLayout>
-
- <RelativeLayout
- android:id="@+id/RelativeLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true">
-
- <Button
- android:id="@+id/isstar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/Up"
- android:layout_centerHorizontal="true"
- android:background="@drawable/downbutton"
- android:text="@string/star" />
-
- <Button
- android:id="@+id/Up"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_gravity="center"
- android:background="@drawable/upbutton"
- android:text="@string/UP" />
-
- <Button
- android:id="@+id/Left"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/Up"
- android:layout_toStartOf="@id/Up"
- android:layout_toLeftOf="@id/Up"
- android:background="@drawable/leftbutton"
- android:text="@string/LEFT" />
-
- <Button
- android:id="@+id/Down"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/Left"
- android:layout_centerHorizontal="true"
- android:background="@drawable/upbutton"
- android:text="@string/DOWN" />
-
- <Button
- android:id="@+id/Right"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/Up"
- android:layout_toEndOf="@id/Up"
- android:layout_toRightOf="@id/Up"
- android:background="@drawable/rightbutton"
- android:text="@string/RIGHT" />
-
- </RelativeLayout>
-
-
- </RelativeLayout>
- activity_register.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:id="@+id/top_register"
- android:layout_width="match_parent"
- android:layout_height="180dp"
- android:background="@drawable/pic_top2" />
-
- <TextView
- android:id="@+id/register_tip"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="70dp"
- android:text="@string/welcomeregister"
- android:textSize="25sp" />
-
- <EditText
- android:id="@+id/username_register"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/top_register"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="20dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/input_line1"
- android:hint="@string/login_tip1"
- android:inputType="text"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:textSize="18sp"
- tools:ignore="autofill" />
-
- <EditText
- android:id="@+id/password_register"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/username_register"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="10dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/input_line1"
- android:hint="@string/register_tip1"
- android:inputType="textPassword"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:textSize="18sp"
- tools:ignore="autofill" />
-
- <Button
- android:id="@+id/registerButton"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:layout_below="@id/password_register"
- android:layout_marginLeft="35dp"
- android:layout_marginTop="15dp"
- android:layout_marginRight="35dp"
- android:background="@drawable/start_button"
- android:text="@string/register_tip5"
- android:textColor="@color/white" />
-
-
- <!-- <RadioButton-->
- <!-- android:id="@+id/rbt_register"-->
- <!-- android:layout_width="wrap_content"-->
- <!-- android:layout_height="wrap_content"-->
- <!-- android:layout_below="@id/registerButton"-->
- <!-- android:layout_marginStart="25dp"-->
- <!-- android:layout_marginLeft="25dp"-->
- <!-- android:layout_marginTop="10dp"-->
- <!-- android:checked="false"-->
- <!-- android:text="@string/login_tip5"-->
- <!-- android:textSize="14sp" />-->
-
-
- <TextView
- android:id="@+id/txt_2"
- android:layout_width="match_parent"
- android:layout_height="25dp"
- android:layout_below="@id/registerButton"
- android:layout_centerVertical="true"
- android:layout_gravity="center"
- android:layout_marginLeft="65dp"
- android:layout_marginTop="145dp"
- android:layout_marginRight="65dp"
- android:gravity="center"
- android:text="@string/login_tip4"
- android:textSize="14sp" />
-
- <Button
- android:id="@+id/bt_wechat"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:layout_below="@id/txt_2"
- android:layout_marginStart="65dp"
- android:layout_marginLeft="65dp"
- android:layout_marginTop="30dp"
- android:background="@drawable/logo_login4" />
-
- <Button
- android:id="@+id/bt_QQ"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:layout_below="@id/txt_2"
- android:layout_marginStart="55dp"
- android:layout_marginLeft="55dp"
- android:layout_marginTop="30dp"
- android:layout_toEndOf="@id/bt_wechat"
- android:layout_toRightOf="@id/bt_wechat"
- android:background="@drawable/logo_login5" />
- <Button
- android:id="@+id/bt_weibo"
- android:layout_width="55dp"
- android:layout_height="55dp"
- android:layout_below="@id/txt_2"
- android:layout_toEndOf="@id/bt_QQ"
- android:layout_marginStart="55dp"
- android:layout_marginTop="30dp"
- android:background="@drawable/logo_login1"
- android:layout_toRightOf="@id/bt_QQ"
- android:layout_marginLeft="55dp" />
-
-
-
- </RelativeLayout>
-
- activity_start_view.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"
- tools:context="com.example.android_snake.ChooseActivity"
- android:orientation="vertical"
- android:background="@color/white"
- >
- <TextView
- android:id="@+id/top_1"
- android:layout_width="match_parent"
- android:layout_height="180dp"
- android:background="@drawable/pic_top2" />
-
- <TextView
- android:id="@+id/txt_1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="70dp"
- android:text="Game player\n贪吃蛇小游戏"
- android:textSize="40sp" />
-
- <Button
- android:id="@+id/star_game"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="50dp"
- android:layout_marginTop="100dp"
- android:layout_marginRight="50dp"
- android:background="@drawable/start_button"
- android:text="@string/stargame" />
-
- <Button
- android:id="@+id/MostBUtton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="50dp"
- android:layout_marginTop="10dp"
- android:layout_marginRight="50dp"
- android:background="@drawable/start_button"
- android:text="@string/historyscore" />
-
- <Button
- android:id="@+id/BackButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/back"
- android:layout_marginLeft="50dp"
- android:layout_marginRight="50dp"
- android:layout_marginTop="10dp"
- android:background="@drawable/start_button"/>
-
- </LinearLayout>
-
本次课程设计目的在于使用java语言设计一款手机贪吃蛇小游戏,为了达到最好的用户体验效果,我学习使用Android Studio进行项目开发,在项目开发过程中,学到了很多新的知识与技能,切实体会到项目开发的完整流程,并在此过程中不断增加需求、完善功能、优化结构,从最开始的游戏逻辑到用户界面一步步进行完善与修改,从数据库连接、文件操作到apk打包等种种操作,见证自己的第一个apk诞生的全过程,获得感颇丰。
下面例举一些项目开发中遇到的问题及解决方案:
一些资源文件引用、调用错误:如引入png图片文件时文件路径不能有中文,value中的颜色 定义文件colors.xml中定义了一个格式不支持的颜色;音频文件引用时的后缀名称问题,提示编码错误,改为.text后缀类型即可正常使用
一些代码逻辑需要学习巩固:如贪吃蛇游戏中的多线程处理、Android Studio中的SQLite连接及文件操作、布局xml文件的代码编写方法、布局与构件种类、SM4国密密码算法等。
一些小功能实现需要去学习:隐藏标题栏、隐藏手机状态栏、开机动画停留3秒、各个界面之间的自动跳转、获取手机屏幕宽度、音频导入与播放、APK打包、APK属性信息设置。
一些小bug需要一个个改正:如贪吃蛇初始化时头的方向若向左,初始运动方向设置为向右便会出场阵亡;食物的图标尺寸大于运动单元,则会出现小蛇看上去吃到食物实际上却并没有到达那个坐标;小蛇的初始位置太偏不容易调整初始进入游戏的状态;由于未在AndroidManifest.xml文件中注册界面的Activity,导致界面跳转时出现软件闪退情况;游戏菜单界面的三个按钮都加音效会导致软件闪退等等……
解决各种问题的过程正是自我提高的过程,弥足珍贵。
开发过程中遇到的这样各种各样的小问题还有很多,现已难以尽数列出……
GreedySnake这个程序虽然已经尽力去完善与改进了,但仍然存在一些小问题,如游戏界面中背景音乐播放使用了MediaPlayer类,按钮音效等短音频处理使用了SoundPool,而MediaPlayer仅支持同时播放一个音频,故播放背景音乐时按钮音效并不能体现……
错误和bug不让人感觉快乐,但程序员的乐趣就在于解决一个又一个报错,修改一个又一个bug。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。