整个页面分为三个部分:
1)GridLayout:存放两个TextView(【score】以及当前所得分数数值)
2)自定义控件GameView(GridLayout):4*4方格,每个方格中存放一个TextView(用于存放num)
3)Button重新开始
代码:
Main:
package com.example.project2048;
import com.example.project2048.R; //加入自定义控件
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private int score = 0;
private TextView tvScore; //定义一个文本框,用于存储所得分数
private static MainActivity mainActivity = null;
private GameView gameView; //自定义控件(4*4卡片的操作,即游戏主体)
private Button btRestart; //按钮"重新开始"
public MainActivity(){
mainActivity = this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvScore = (TextView) findViewById(R.id.tvScore); //实例化(卡片移动函数可调用)
gameView = (GameView) findViewById(R.id.gameView);
btRestart = (Button) findViewById(R.id.btRestart);
btRestart.setOnClickListener(this);
}
public static MainActivity getMainActivity(){
return mainActivity;
}
public void showScore(){
tvScore.setText(score+"");
}
public void addScore(int s){ //分数计算
score += s;
showScore();
}
public void clearScore(){ //分数清0
score = 0;
showScore();
}
@Override
public void onClick(View v) {
gameView.restartGame();
}
}
GameView:
package com.example.project2048;
import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.Toast;
/*
* 自定义控件:
* 1.新建一个类,继承view/view的子类 *增加相应的构造方法
* 2.在布局文件中加入该类 *使用全类名
*/
public class GameView extends GridLayout {
private Card[][] cardsMap = new Card[4][4]; //存储4*4方格中的数字
private List<Point> lists = new ArrayList<Point>();
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
initGame();
}
private void initGame(){ //初始化
setColumnCount(4); //设置4行4列
setBackgroundColor(0xffbbada0); //设置背景颜色
setOnTouchListener(new OnTouchListener() { //(手指)移动监听
private float startX,startY,offsetX,offsetY;
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: //(手指)按下
//获取当前位置坐标
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP: //(手指)抬起
//获取手指X,Y轴的位移(有方向)
offsetX = event.getX() - startX;
offsetY = event.getY() - startY;
/*判断手指移动方向(上下左右)
*(-5,5)为误差范围内(误差:eg.手指不小心滑动)
*/
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX < -5) {
swipeLeft();
//Toast.makeText(getContext(), "向左滑动", Toast.LENGTH_LONG).show();
} else if(offsetX > 5) {
swipeRight();
//Toast.makeText(getContext(), "向右滑动", Toast.LENGTH_LONG).show();
}
}else {
if (offsetY < -5) {
swipeUp();
//Toast.makeText(getContext(), "向上滑动", Toast.LENGTH_LONG).show();
}else if (offsetY > 5) {
swipeDown();
//Toast.makeText(getContext(), "向下滑动", Toast.LENGTH_LONG).show();
}
}
break;
}
return true;
}
});
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
int cardWidth = (Math.min(w, h)-10)/4; //获取卡片大小
addCard(cardWidth, cardWidth);
startGame();
}
private void addCard(int cardWidth,int cardHeigh){
Card c;
//遍历方格,将文本框添加至方格中
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
c = new Card(getContext());
// c.setNum(0);
addView(c, cardWidth, cardHeigh);
cardsMap[x][y] = c;
}
}
}
private void startGame(){ //游戏开始
MainActivity.getMainActivity().clearScore(); //分数清0
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
cardsMap[x][y].setNum(0); //4*4方格上的数字全部置为0
}
}
//添加两个随机数
addRandomNum();
addRandomNum();
}
private void addRandomNum(){ //添加随机数
lists.clear();
//遍历4*4方格,寻找空白方格(即数字为0的)
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if (cardsMap[x][y].getNum() <= 0) {
lists.add(new Point(x, y));
}
}
}
Point p = lists.remove((int)(Math.random()*lists.size())); //避免越界
cardsMap[p.x][p.y].setNum(Math.random()>0.1 ? 2 : 4);//9:1
}
//上下左右移动
private void swipeLeft(){ //左移
boolean add = false;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
for (int x1 = x+1; x1 < 4; x1++) {
if (cardsMap[x1][y].getNum() > 0) { //右边存在不为空(不为0)的卡片
//左边卡片为空(为0),右边卡片左移
if (cardsMap[x][y].getNum()<=0) {
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x1][y].setNum(0);
x--;
add = true;
}
//左边卡片与右边卡片值相等,右边移至左边叠加
else if(cardsMap[x][y].equals(cardsMap[x1][y])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum()); //分数相应增加
add = true;
}
break;
}
}
}
}
if (add) {
addRandomNum(); //移动后添加随机数
endGame(); //判断游戏是否结束
}
}
private void swipeRight(){ //右移
boolean add = false;
for (int y = 0; y < 4; y++) {
for (int x = 3; x >=0 ; x--) {
for (int x1 = x-1; x1 >=0; x1--) {
if (cardsMap[x1][y].getNum() > 0) {
if (cardsMap[x][y].getNum() <=0) {
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x1][y].setNum(0);
x++;
add = true;
}else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
add = true;
}
break;
}
}
}
}
if (add) {
addRandomNum();
endGame();
}
}
private void swipeUp(){ //上移
boolean add = false;
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
for (int y1 = y+1; y1 < 4; y1++) {
if (cardsMap[x][y1].getNum() > 0) {
if (cardsMap[x][y].getNum() <= 0) {
cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
cardsMap[x][y1].setNum(0);
y--;
add = true;
}else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
add = true;
}
break;
}
}
}
}
if (add) {
addRandomNum();
endGame();
}
}
private void swipeDown(){ //下移
boolean add = false;
for (int x = 0; x < 4; x++) {
for (int y = 3; y >=0; y--) {
for (int y1 = y-1; y1 >=0; y1--) {
if (cardsMap[x][y1].getNum() > 0) {
if (cardsMap[x][y].getNum()<=0) {
cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
cardsMap[x][y1].setNum(0);
y++;
add = true;
}else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
add = true;
}
break;
}
}
}
}
if (add) {
addRandomNum();
endGame();
}
}
private void endGame(){ //判断游戏是否结束
boolean complete = true;
ALL:for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
//卡片仍有为空(为0),或连续两张有值相等的,则游戏继续
if (cardsMap[x][y].getNum() == 0
||(x > 0 && cardsMap[x][y].equals(cardsMap[x-1][y]))
||(x < 3 && cardsMap[x][y].equals(cardsMap[x+1][y]))
||(y > 0 && cardsMap[x][y].equals(cardsMap[x][y-1]))
||(y < 3 && cardsMap[x][y].equals(cardsMap[x][y+1]))) {
complete = false;
break ALL;
}
}
}//ALL:有一个条件满足循环即中断,提高效率
if (complete) { //若游戏结束
new AlertDialog.Builder(getContext()) //弹出提示对话框
.setTitle("你好!")
.setMessage("游戏结束")
//为“重新开始”按钮设置监听事件
.setPositiveButton("重新开始", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
startGame();
}
}).show();
}
}
public void restartGame(){ //重新开始游戏
MainActivity.getMainActivity().clearScore(); //分数清0
//遍历4*4方格,将值不为0的所有卡片置为0
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if (cardsMap[x][y] ==null) {
continue;
}
cardsMap[x][y].setNum(0);
}
}
//添加两个随机数
addRandomNum();
addRandomNum();
}
}
Card:
package com.example.project2048;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;
public class Card extends FrameLayout {
private TextView tv; //文本框(卡片中存放数值)
private int num = 0;
public Card(Context context) {
super(context);
tv = new TextView(getContext());
tv.setTextSize(32);
tv.setGravity(Gravity.CENTER); //在方格中居中放置
tv.setBackgroundColor(0x33ffffff);
LayoutParams params = new LayoutParams(-1, -1);
params.setMargins(10, 10, 0, 0);
addView(tv, params); //将文本框添加至方格上
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
//根据卡片上的值不同,设置相应卡片背景颜色
if (num <= 0) {
tv.setBackgroundColor(0x33ffffff);
tv.setText(""); //若卡片值为0,则不显示数值
} else {
if(num == 2)
tv.setBackgroundColor(Color.parseColor("#CDB79E"));//深灰
if(num == 4)
tv.setBackgroundColor(Color.parseColor("#CDB38B"));//加深灰
if(num == 8)
tv.setBackgroundColor(Color.parseColor("#FF8C00"));//橙色
if(num == 16)
tv.setBackgroundColor(Color.parseColor("#FF7F00"));//橙色
if(num == 32)
tv.setBackgroundColor(Color.parseColor("#FF4500"));//桔红
if(num == 64)
tv.setBackgroundColor(Color.parseColor("#FF0000"));//红
if(num == 128)
tv.setBackgroundColor(Color.parseColor("#FFF68F"));//浅桔
/*tv.setText(num);
* tv.setText(num+"");
* 方法重载(int/char)
*/
tv.setText(num+"");
}
}
public boolean equals(Card c) {
return this.getNum()==c.getNum();
}
}