android 2048游戏项目详解
壹.自定义卡片单元视图:
public class Cards extends FrameLayout{
private TextView labels;
private int num=0;
public Cards(Context context) {
super(context);
labels=new TextView(getContext());
labels.setTextSize(32);
labels.setGravity(Gravity.CENTER);
labels.setBackgroundColor(0x33ffffff);
LayoutParams lp=new LayoutParams(-1, -1);
lp.setMargins(10,10,0,0);
this.addView(labels,lp);
this.setNum(0);
}
public void setNum(int num){
this.num=num;
if(num<=0){
labels.setText("");
}
else{
labels.setText(num+"");
}
}
public int getNum(){
return this.num;
}
//判断两张卡片的值是否相等
public boolean equals(Cards c){
return this.getNum()==c.getNum();
}
}
贰.创建自定义网格布局:
public class MyGridView extends GridLayout {
private Cards[][] cardsMap=new Cards[4][4];
private List<Point> emptyPoints = new ArrayList<Point>();
public MyGridView(Context context) {
super(context);
initViews();
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViews();
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initViews();
}
private void initViews(){
setColumnCount(4);
this.setBackgroundColor(0xffbbada0);
}
@Override
//绘制布局的过程中添加卡片布局
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int cardWidth=(Math.min(w, h)-10)/4;
addCards(cardWidth,cardWidth);
startGame();
}
/**
* 添加卡片视图
* @param cardWidth
* @param cardHeight
*/
private void addCards(int cardWidth,int cardHeight){
Cards c;
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
c=new Cards(getContext());
c.setNum(0);
addView(c,cardWidth,cardHeight);
cardsMap[x][y]=c;
}
}
}
叁.在主activity中加入自定义布局:
<com.zyl2015.mynew2048.MyGridView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/gameView" >
</com.zyl2015.mynew2048.MyGridView>
四.实现滑动手势监听
private void initGameView(){
setColumnCount(4);
setBackgroundColor(0xffbbada0);
//监听触摸事件处理逻辑
setOnTouchListener(new View.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;
}
});
}
五.实现随机出现2或4的卡片功能:
/**
* 随机添加一个卡片,值为2或4
*/
private void addRandom(){
emptyPoints.clear();
for (int x=0;x<4;x++){
for(int y=0;y<4;y++){
if(cardsMap[x][y].getNum()<=0){
emptyPoints.add(new Point(x,y));
}
}
}
Point p=emptyPoints.remove((int)Math.random()*emptyPoints.size());
cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);
Log.i("zyl", cardsMap[p.x][p.y].getNum()+"");
}
六.核心逻辑处理(只演示向左滑动):
private void swipeUp(){
boolean merge=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--;
merge=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());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandom();
checkComplete();
}
}
七.实现计分功能(调动mainactivity里面的方法)
public void showScore(){
tvTotalScore.setText(tolScore+"");
}
public void addScore(int s){
tolScore+=s;
showScore();
}
public static MainActivity getMainActivity() {
return mainActivity;
}
}
八.判断是否游戏结束:
/**
* 相邻的可以消除并且还有空,游戏就没结束
*/
private void checkComplete(){
boolean complete =true;
ALL:
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
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;
}
}
}
if(complete){
Builder builder= new AlertDialog.Builder(getContext()).setTitle("提示信息").setMessage(" 你GameOver了!");
builder.setPositiveButton("重来", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startGame();
}
});
builder.setNegativeButton("哭一场", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
Toast.makeText(getContext(), "哭", Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
}
详细实现过程如下:
一.卡片类
public class Cards extends FrameLayout{
private TextView labels;
private int num=0;
public Cards(Context context) {
super(context);
labels=new TextView(getContext());
labels.setTextSize(32);
labels.setGravity(Gravity.CENTER);
labels.setBackgroundColor(0x33ffffff);
LayoutParams lp=new LayoutParams(-1, -1);
lp.setMargins(10,10,0,0);
this.addView(labels,lp);
this.setNum(0);
}
public void setNum(int num){
this.num=num;
if(num<=0){
labels.setText("");
}
else{
labels.setText(num+"");
}
}
public int getNum(){
return this.num;
}
public boolean equals(Cards c){
return this.getNum()==c.getNum();
}
}
二.自定义网格布局、核心逻辑处理类
public class MyGridView extends GridLayout {
private Cards[][] cardsMap=new Cards[4][4];
private List<Point> emptyPoints = new ArrayList<Point>();
public MyGridView(Context context) {
super(context);
initViews();
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViews();
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initViews();
}
/**
* 初始化卡片布局
*/
private void initViews(){
setColumnCount(4);
this.setBackgroundColor(0xffbbada0);
//监听触摸事件处理逻辑
this.setOnTouchListener(new View.OnTouchListener(){
private float startX,startY,offsetX,offsetY;
@Override
public boolean onTouch(View v, MotionEvent m) {
// 记录方向
switch(m.getAction()){
case MotionEvent.ACTION_DOWN:
startX=m.getX();
startY=m.getY();
break;
case MotionEvent.ACTION_UP:
offsetX=m.getX()-startX;
offsetY=m.getY()-startY;
if(Math.abs(offsetX)>Math.abs(offsetY)){
if(offsetX<-5){
swipeLeft();
Log.i("zyl","left");
}
else if(offsetX>5){
swipeRight();
Log.i("zyl","right");
}
}
else{
if(offsetY<-5){
swipeUp();
Log.i("zyl","up");
}
else if(offsetY>5){
swipeDown();
Log.i("zyl","down");
}
}
break;
}
return true;
}
});
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int cardWidth=(Math.min(w, h)-10)/4;
addCards(cardWidth,cardWidth);
startGame();
}
/**
* 添加卡片视图
* @param cardWidth
* @param cardHeight
*/
private void addCards(int cardWidth,int cardHeight){
Cards c;
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
c=new Cards(getContext());
c.setNum(0);
addView(c,cardWidth,cardHeight);
cardsMap[x][y]=c;
}
}
}
private void swipeLeft(){
boolean merge=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){
if(cardsMap[x][y].getNum()<=0){
cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
cardsMap[x1][y].setNum(0);
x--;
merge=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());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandom();
checkComplete();
}
}
private void swipeRight(){
boolean merge=false;
for(int y=0;y<=3;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++;
merge=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());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandom();
checkComplete();
}
}
private void swipeUp(){
boolean merge=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--;
merge=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());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandom();
checkComplete();
}
}
private void swipeDown(){
boolean merge=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++;
merge=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());
merge=true;
}
break;
}
}
}
}
if(merge){
addRandom();
checkComplete();
}
}
/**
* 随机添加一个卡片,值为2或4
*/
private void addRandom(){
emptyPoints.clear();
for (int x=0;x<4;x++){
for(int y=0;y<4;y++){
if(cardsMap[x][y].getNum()<=0){
emptyPoints.add(new Point(x,y));
}
}
}
Point p=emptyPoints.remove((int)Math.random()*emptyPoints.size());
cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);
Log.i("zyl", cardsMap[p.x][p.y].getNum()+"");
}
/**
* 开始游戏,清空所有条目
*/
private void startGame(){
MainActivity.getMainActivity().clearScore();
for(int x=0;x<4;x++){
for(int y=0;y<4;y++){
cardsMap[x][y].setNum(0);
}
}
addRandom();
addRandom();
}
/**
* 相邻的可以消除并且还有空,游戏就没结束
*/
private void checkComplete(){
boolean complete =true;
ALL:
for(int y=0;y<4;y++){
for(int x=0;x<4;x++){
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;
}
}
}
if(complete){
Builder builder= new AlertDialog.Builder(getContext()).setTitle("提示信息").setMessage(" 你GameOver了!");
builder.setPositiveButton("重来", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startGame();
}
});
builder.setNegativeButton("哭一场", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
Toast.makeText(getContext(), "哭", Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
}
}
三.主活动
public class MainActivity extends Activity {
private int score = 0;
private int tolScore=0;
private TextView tvTotalScore;
private static MainActivity mainActivity = null;
public MainActivity(){
mainActivity=this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTotalScore=(TextView)this.findViewById(R.id.tvTotalScore);
}
public void clearScore(){
tolScore=0;
showScore();
}
public void showScore(){
tvTotalScore.setText(tolScore+"");
}
public void addScore(int s){
tolScore+=s;
showScore();
}
public static MainActivity getMainActivity() {
return mainActivity;
}
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。