这章主要讲解2048游戏的核心部分。
我们都知道,2048这款游戏其实操作很简单的,无非就是上下左右四个动作,然后根据卡片上的数字进行相应的操作。
首先,我们用到这个GameView控件的时候(因为继承了GridLayout,相当于自定义控件),定义了三个构造函数:
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
initGameView();
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initGameView();
}
public GameView(Context context) {
super(context);
initGameView();
}
当用到控件的时候 就会自动调用initGameView()函数:
private void initGameView() {
setColumnCount(4);
setBackgroundColor(0xffbbada0);
setOnTouchListener(new OnTouchListener() {
private float startX, startY, offsetX, offsetY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
offsetX = event.getX() - startX;
offsetY = event.getY() - startY;
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX < -5) {
swipeLeft();
} else if (offsetX > 5) {
swipeRight();
}
} else {
if (offsetY < -5) {
swipeUp();
} else if (offsetY > 5) {
swipeDown();
}
}
break;
}
return true;
}
});
}
切记 返回值一定要是return true ,否则只会监听到down事件其余的move和up都不行。接下来是每个动作的实现:
//以下四个函数顾名思义就是OnTouch的四个方向的操作具体实现方法
private void swipeLeft() {
boolean ismove = false;
//Log.i("TAAAAAAAAAAAAAAAAAAA","swipeLeft");
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
for (int x1 = x + 1; x1 < 4; x1++) {
if (cardMap[x1][y].getNum() > 0) {
if (cardMap[x][y].getNum() <= 0) {
// int oldNum = cardMap[x][y].getNum();//获取旧值
cardMap[x][y].setNum(cardMap[x1][y].getNum());
cardMap[x1][y].setNum(0);
//if (oldNum != cardMap[x][y].getNum()) {//代表有卡片移动了 就会在添加一个卡片
// setCardBGColor();
ismove = true;
// }
x--;
} else if (cardMap[x1][y].getNum() == cardMap[x][y].getNum()) {
cardMap[x][y].setNum(cardMap[x1][y].getNum() * 2);
cardMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(cardMap[x][y].getNum());
//setCardBGColor();
ismove = true;
}
break;
}
}
}
}
if (ismove) {
addRandomNum();
checkcomplete();
}
}
private void swipeRight() {
//Log.i("TAAAAAAAAAAAAAAAAAAA", "swipeRight");
boolean ismove = false;
for (int y = 0; y < 4; y++) {
for (int x = 3; x >= 0; x--) {
for (int x1 = x - 1; x1 >= 0; x1--) {
// int oldNum = cardMap[x][y].getNum();//获取旧值
if (cardMap[x1][y].getNum() > 0) {
if (cardMap[x][y].getNum() <= 0) {
cardMap[x][y].setNum(cardMap[x1][y].getNum());
cardMap[x1][y].setNum(0);
// if (oldNum != cardMap[x][y].getNum()) {
// setCardBGColor();
ismove = true;
// }
x++;
break;
} else if (cardMap[x1][y].getNum() == cardMap[x][y].getNum()) {
cardMap[x][y].setNum(cardMap[x1][y].getNum() * 2);
cardMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(cardMap[x][y].getNum());
// setCardBGColor();
ismove = true;
break;
} else {
break;
}
}
}
}
}
if (ismove) {
addRandomNum();
checkcomplete();
}
}
private void swipeDown() {
//Log.i("TAAAAAAAAAAAAAAAAAAA", "swipeDown");
boolean ismove = false;
for (int x = 0; x < 4; x++) {
for (int y = 3; y >= 0; y--) {
for (int y1 = y - 1; y1 >= 0; y1--) {
if (cardMap[x][y1].getNum() > 0) {
// int oldNum = cardMap[x][y].getNum();
if (cardMap[x][y].getNum() <= 0) {
cardMap[x][y].setNum(cardMap[x][y1].getNum());
cardMap[x][y1].setNum(0);
// if (oldNum != cardMap[x][y].getNum()) {
// setCardBGColor();
ismove = true;
// }
y++;
break;
} else if (cardMap[x][y].getNum() == cardMap[x][y1].getNum()) {
cardMap[x][y].setNum(cardMap[x][y1].getNum() * 2);
cardMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(cardMap[x][y].getNum());
// setCardBGColor();
ismove = true;
break;
} else {
break;
}
}
}
}
}
if (ismove) {
addRandomNum();
checkcomplete();
}
}
private void swipeUp() {
//Log.i("TAAAAAAAAAAAAAAAAAAA", "swipeUp");
boolean ismove = false;
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
for (int y1 = y + 1; y1 < 4; y1++) {
if (cardMap[x][y1].getNum() > 0) {
if (cardMap[x][y].getNum() <= 0) {
// int oldNum = cardMap[x][y].getNum();
cardMap[x][y].setNum(cardMap[x][y1].getNum());
cardMap[x][y1].setNum(0);
// if (oldNum != cardMap[x][y].getNum()) {
// setCardBGColor();
ismove = true;
// }
y--;
break;
} else if (cardMap[x][y].getNum() == cardMap[x][y1].getNum()) {
cardMap[x][y].setNum(cardMap[x][y1].getNum() * 2);
cardMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(cardMap[x][y].getNum());
// setCardBGColor();
ismove = true;
break;
} else {
break;
}
}
}
}
}
if (ismove) {
addRandomNum();
checkcomplete();
}
}
下面是checkcomplete()函数的实现:
//判断游戏结束
private void checkcomplete(){
boolean isover=true;
ALL:
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
if(cardMap[x][y].getNum()==0||
((x>0)&&cardMap[x][y].getNum()==cardMap[x-1][y].getNum())||
((x<3)&&cardMap[x][y].getNum()==cardMap[x+1][y].getNum())||
((y>0)&&cardMap[x][y].getNum()==cardMap[x][y-1].getNum())||
((y<3)&&cardMap[x][y].getNum()==cardMap[x][y+1].getNum())){
isover=false;
break ALL;
}
}
}
if(isover){
final AlertDialog.Builder builder=new AlertDialog.Builder(getContext());
builder.setTitle("提示");
builder.setMessage("游戏结束,是否继续?");
builder.setPositiveButton("继续", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startGame();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
}
上面的含义我想大家只要稍微动下脑筋就会明白的。
主逻辑中还有个记录分数的功能,调用了MainActivity里面的方法:
package com.example.administrator.game2048;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvScore;
private int score=0;
public MainActivity(){
mainActivity=this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvScore= (TextView) findViewById(R.id.tvScore);
}
private static MainActivity mainActivity=null;
public static MainActivity getMainActivity() {
return mainActivity;
}
public void clearScore(){
score=0;
showScore();
}
public void showScore(){
tvScore.setText(score+"");
}
public void addScore(int s){
score+=s;
showScore();
}
}
另外 配置文件中Activity节点里加上
android:screenOrientation="portrait"
只能竖屏不能变换
到这里 就完全写完了,如果嫌这里麻烦的话 可以直接下载源码。