mcrwayfun,歡迎你
阿新 • • 發佈:2019-02-02
現在我們要實現一個2048的遊戲,那麼開始吧~
首先我們先來把佈局給實現了~2048是一個4*4的平面遊戲,那麼就要用到GridLayout,我們先寫將其嵌入在一個LinearLayout中,請看程式碼
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <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:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/Score" /> <TextView android:id="@+id/tvScore" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textAppearance="?android:attr/textAppearanceLarge"/> <Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/newGame" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> <com.example.game2048.GameView android:id="@+id/gameView" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" > </com.example.game2048.GameView> </LinearLayout>
建立一個遊戲類GameView,其繼承自佈局GridLayout,並這個類繫結在activity_main.xml的GridLayout上,具體操作如下
1:滑鼠移至GameView處,其自動浮現類的路徑,複製
2:替換關鍵字GridLayout
GameView的程式碼,要向AndroidMainfest.xml的activity新增屬性 android:screenOrientation="portrait"
public class GameView extends GridLayout { private Card[][] cardsMap=new Card[4][4]; private List<Point> emptyPoints=new ArrayList<Point>(); // 保險起見,把三個建構函式全部都添加了 public GameView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initGameView(); }// 建構函式1 public GameView(Context context, AttributeSet attrs) { super(context, attrs); initGameView(); }// 建構函式2 public GameView(Context context) { super(context); initGameView(); }// 建構函式3 private void initGameView(){//啟動遊戲 setColumnCount(4);//設定為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();//獲得起始的x座標 startY=event.getY();//獲得起始的y座標 break; case MotionEvent.ACTION_UP://手指觸碰後 offsetX=event.getX()-startX;//獲得偏移的x座標 offsetY=event.getY()-startY;//獲得偏移的y座標 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;//返回true事件發生 } }); } 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||//如果一個格子不為0並且它上下左右有跟它相等的數,則遊戲不結束 (x>1&&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("遊戲結束 ").setPositiveButton("重來 ", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startGame(); } }).show(); } } @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(); } private void addCards(int cardHeight,int cardWidth){ 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; } } } public void startGame(){ MainActivity.getMainActivity().clearScore();//分數清零 for(int y=0;y<4;y++){//原先可能不為0,所以要先清0 for(int x=0;x<4;x++){ cardsMap[x][y].setNum(0); } } addRandomNum();//新增兩個隨機數 addRandomNum(); } private void addRandomNum(){ emptyPoints.clear();//新增隨機數之前把列表清空 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()));//取出列表中的一個點 cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);//2生成的概率是4的9倍 } 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++){//從當前位置往右遍歷,只遍歷3列 if(cardsMap[x1][y].getNum()>0){//找到一個當前格子大於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--){//從當前位置往右遍歷,只遍歷3列 if(cardsMap[x1][y].getNum()>0){//找到一個當前格子大於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++){//從當前位置往右遍歷,只遍歷3列 if(cardsMap[x][y1].getNum()>0){//找到一個當前格子大於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--){//從當前位置往右遍歷,只遍歷3列 if(cardsMap[x][y1].getNum()>0){//找到一個當前格子大於0的 if(cardsMap[x][y].getNum()<=0){//與當前格同一行的,且在其前面的(列方向),是空白的 cardsMap[x][y].setNum(cardsMap[x][y1].getNum());//將當前格子的數字移到空白格處 cardsMap[x][y1].setNum(0);//當前格清零 y++; }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());//計分 } break; } } } } if(merge){ addRandomNum(); checkComplete(); } } }
接下來要建立一個紙牌類,來建立卡片,類名為Card
public class Card extends FrameLayout { private int num=0; private TextView label; private View background; public Card(Context context) { super(context); LayoutParams lp = null; lp = new LayoutParams(-1, -1);//填滿父容器 lp.setMargins(10, 10, 0, 0);//設定每個文字之間的距離 background = new View(getContext()); background.setBackgroundColor(0x33ffffff);//設定第二層的背景顏色 addView(background, lp);//加入佈局中 label = new TextView(getContext()); label.setTextSize(28); label.setGravity(Gravity.CENTER);//使數字居中 lp = new LayoutParams(-1, -1);//第三層背景 lp.setMargins(10, 10, 0, 0); addView(label, lp); setNum(0); } public int getNum() { return num; } public void setNum(int num) { this.num = num; if(num<=0){ label.setText("");//如果數小於等於0,設定空字元 }else{ String s=Integer.toString(num); label.setText(s); } switch (num) {//設定相應數字對應的顏色 case 0: label.setBackgroundColor(0x00000000); break; case 2: label.setBackgroundColor(0xffeee4da); break; case 4: label.setBackgroundColor(0xffede0c8); break; case 8: label.setBackgroundColor(0xfff2b179); break; case 16: label.setBackgroundColor(0xfff59563); break; case 32: label.setBackgroundColor(0xfff67c5f); break; case 64: label.setBackgroundColor(0xfff65e3b); break; case 128: label.setBackgroundColor(0xffedcf72); break; case 256: label.setBackgroundColor(0xffedcc61); break; case 512: label.setBackgroundColor(0xffedc850); break; case 1024: label.setBackgroundColor(0xffedc53f); break; case 2048: label.setBackgroundColor(0xffedc22e); break; default: label.setBackgroundColor(0xff3c3a32); break; } } public boolean equals(Card o){ return getNum()==o.getNum();//判斷卡片的內容是否相等 } }
最後是MainActivity的實現
public class MainActivity extends Activity {
private TextView tvScore;
private static MainActivity mainActivity=null;//構造一個MainActivity例項變數,可以方便獲取
private int score=0;
private Button my_button;
private GameView gameView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
tvScore=(TextView) findViewById(R.id.tvScore);
gameView=(GameView) findViewById(R.id.gameView);
my_button=(Button) findViewById(R.id.my_button);
my_button.setOnClickListener(new OnClickListener() {//重新開始
@Override
public void onClick(View v) {
gameView.startGame();
}
});
}
public MainActivity(){
mainActivity=this;
}
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();
}
}
最後來一些遊戲截圖吧~
----------------------------晴天_1993----------------------------