没玩过2048的可以自己下一个玩玩,挺有趣的益智游戏。
本文实现了其简单的游戏逻辑,能够进行记分,游戏结束判断功能。重新开始以及保存游戏模块还没有写好,后边
会一一进行完善。
代码都有详细的注释,相信大家都能够看懂。
1.MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView tvScore; private static MainActivity mainActivity=null; private Button restart,saveGame,quitGame; public MainActivity(){ //可以在外界访问MainActivity的实例 mainActivity=this; //MainActivity一旦被构建,就给mainActivity静态变量赋值,就可以从外界进行访问它 } public static MainActivity getMainActivity(){ return mainActivity; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvScore=(TextView)findViewById(R.id.tvScore); quitGame=(Button)findViewById(R.id.quit); restart=(Button)findViewById(R.id.restart); restart.setOnClickListener(this); quitGame.setOnClickListener(this); } @Override public void onClick(View v) { try { switch (v.getId()){ case R.id.quit: System.exit(0); break; case R.id.restart: //new GameView(this,attrs,defStyleAttr).startGame(); //调用方法不成功 Toast.makeText(this, "Not complete", Toast.LENGTH_SHORT).show(); break; } }catch (NullPointerException e){ //空指针异常, 用一个null对象调用了它的某一个方法导致java.lang.NullPointerException错误 e.printStackTrace(); } } //记分的实现: public void clearScore(){ score=0; showScore(); } public void showScore(){ tvScore.setText(score+""); } public void addScore(int s){ score+=s; showScore(); } private int score=0;
}
2.新建GameView类:
public class GameView extends GridLayout { public GameView(Context context, AttributeSet attrs, int defStyleAttr) { //构造方法 super(context, attrs, defStyleAttr); initGameView(); } public GameView(Context context, AttributeSet attrs) { super(context, attrs); initGameView(); } public GameView(Context context) { super(context); initGameView(); } private void initGameView(){ //初始化 setColumnCount(4);//指定为4列 setBackgroundColor(0xffF0FFF0); 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)){ //如果用户斜着滑动,X的偏移量大于Y的偏移量,说明用户为向X方向移动的意图 if(offsetX<-5){ //理论上是小于0,由于可能存在误差,故选择-5 swipeLeft(); }else if(offsetX>5){ swipeRight(); } }else { if (offsetY < -5) { swipeUp(); }else if(offsetY>5){ swipeDown(); } } 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)-15)/4; addCards(cardWidth,cardWidth); startGame(); } private void addCards(int cardWidth,int cardHeight){ 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,cardHeight); cardsMap[x][y]=c; //把16张卡片全部添加进这个二维数组中,方便使用 } } } public 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); //清0 } } addRandomNum(); //调用 addRandomNum(); } private void addRandomNum(){ //添加随机数模块 emptyPoints.clear(); //清0 for (int y=0;y<4;y++){ for(int x=0;x<4;x++){ if(cardsMap[x][y].getNum()<=0){ //只有当卡片上没有数字时才会在其上添加 emptyPoints.add(new Point(x,y)); } } } Point p=emptyPoints.remove((int)(Math.random()*emptyPoints.size())); //Math.random()随机获取0-1之间的数 cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4); //2和4出现的概率为9:1 } 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){ //判断是否合并,若合并了,则添加一个随机数 addRandomNum(); checkComplete(); } } private void swipeRight(){ boolean merge=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++; 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){ addRandomNum(); 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){ addRandomNum(); 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){ addRandomNum(); checkComplete(); } } private void checkComplete(){ //判断游戏是否结束模块,当16个卡片填满数字且相邻之间没有相同的数字,则认为游戏结束。 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){ new AlertDialog.Builder(getContext()).setTitle("Hello!").setMessage("The game is over !") .setNegativeButton("Restart", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startGame(); } }).setPositiveButton("Quit", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { System.exit(0); //直接退出游戏 } }).show(); } } private Card[][] cardsMap=new Card[4][4]; private List<Point> emptyPoints=new ArrayList<Point>(); }
3.新建Card类:
package com.example.administrator.game2048; import android.content.Context; import android.view.Gravity; import android.widget.FrameLayout; import android.widget.TextView; /** * Created by Administrator on 2016/9/17. */ public class Card extends FrameLayout { private int num=0; private TextView label; public Card(Context context) { super(context); label=new TextView(getContext()); label.setTextSize(32); label.setBackgroundColor(0x335F9EA0); label.setGravity(Gravity.CENTER); //卡片在中心显示 LayoutParams lp=new LayoutParams(-1,-1); // (-1,-1)表示填充满整个父级容器 lp.setMargins(15,15,0,0); //设置每个卡片的间隔 addView(label,lp); } public int getNum() { return num; } public void setNum(int num) { this.num = num; if(num<=0){ label.setText(""); }else{ label.setText(num+""); } } public boolean equals(Card o) { return getNum()==o.getNum(); } }
4.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.game2048.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Score :" android:textSize="25dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tvScore" android:textSize="25dp"/> </LinearLayout> <Space android:layout_width="match_parent" android:layout_height="15dp" /> <com.example.administrator.game2048.GameView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.8" android:id="@+id/gameView"> </com.example.administrator.game2048.GameView> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.1" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:id="@+id/restart" android:text="Restart" android:textAllCaps="false" android:background="#2bb" android:textSize="15dp" android:textColor="#159" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:id="@+id/save" android:text="Save" android:textAllCaps="false" android:background="#2cc" android:textSize="15dp" android:textColor="#159" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:id="@+id/quit" android:text="Quit" android:textAllCaps="false" android:background="#2dd" android:textSize="15dp" android:textColor="#159" /> </LinearLayout> </LinearLayout>
5.游戏效果截图: