Android期末项目2048小游戏。
2048属于益智类小游戏,它做到了娱乐性、趣味性、教育性相统一。益智类的游戏即是需要去开动大脑去思考从而获得游戏的胜利。简单的益智类游戏可以使玩家在娱乐中不断的开发大脑。这样一来就实现了在娱乐中学习。每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方随机出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。
完成2048基本功能,加入动画效果,加入声音效果,能够记录并显示最高分,能够自动保存游戏进度。
1.基本的2048游戏功能
2.记录最高分功能
3.记录完成2048次数功能
4.声音设置功能
5.自动保存游戏进度功能
6.结束游戏时判定是否是新纪录
1.初始化面板
// An highlighted block
public void initView() {
removeAllViews();
canSwipe = true;
getGoal=false;
gridColumnCount=4;
cells = new Cell[gridColumnCount][gridColumnCount];
// 设置界面大小
setColumnCount(gridColumnCount);
// 获取格子的宽
int cellWidth = getCellSize();
// 获取格子的高
int cellHeight = getCellSize();
addCell(cellWidth, cellHeight);
startGame();
setOnTouchListener((v, event) -> {
// 通知父控件不要拦截此控件的onTouch事件
v.getParent().requestDisallowInterceptTouchEvent(true);
if (canSwipe) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setX = event.getX();
setY = event.getY();
break;
case MotionEvent.ACTION_UP:
offsetX = event.getX() - setX;
offsetY = event.getY() - setY;
// 判断滑动方向
int orientation = getOrientation(offsetX, offsetY);
switch (orientation) {
case 0:
// 向右滑动
swipeRight();
break;
case 1:
// 向左滑动
swipeLeft();
break;
case 2:
// 向下滑动
swipeDown();
break;
case 3:
// 向上滑动
swipeUp();
break;
default:
break;
}
default:
break;
}
}
return true;
});
}
2.Cell类实现,Cell表示游戏中移动的数字快,块的字体、颜色、等属性都在对象中进行设置,Cell类如下:
package com.example.game2048.view;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import android.graphics.Typeface;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.example.game2048.R;
public class Cell extends FrameLayout {
private TextView cellShowText;
private int digital;
public Cell(Context context) {
super(context);
}
public Cell(@NonNull Context context, int leftMargin, int topMargin, int bottomMargin) {
super(context);
init(context, leftMargin, topMargin, bottomMargin);
}
private void init(@NonNull Context context, int leftMargin, int topMargin, int bottomMargin) {
cellShowText = new TextView(context);
cellShowText.setTextSize(40);
cellShowText.setGravity(Gravity.CENTER);
// 抗锯齿
cellShowText.getPaint().setAntiAlias(true);
// 粗体
cellShowText.getPaint().setFakeBoldText(true);
// 字体
cellShowText.setTypeface(Typeface.MONOSPACE);
// 颜色
cellShowText.setTextColor(ContextCompat.getColor(context, R.color.colorTextDark));
// 填充整个父容器
LayoutParams params = new LayoutParams(-1, -1);
params.setMargins(leftMargin, topMargin, 0, bottomMargin);
addView(cellShowText, params);
setDigital(0);
}
//获取卡片
public TextView getItemCell() {
return cellShowText;
}
//获取数字
public int getDigital() {
return digital;
}
//设置数字
public void setDigital(int digital) {
this.digital = digital;
cellShowText.setBackgroundResource(getBackgroundResource(digital));
if (digital <= 0) {
cellShowText.setText("");
} else {
cellShowText.setText(String.valueOf(digital));
}
}
//设置数字背景
private int getBackgroundResource(int number) {
switch (number) {
case 0:
return R.drawable.bg_cell_0;
case 2:
return R.drawable.bg_cell_2;
case 4:
return R.drawable.bg_cell_4;
case 8:
return R.drawable.bg_cell_8;
case 16:
return R.drawable.bg_cell_16;
case 32:
return R.drawable.bg_cell_32;
case 64:
return R.drawable.bg_cell_64;
case 128:
return R.drawable.bg_cell_128;
case 256:
return R.drawable.bg_cell_256;
case 512:
return R.drawable.bg_cell_512;
case 1024:
return R.drawable.bg_cell_1024;
case 2048:
return R.drawable.bg_cell_2048;
default:
return R.drawable.bg_cell_default;
}
}
}
3、在空白处随机添加数字
public void addDigital() {
getEmptyCell();
if (emptyCellPoint.size() > 0) {
// 随机取出一个空格子的坐标位置
Point point = emptyCellPoint.get((int) (Math.random() * emptyCellPoint.size()));
cells[point.x][point.y].setDigital(Math.random() > 0.4 ? 2 : 4);
// 设置动画
setAppearAnim(cells[point.x][point.y]);
}
}
4、向面板中加入数字块
private void addCell(int cellWidth, int cellHeight) {
Cell cell;
for (int i = 0; i < gridColumnCount; i++) {
for (int j = 0; j < gridColumnCount; j++) {
if (i == gridColumnCount - 1) {
// 为最底下的格子加上bottomMargin
cell = new Cell(getContext(), 16, 16, 16);
} else {
cell = new Cell(getContext(), 16, 16, 0);
}
cell.setDigital(0);
addView(cell, cellWidth, cellHeight);
cells[i][j] = cell;
}
}
}
5、滑动逻辑实现,滑动时,判断每一行(列)的数据,0代表空格子,将非0数字存在一个list中,然后判断若当前数字与前一个数字相同,合并,并将此list作为这行(列)的新数据,再按滑动的方向向这行(列)中存放list中的数字,以上滑为例:
private void swipeUp() {
// 判断是否需要添加数字
boolean needAddDigital = false;
for (int i = 0; i < gridColumnCount; i++) {
for (int j = 0; j < gridColumnCount; j++) {
// 获取当前位置数字
int currentDigital = cells[j][i].getDigital();
someData.add(currentDigital);
if (currentDigital != 0) {
// 记录数字
if (recordPreviousDigital == -1) {
recordPreviousDigital = currentDigital;
} else {
// 记录的之前的数字和当前数字不同
if (recordPreviousDigital != currentDigital) {
// 加入记录的数字
dataAfterSwipe.add(recordPreviousDigital);
recordPreviousDigital = currentDigital;
} else {// 记录的之前的数字和当前的数字相同
// 加入*2
dataAfterSwipe.add(recordPreviousDigital * 2);
// 记录得分
recordScore(recordPreviousDigital * 2);
// 重置记录数字
recordPreviousDigital = -1;
}
}
}
}
if (recordPreviousDigital != -1) {
dataAfterSwipe.add(recordPreviousDigital);
}
// 补0
for (int p = dataAfterSwipe.size(); p < gridColumnCount; p++) {
dataAfterSwipe.add(0);
}
// 若原始数据和移动后的数据不同,视为界面发生改变
if (!someData.equals(dataAfterSwipe)) {
needAddDigital = true;
}
someData.clear();
// 重新设置格子数据
for (int k = 0; k < dataAfterSwipe.size(); k++) {
cells[k][i].setDigital(dataAfterSwipe.get(k));
}
// 重置数据
recordPreviousDigital = -1;
dataAfterSwipe.clear();
}
if (needAddDigital) {
// 添加一个随机数字(2或4)
addDigital();
playSound();
}
judgeOverOrAccomplish();
}
基本完成了2048游戏的所有功能,但界面比较简陋,没有做出块滑动、碰撞的动画。在此过程中也学到了许多新东西,如SharedPreferences, GestureOverlayView, BoradcastReceiver等等。
此项目有待改进的地方:
1.加入数字快滑动和碰撞的动画效果。
2.增加选择阶数功能。即总方块数可由用户自定义4x4或5x5、6x6等。
3.增加一些游戏工具,如消除指定数字块,指定方块换位等,工具可通过完成指定分数获得。
项目源码:链接:https://pan.baidu.com/s/1TwBOzI5MDBPx6LtgzZxYmg 提取码:9pn6