} else {

return -1;

}

}

}

2. Cell类的设计:Cell用来表示游戏中的小格子

  • Cell表示游戏中移动的小格子,格子的颜色、显示数字等属性都在对象中进行设置,Cell类如下:

public class Cell extends FrameLayout {

//显示数字的TextView

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);

// 不同难度设置不同字体大小

switch (Config.GRIDColumnCount) {

case 4:

cellShowText.setTextSize(36);

break;

case 5:

cellShowText.setTextSize(28);

break;

case 6:

cellShowText.setTextSize(20);

break;

default:

cellShowText.setTextSize(36);

break;

}

cellShowText.setGravity(Gravity.CENTER);

// 抗锯齿

cellShowText.getPaint().setAntiAlias(true);

// 粗体

cellShowText.getPaint().setFakeBoldText(true);

// 颜色

cellShowText.setTextColor(ContextCompat.getColor(context, R.color.colorWhite));

// 填充整个父容器

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. 将cell添加到GameView中:

  • 游戏初始化需要根据难度向GameView添加所有的Cell

/**

  • 初始化向布局中添加空格子

  • @param cellWidth 格子宽

  • @param cellHeight 格子高

*/

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;

}

}

}

  • 所有格子需要获取数字,最初全部设为0,即所有格子为空

//获取空格子

private void getEmptyCell() {

// 清空

emptyCellPoint.clear();

// 遍历所有格子,记录所有空格子的坐标位置

for (int i = 0; i < gridColumnCount; i++) {

for (int j = 0; j < gridColumnCount; j++) {

// 空格子

if (cells[i][j].getDigital() <= 0) {

emptyCellPoint.add(new Point(i, j));

}

}

}

}

  • 以4:6的概率随机获取一个数字2或4

public void addDigital(boolean isCheat) {

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 showChangeModeDialog() {

String subject = “”;

if (Config.CurrentGameMode == Constant.MODE_CLASSIC) {

subject = “无限模式”;

} else if (Config.CurrentGameMode == Constant.MODE_INFINITE) {

subject = “经典模式”;

}

CommonDialog dialog = new CommonDialog(this, R.style.CustomDialog);

dialog.setCancelable(true);

dialog.setTitle(getResources().getString(R.string.tip))

.setMessage(“是否要切换到” + subject)

.setOnPositiveClickedListener("", v -> {

if (Config.CurrentGameMode == Constant.MODE_CLASSIC) {

Toast.makeText(GameActivity.this, “已进入无限模式”, Toast.LENGTH_SHORT).show();

enterInfiniteMode();

}
else {

Toast.makeText(GameActivity.this, “已进入经典模式”, Toast.LENGTH_SHORT).show();

enterClassicsMode();

}

dialog.cancel();

})

.setOnNegativeClickListener("", v -> dialog.cancel())

.show();

}

// 进入无限模式

private void enterInfiniteMode() {

Config.haveCheat = false;

Config.CurrentGameMode = Constant.MODE_INFINITE;

// 保存游戏模式

ConfigManager.putCurrentGameMode(this, Constant.MODE_INFINITE);

titleDescribe.setText(getResources().getString(R.string.game_mode_infinite));

bestScores.setText(String.valueOf(ConfigManager.getBestScoreWithinInfinite(this)));

bestScoresRank.setText(getResources().getText(R.string.tv_best_score_infinite));

currentScores.setText(String.valueOf(ConfigManager.getCurrentScoreWithinInfinite(this)));

modeDescribe.setText(getResources().getString(R.string.tv_describe_infinite));

setTextStyle(titleDescribe);

gameView.initView(Constant.MODE_INFINITE);

}

//进入经典模式

private void enterClassicsMode() {

Config.haveCheat = false;

Config.CurrentGameMode = Constant.MODE_CLASSIC;

// 保存游戏模式

ConfigManager.putCurrentGameMode(this, Constant.MODE_CLASSIC);

titleDescribe.setText(getResources().getString(R.string.game_mode_classics));

// 读取到历史最高分

bestScores.setText(String.valueOf(Config.BestScore));

bestScoresRank.setText(getString(R.string.best_score_rank, Config.GRIDColumnCount));

currentScores.setText(String.valueOf(ConfigManager.getCurrentScore(this)));

modeDescribe.setText(getResources().getString(R.string.tv_describe));

setTextStyle(titleDescribe);

gameView.initView(Constant.MODE_CLASSIC);

}

5. 记录当前分数及历史最高分数

//记录得分

private void recordScore(int score) {

currentScores.setText(String.valueOf(score));

// 当前分数大于最高分

if (Config.CurrentGameMode == Constant.MODE_CLASSIC) {

if (score > ConfigManager.getBestScore(this)) {

updateBestScore(score);

}

} else if (Config.CurrentGameMode == Constant.MODE_INFINITE) {

if (score > ConfigManager.getBestScoreWithinInfinite(this)) {

updateBestScore(score);

}

}

}

//更新历史最高分

private void updateBestScore(int newScore) {

bestScores.setText(String.valueOf(newScore));

if (Config.CurrentGameMode == Constant.MODE_CLASSIC) {

Config.BestScore = newScore;

ConfigManager.putBestScore(this, newScore);

} else if (Config.CurrentGameMode == Constant.MODE_INFINITE) {

Config.BestScoreWithinInfinite = newScore;

ConfigManager.putBestScoreWithinInfinite(this, newScore);

}

}

6. 判断游戏是否结束

  • 每次获取数字时需要判断游戏是否结束

private void judgeOverOrAccomplish() {

// 判断游戏结束的标识

boolean isOver = true;

// 判断游戏是否结束:格子都不为空且相邻的格子数字不同

over:

for (int i = 0; i < gridColumnCount; i++) {

for (int j = 0; j < gridColumnCount; j++) {

// 有空格子,游戏还可以继续

if (cells[i][j].getDigital() == 0) {

isOver = false;

break over;

}

// 判断左右上下有没有相同的

if (j < gridColumnCount - 1) {

if (cells[i][j].getDigital() == cells[i][j + 1].getDigital()) {

isOver = false;

break over;

}

}

if (i < gridColumnCount - 1) {

if (cells[i][j].getDigital() == cells[i + 1][j].getDigital()) {

isOver = false;

break over;

}

}

}

}

// 游戏结束,弹出提示框

if (isOver) {

canSwipe = false;

sendGameOverMsg(ACTION_LOSE);

}

// 经典模式下才判赢

if (gameMode == 0) {

// 判断是否达成游戏目标

for (int i = 0; i < gridColumnCount; i++) {

for (int j = 0; j < gridColumnCount; j++) {

// 有一个格子数字到达2048则视为达成目标

if (cells[i][j].getDigital() == 2048) {

canSwipe = false;

int currentTime = ConfigManager.getGoalTime(getContext()) + 1;

ConfigManager.putGoalTime(getContext(), currentTime);

Config.GetGoalTime = currentTime;

sendGameOverMsg(ACTION_WIN);

}

}

}

}

}

5. 总结


  • 涉及到的知识点汇总:

  • Sqlite

  • SharedPreferences

  • GestureOverlayView

  • Animation

  • Spannable

  • Handler

  • BroadcastReceiver

  • Timer

  • 自定义View

== 0) {

// 判断是否达成游戏目标

for (int i = 0; i < gridColumnCount; i++) {

for (int j = 0; j < gridColumnCount; j++) {

// 有一个格子数字到达2048则视为达成目标

if (cells[i][j].getDigital() == 2048) {

canSwipe = false;

int currentTime = ConfigManager.getGoalTime(getContext()) + 1;

ConfigManager.putGoalTime(getContext(), currentTime);

Config.GetGoalTime = currentTime;

sendGameOverMsg(ACTION_WIN);

}

}

}

}

}

5. 总结


  • 涉及到的知识点汇总:

  • Sqlite

  • SharedPreferences

  • GestureOverlayView

  • Animation

  • Spannable

  • Handler

  • BroadcastReceiver

  • Timer

  • 自定义View

