我也来开发2048之终极奥义
作者:互联网
本次教程跟之前隔了不少时间哈,有点忘记了的建议先看看前面的熟悉下,今天我准备把这个2048给结束了,拖了这么久。
依照惯例,我们已经把准备工作都做好了。今天这一部分信息量比較大,也是整个游戏的核心所在,所以我准备分功能来讲。最后大家结合源代码来看就不会感觉太吃力了。
1、初始化游戏
初始化的时候,我们要干嘛呢,首先要看配置。配置了几行,然后先画好面板。然后要给在面板上随机生成2个数字Item。这涉及到2个方法,一个是初始化面板,一个是加入随机数字
private void initGameView(int cardSize) {
removeAllViews();
GameItem card;
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
card = new GameItem(getContext(), 0);
addView(card, cardSize, cardSize);
// 初始化GameMatrix所有为0 空格List为所有
gameMatrix[i][j] = card;
blanks.add(new Point(i, j));
}
}
// 加入随机数字
addRandomNum();
addRandomNum();
}
private void addRandomNum() {
getBlanks();
if (blanks.size() > 0) {
int randomNum = (int) (Math.random() * blanks.size());
Point randomPoint = blanks.get(randomNum);
gameMatrix[randomPoint.x][randomPoint.y].setNum(Math.random() > 0.2d ? 2 : 4);
Game.getGameActivity().getAnimationLayer().animcreate(gameMatrix[randomPoint.x][randomPoint.y]);
}
}
在推断生成2、4的时候,我们使用了通常产生范围随机数的方法。同一时候指定2和4的比例在1:4,当然这个大家能够依据须要更改
2、详细參数等初始化
这个比較简单了。直接上代码。大家应该都看得懂
private void initGameMatrix() {
// 初始化矩阵
removeAllViews();
scoreHistory = 0;
Config.Scroe = 0;
Config.GameLines = Config.sp.getInt(Config.KEY_GameLines, 4);
gameLines = Config.GameLines;
gameMatrix = new GameItem[gameLines][gameLines];
gameMatrixHistory = new int[gameLines][gameLines];
calList = new ArrayList<Integer>();
blanks = new ArrayList<Point>();
highScore = Config.sp.getInt(Config.KEY_HighScore, 0);
setColumnCount(gameLines);
setRowCount(gameLines);
setOnTouchListener(this);
// 初始化View參数
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
display.getMetrics(metrics);
Config.ItemSize = metrics.widthPixels / Config.GameLines;
initGameView(Config.ItemSize);
}
这部分不妨结合源代码看比較好,凝视清晰
3、触摸事件
触摸的时候推断4个方向,这个基本也是通用的写法了,不多说了
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
saveHistoryMatrix();
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
endX = (int) event.getX();
endY = (int) event.getY();
judgeDirection(endX - startX, endY - startY);
if (isMoved()) {
addRandomNum();
// 改动显示分数
Game.getGameActivity().setScore(Config.Scroe, 0);
}
int result = checkCompleted();
if (result == 0) {
if (Config.Scroe > highScore) {
Editor editor = Config.sp.edit();
editor.putInt(Config.KEY_HighScore, Config.Scroe);
editor.commit();
}
Toast.makeText(getContext(), "lose", Toast.LENGTH_LONG).show();
Config.Scroe = 0;
} else if (result == 2) {
Toast.makeText(getContext(), "success", Toast.LENGTH_LONG).show();
Config.Scroe = 0;
}
break;
default:
break;
}
return true;
}
当中推断偏移的方法private void judgeDirection(int offsetX, int offsetY) {
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX > 10) {
swipeRight();
} else {
swipeLeft();
}
} else {
if (offsetY > 10) {
swipeDown();
} else {
swipeUp();
}
}
}
以下我们来讲2048的终极奥义了。就是算法的实现,详细的算法在第一篇中已经解说了大概的过程。点我去看。以下我们选一个方向来讲怎样实现
private void swipeLeft() {
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
int currentNum = gameMatrix[i][j].getNum();
if (currentNum != 0) {
if (keyItemNum == -1) {
keyItemNum = currentNum;
} else {
if (keyItemNum == currentNum) {
calList.add(keyItemNum * 2);
Config.Scroe += keyItemNum * 2;
keyItemNum = -1;
} else {
calList.add(keyItemNum);
keyItemNum = currentNum;
}
}
} else {
continue;
}
}
if (keyItemNum != -1) {
calList.add(keyItemNum);
}
// 改变Item值
for (int j = 0; j < calList.size(); j++) {
gameMatrix[i][j].setNum(calList.get(j));
}
for (int m = calList.size(); m < gameLines; m++) {
gameMatrix[i][m].setNum(0);
}
// 重置行參数
keyItemNum = -1;
calList.clear();
}
}
概括来说。就是选取基准,挨个比較,又一次排列
代码非常清晰。大家看看就知道了。关键是怎样总结出这个算法。
4、以下就是推断游戏什么时候须要新加入一个数字Item
当当前的数字矩阵结构域上次的结构发生区别的时候,我们就要add一个新的数字Item了
private boolean isMoved() {
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
if (gameMatrixHistory[i][j] != gameMatrix[i][j].getNum()) {
return true;
}
}
}
return false;
}
这个地方我们使用了一个历史矩阵来存储上一次的数字矩阵
5、最后就是怎样推断结束了
假设当前还有空格的Item,则必然没有结束,若相邻的数字都没有同样的数字,则必然结束,若出现配置的Goal,则赢了
private int checkCompleted() {
getBlanks();
if (blanks.size() == 0) {
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
if (j < gameLines - 1) {
if (gameMatrix[i][j].getNum() == gameMatrix[i][j + 1].getNum()) {
return 1;
}
}
if (i < gameLines - 1) {
if (gameMatrix[i][j].getNum() == gameMatrix[i + 1][j].getNum()) {
return 1;
}
}
}
}
return 0;
}
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
if (gameMatrix[i][j].getNum() == 2048) {
return 2;
}
}
}
return 1;
}
以下放出一些终于的图片:
因为刚换了工作,上下班时间倍增,所以写代码的时间也少了,事实上关于这个游戏我还有非常多想法没做。这个版本号的2048,比网上的版本号,多了撤销上次移动功能。多了能够定制游戏维数的功能,多了配置目标值的功能,我这个版本号的2048,配置要求极低,相比cocos2dx版本号的来说,极大的减少了电量消耗,可配置性更强。这些都是我在玩的过程中。认为不爽的地方,然后改进的。另一些想法。眼下还没有去做。平时工作去做android的framework了,应用层也就研究的少了,希望大家能改进我的代码。做出更好的2048。
1、加入debug功能,也称作弊后门,我原来是想,当手指滑动超过多少距离后,调用一个新方法。设置加入的随机数的位置和大小,这个用我如今的代码是非常好实现的,仅仅要把addRandom方法改下,写一个debugRandom方法就OK了
2、分享功能。这个用ShareSdk就能够了,玩游戏嘛,就是要大家一起玩才好玩。无社交不游戏
3、更换2、4、8、16……数字的背景。这个网上非常多了。我们也能够自己定义一套背景,这个实现也是比較简单的,仅仅要把GameItem这个类里面的Item的背景加入一个set方法就ok了
以上。终了
以下,刷代码
package com.xys.game2048.view;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.SharedPreferences.Editor;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.GridLayout;
import android.widget.Toast;
import com.xys.game2048.activity.Game;
import com.xys.game2048.bean.GameItem;
import com.xys.game2048.config.Config;
public class GameView extends GridLayout implements OnTouchListener {
// GameView相应矩阵
private GameItem[][] gameMatrix;
// 空格List
private List<Point> blanks;
// 矩阵行列数
private int gameLines;
// 记录坐标
private int startX, startY, endX, endY;
// 辅助数组
private List<Integer> calList;
private int keyItemNum = -1;
// 历史记录数组
private int[][] gameMatrixHistory;
// 历史记录分数
private int scoreHistory;
// 最高记录
private int highScore;
public GameView(Context context) {
super(context);
initGameMatrix();
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
initGameMatrix();
}
public void startGame() {
initGameMatrix();
initGameView(Config.ItemSize);
}
private void initGameView(int cardSize) {
removeAllViews();
GameItem card;
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
card = new GameItem(getContext(), 0);
addView(card, cardSize, cardSize);
// 初始化GameMatrix所有为0 空格List为所有
gameMatrix[i][j] = card;
blanks.add(new Point(i, j));
}
}
// 加入随机数字
addRandomNum();
addRandomNum();
}
/**
* 撤销上次移动
*/
public void revertGame() {
if (gameMatrixHistory.length != 0) {
Game.getGameActivity().setScore(scoreHistory, 0);
Config.Scroe = scoreHistory;
for (int i = 0; i < gameLines; i++) {
for (int j = 0; j < gameLines; j++) {
gameMatrix[i][j].setNum(gameMatrixHistory[i][j]);
}
}
}
}
/**
* 加入随机数字
*/
private void addRandomNum() {
getBlanks();
if (blanks.size() > 0) {
int randomNum = (int) (Math.random() * blanks.size());
Point randomPoint = blanks.get(randomNum);
gameMatrix[randomPoint.x][randomPoint.y].setNum(Math.random() > 0.2d ?
标签:奥义,int,gameLines,2048,private,import,终极,Config,gameMatrix 来源: https://www.cnblogs.com/ldxsuanfa/p/10959859.html