Android小项目--2048小游戏,flutter人脸识别插件相关推荐

  1. python小项目——2048小游戏(详解)

    2048游戏 原版游戏地址 第一部分 导入所需要的库 第二部分 确认游戏键位设置,并和对应的操作关联 第三部分 获取用户输入的值,并直到有效键位 第四部分 对矩阵的应用,减少代码量 第五部分 创建棋盘 ...

  2. QT小项目---2048小游戏

    目录 效果展示 游戏简介 游戏详情 操作指南 操作技巧 代码实现 QWidget.h Widget.cpp GameWidget.h GameWidget.cpp 总结 效果展示 游戏简介 游戏详情 ...

  3. java课设小迷宫含代码_Java小项目之迷宫游戏的实现方法

    项目要求: 一个网格迷宫由n行n列的单元格组成,每个大院个要么是空地(用0表示),要么是障碍物(用1表示),你的任务是找一条从起点到终点的移动序列,其中只能上下左右移动到相邻单元格.任何时候都不能在有 ...

  4. java 迷宫游戏_Java小项目之迷宫游戏的实现方法

    项目要求: 一个网格迷宫由n行n列的单元格组成,每个大院个要么是空地(用0表示),要么是障碍物(用1表示),你的任务是找一条从起点到终点的移动序列,其中只能上下左右移动到相邻单元格.任何时候都不能在有 ...

  5. c小项目,小码资金管理工具

    纯c小项目,小码资金管理工具moneykeeper 作者:流浪舟 公众号:小码之光 你小码哥回来啦!最近闷得慌,又在学java(自学,想走这条路,哎,一个人找到所爱的真的很难,说不定哪天真的挂了,就来 ...

  6. 在uni-app的app项目中使用live-pusher实现人脸识别

    在uni-app的app项目中使用live-pusher实现人脸识别 前言 一.环境 二.使用步骤 三.permission.js源代码 四.face.vue源代码 五.代码效果 总结 前言 在uni ...

  7. 【项目实训】基于人脸识别的课堂签到管理系统(python+qt5+sqlite3+百度智能云)

    [项目实训]基于人脸识别的课堂签到管理系统(python+qt5+sqlite3+百度智能云) 一.环境介绍 二.签到功能 2.1 启动签到 2.2 结束签到 三.用户组操作 3.1 添加用户组 3. ...

  8. jQuery 人脸识别插件,支持图片和视频

    jQuery Face Detection 是一款人脸检测插件,能够检测到图片,视频和画布中的人脸坐标.它跟踪人脸并输出人脸模型的坐标位置为一个数组.我们相信,面部识别技术能够给我们的 Web 应用带 ...

  9. 前端项目2048小游戏

    第一章 2048游戏介绍 1.1 项目介绍 相信大家都玩过2048这个游戏,这次我们就一步步地来完成2048的开发,这个项目它需要用到html css和js的知识. 需求分析: 1 游戏是一个4x4的 ...

  10. 练手的70个超火python小项目,小编建议收藏哦,送你们玩

    相信正在学Python你一定为了没有练手项目而发愁,小编精心准备出了70个Python的练手项目,相信能够喂饱大伙儿吧!哈哈! 这里面的项目都很有代表性,不只是可以用来练手,而且在以后的工作中都有很实 ...

最新文章

  1. python将一个json字典转换为一个python对象
  2. 参数 ByVal 和 ByRef 区别
  3. Java程序员必须知道的Java10特性
  4. windows文件保护_文件通通用它加密,安全等级提高一个档次
  5. 玩转Google开源C++单元测试框架Google Test系列(gtest)之八 - 打造自己的单元测试框架
  6. Visual Studio listView控件绑定SQL Server数据库并动态显示数据,调整列宽
  7. 个人.NET ORM全攻略,提供最新版本下载
  8. 游戏开发之STL库的基础使用(string、vector、list、map、unordered_map)(C++基础)
  9. 开源项目smartImageView
  10. 详细了解 clientWidth、clientHeight、clientLeft、clientTop 以及几个常用的场景
  11. 【OOP编程思想小感悟】
  12. 69. Sqrt(x)
  13. Spring Cloud
  14. 洛谷3678:简单的数学题(画柿子+杜教筛)
  15. 吃货在东京 -- 记那段吃不饱的日子 之四 台场的日本拉面
  16. JAVA实习生面试问题
  17. IIS网站——SSL安全加密机制
  18. mysql中高阶玩法系列(八)
  19. 一般早餐店卖不了的包子、馒头是怎么处理的?
  20. python测试开发django(8)--django连接mysql

热门文章

  1. GitHub使用教程-官网指南
  2. sscom串口调试助手
  3. 使用SAP HANA ODBC驱动程序进行连接
  4. vs 2017 linux版本,vs2017 linux版
  5. 研磨设计模式之工厂方法模式-2
  6. 电子海图领域一些概念名词的梳理
  7. 经典DOS游戏皇帝攻略(曾经的回忆)
  8. Winform开发框架的重要特性总结
  9. 计算机基础.办公自动化期末试卷复习必看
  10. AndroidStudio使用gradle出现Could not download... 或unable to resolve dependency for...