I am also developing the ultimate aoyi of 2048.

Source: Internet
Author: User
Tags gety

This tutorial has been separated from the previous one for a while. If you forget it, let's take a look at the previous ones. Today, I am going to end this 2048 lesson, dragging on for so long.


According to the Convention, we have done all the preparation work well. Today, this part of the information is large, and it is also the core of the entire game. So I have prepared the sub-function, in the end, we will not feel too hard to look at the source code.


1. initialize the game

What should we do during initialization? First, we need to check the configuration, configure several rows, then draw the panel, and then randomly generate two numeric items on the panel, this involves two methods: initialization panel and adding random numbers.

Private void initGameView (int cardSize) {removeAllViews (); GameItem card; for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {card = new GameItem (getContext (), 0); addView (card, cardSize, cardSize ); // initialize GameMatrix with all 0 spaces. List all gameMatrix [I] [j] = card; blanks. add (new Point (I, j) ;}// add random numbers addRandomNum ();}

private void addRandomNum() {getBlanks();if (blanks.size() > 0) {    int randomNum = (int) (Math.random() * blanks.size());    Point randomPoint = blanks.get(randomNum);    gameMatrix[randomPoint.x][randomPoint.y].setNum(Math.random() > 0.2d ? 2 : 4);    Game.getGameActivity().getAnimationLayer().animcreate(gameMatrix[randomPoint.x][randomPoint.y]);}    }

When determining the generation of 2 and 4, we use the method that usually generates a random number in the range, and specify the ratio of 2 to 4 at. Of course, you can change the value as needed.


2. Initialization of specific parameters

This is relatively simple. You should understand the Code directly.

Private void initGameMatrix () {// initialization matrix removeAllViews (); scoreHistory = 0; Config. scroe = 0; Config. gameLines = Config. sp. getInt (Config. KEY_GameLines, 4); gameLines = Config. gameLines; gameMatrix = new GameItem [gameLines] [gameLines]; gameMatrixHistory = new int [gameLines] [gameLines]; calList = new ArrayList <Integer> (); blanks = new ArrayList <Point> (); highScore = Config. sp. getInt (Config. KEY_HighScore, 0); setColumnCount (gameLines); setRowCount (gameLines); setOnTouchListener (this); // initialize the View parameter DisplayMetrics metrics = new DisplayMetrics (); WindowManager wm = (WindowManager) getContext (). getSystemService (Context. WINDOW_SERVICE); Display display = wm. getdefadisplay display (); display. getMetrics (metrics); Config. itemSize = metrics. widthPixels/Config. gameLines; initGameView (Config. itemSize );}

This part should be better viewed with the source code, with clear comments.


3. Touch events

The four directions are determined during touch. This is also a general method.

Public boolean onTouch (View v, MotionEvent event) {switch (event. getAction () {case MotionEvent. ACTION_DOWN: saveHistoryMatrix (); startX = (int) event. getX (); startY = (int) event. getY (); break; case MotionEvent. ACTION_MOVE: break; case MotionEvent. ACTION_UP: endX = (int) event. getX (); endY = (int) event. getY (); judgeDirection (endX-startX, endY-startY); if (isMoved () {addRandomNum (); // modify the display score Game. getGameActivity (). setScore (Config. scroe, 0);} int result = checkCompleted (); if (result = 0) {if (Config. scroe> highScore) {Editor editor = Config. sp. edit (); editor. putInt (Config. KEY_HighScore, Config. scroe); editor. commit ();} Toast. makeText (getContext (), "lose", Toast. LENGTH_LONG ). show (); Config. scroe = 0;} else if (result = 2) {Toast. makeText (getContext (), "success", Toast. LENGTH_LONG ). show (); Config. scroe = 0;} break; default: break;} return true ;}
The offset Determination Method

private void judgeDirection(int offsetX, int offsetY) {if (Math.abs(offsetX) > Math.abs(offsetY)) {    if (offsetX > 10) {swipeRight();    } else {swipeLeft();    }} else {    if (offsetY > 10) {swipeDown();    } else {swipeUp();    }}    }

Next we will talk about the ultimate role of 2048, that is, the implementation of algorithms. The specific algorithm has explained the rough process in the first article. Let's take a look at it. Next we will select a direction to explain how to implement it.

Private void swipeLeft () {for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {int currentNum = gameMatrix [I] [j]. getNum (); if (currentNum! = 0) {if (keyItemNum =-1) {keyItemNum = currentNum;} else {if (keyItemNum = currentNum) {calList. add (keyItemNum * 2); Config. scroe + = keyItemNum * 2; keyItemNum =-1;} else {calList. add (keyItemNum); keyItemNum = currentNum ;}} else {continue ;}} if (keyItemNum! =-1) {calList. add (keyItemNum);} // change the Item value for (int j = 0; j <calList. size (); j ++) {gameMatrix [I] [j]. setNum (calList. get (j);} for (int m = calList. size (); m <gameLines; m ++) {gameMatrix [I] [m]. setNum (0);} // reset the row parameter keyItemNum =-1; calList. clear ();}}

In general, it is to select a benchmark, compare one by one, and rearrange

The code is very clear and you can see it. The key is how to sum up this algorithm.


4. The following figure determines when a new digital Item needs to be added to the game.

When the structure of the current digital matrix structure field is different from the previous one, we need to add a new number Item.

private boolean isMoved() {for (int i = 0; i < gameLines; i++) {    for (int j = 0; j < gameLines; j++) {if (gameMatrixHistory[i][j] != gameMatrix[i][j].getNum()) {    return true;}    }}return false;    }

Here we use a historical matrix to store the last digital matrix.


5. Finally, how can we judge the end?

If there is a space Item, it will certainly not end. If there are no adjacent numbers with the same number, it will end. If the configured Goal appears, it will win.

private int checkCompleted() {getBlanks();if (blanks.size() == 0) {    for (int i = 0; i < gameLines; i++) {for (int j = 0; j < gameLines; j++) {    if (j < gameLines - 1) {if (gameMatrix[i][j].getNum() == gameMatrix[i][j + 1].getNum()) {    return 1;}    }    if (i < gameLines - 1) {if (gameMatrix[i][j].getNum() == gameMatrix[i + 1][j].getNum()) {    return 1;}    }}    }    return 0;}for (int i = 0; i < gameLines; i++) {    for (int j = 0; j < gameLines; j++) {if (gameMatrix[i][j].getNum() == 2048) {    return 2;}    }}return 1;    }

Some final images are shown below:



Since I just changed my job and work time doubled, I have less time to write code. In fact, I still have a lot of ideas about this game. The version 2048 is better than the online version, with the function of revoking the last move, the function of customizing the dimension of the game, and the function of configuring the target value, I have 2048 of this version, and the configuration requirements are extremely low. Compared with the cocos2dx version, greatly reduces power consumption and is more configurable. These are what I felt uncomfortable when I was playing the game. Then I improved it. I still have some ideas. I haven't done it yet. I usually work on the android framework, the application layer is also less researched. I hope everyone can improve my code and make a better 2048.

1. Add the debug function, also known as the cheating backdoor. I originally thought that when the finger slides more than how many distances, call a new method to set the position and size of the added random number, this is well implemented using my current code. You only need to change the addRandom method and write a debugRandom method.

2. Share the function. You can use ShareSdk to play games. It is fun to play games together without social networking.

3. Replace 2, 4, 8, 16 ...... There are a lot of digital backgrounds on the Internet. We can also customize a set of backgrounds. This implementation is also relatively simple, you only need to add a set method to the background of the Item in the class GameItem.

Above, end

Below, click the code

Package com. xys. game2048.view; import java. util. arrayList; import java. util. list; import android. content. context; import android. content. sharedPreferences. editor; import android. graphics. point; import android. util. attributeSet; import android. util. displayMetrics; import android. view. display; import android. view. motionEvent; import android. view. view; import android. view. view. onTouchListener; import android. view. WindowManager; import android. widget. gridLayout; import android. widget. toast; import com. xys. game2048.activity. game; import com. xys. game2048.bean. gameItem; import com. xys. game2048.config. config; public class GameView extends GridLayout implements OnTouchListener {// GameView ing matrix private GameItem [] [] gameMatrix; // space List private List <Point> blks; // The number of rows and columns in the Matrix. private int gameLines; // records the coordinate private int s. TartX, startY, endX, endY; // secondary array private List <Integer> calList; private int keyItemNum =-1; // array of historical records private int [] [] gameMatrixHistory; // historical record score private int scoreHistory; // the highest record private int highScore; public GameView (Context context) {super (context); initGameMatrix ();} public GameView (Context context, attributeSet attrs) {super (context, attrs); initGameMatrix ();} public void startGame () {ini TGameMatrix (); initGameView (Config. itemSize);} private void initGameView (int cardSize) {removeAllViews (); GameItem card; for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {card = new GameItem (getContext (), 0); addView (card, cardSize, cardSize ); // initialize GameMatrix with all 0 spaces. List all gameMatrix [I] [j] = card; blanks. add (new Point (I, j) ;}// add random numbers addRandomNum (); addRandomNum () ;}/ *** undo Last moved */public void revertGame () {if (gameMatrixHistory. length! = 0) {Game. getGameActivity (). setScore (scoreHistory, 0); Config. scroe = scoreHistory; for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {gameMatrix [I] [j]. setNum (gameMatrixHistory [I] [j]) ;}}/ *** add random numbers */private void addRandomNum () {getBlanks (); if (blanks. size ()> 0) {int randomNum = (int) (Math. random () * blanks. size (); Point randomPoint = blanks. get (randomNum); game Matrix [randomPoint. x] [randomPoint. y]. setNum (Math. random ()> 0.2d? 2: 4); Game. getGameActivity (). getAnimationLayer (). animcreate (gameMatrix [randomPoint. x] [randomPoint. y]) ;}}/*** get space Item array */private void getBlanks () {blanks. clear (); for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {if (gameMatrix [I] [j]. getNum () = 0) {blanks. add (new Point (I, j) ;}}}/*** initialize View */private void initGameMatrix () {// initialize the matrix removeAllViews (); scoreHisto Ry = 0; Config. scroe = 0; Config. gameLines = Config. sp. getInt (Config. KEY_GameLines, 4); gameLines = Config. gameLines; gameMatrix = new GameItem [gameLines] [gameLines]; gameMatrixHistory = new int [gameLines] [gameLines]; calList = new ArrayList <Integer> (); blanks = new ArrayList <Point> (); highScore = Config. sp. getInt (Config. KEY_HighScore, 0); setColumnCount (gameLines); setRowCount (gameLines); setOnTouchListener (This); // initialize the View parameter DisplayMetrics metrics = new DisplayMetrics (); WindowManager wm = (WindowManager) getContext (). getSystemService (Context. WINDOW_SERVICE); Display display = wm. getdefadisplay display (); display. getMetrics (metrics); Config. itemSize = metrics. widthPixels/Config. gameLines; initGameView (Config. itemSize) ;}@ Override public boolean onTouch (View v, MotionEvent event) {switch (event. getAction ()) {Case MotionEvent. ACTION_DOWN: saveHistoryMatrix (); startX = (int) event. getX (); startY = (int) event. getY (); break; case MotionEvent. ACTION_MOVE: break; case MotionEvent. ACTION_UP: endX = (int) event. getX (); endY = (int) event. getY (); judgeDirection (endX-startX, endY-startY); if (isMoved () {addRandomNum (); // modify the display score Game. getGameActivity (). setScore (Config. scroe, 0);} int result = checkCompleted (); If (result = 0) {if (Config. scroe> highScore) {Editor editor = Config. sp. edit (); editor. putInt (Config. KEY_HighScore, Config. scroe); editor. commit ();} Toast. makeText (getContext (), "lose", Toast. LENGTH_LONG ). show (); Config. scroe = 0;} else if (result = 2) {Toast. makeText (getContext (), "success", Toast. LENGTH_LONG ). show (); Config. scroe = 0;} break; default: break;} return true;}/*** save history */ Private void saveHistoryMatrix () {scoreHistory = Config. scroe; for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {gameMatrixHistory [I] [j] = gameMatrix [I] [j]. getNum () ;}}/ *** determine the direction of movement based on the offset ** @ param offsetX * @ param offsetY */private void judgeDirection (int offsetX, int offsetY) {if (Math. abs (offsetX)> Math. abs (offsetY) {if (offsetX> 10) {swipeRight ();} else {swipeL Eft () ;}} else {if (offsetY> 10) {swipeDown () ;}else {swipeUp ();}}} /*** determine whether to end ** @ return 0: End 1: normal 2: Successful */private int checkCompleted () {getBlanks (); if (blanks. size () = 0) {for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {if (j <gameLines-1) {if (gameMatrix [I] [j]. getNum () = gameMatrix [I] [j + 1]. getNum () {return 1 ;}} if (I <gameLines-1) {if (gameMatrix [I] [j]. getNum () = gameMatrix [I + 1] [j]. getNum () {return 1 ;}}} return 0 ;}for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {if (gameMatrix [I] [j]. getNum () = 2048) {return 2 ;}} return 1 ;}/ *** determine whether to move (whether to add Item) ** @ return */private boolean isMoved () {for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {if (gameMatrixHistory [I] [j]! = GameMatrix [I] [j]. getNum () {return true ;}} return false;}/*** sliding event: top */private void swipeUp () {for (int I = 0; I <gameLines; I ++) {for (int j = 0; j <gameLines; j ++) {int currentNum = gameMatrix [j] [I]. getNum (); if (currentNum! = 0) {if (keyItemNum =-1) {keyItemNum = currentNum;} else {if (keyItemNum = currentNum) {calList. add (keyItemNum * 2); Config. scroe + = keyItemNum * 2; keyItemNum =-1;} else {calList. add (keyItemNum); keyItemNum = currentNum ;}} else {continue ;}} if (keyItemNum! =-1) {calList. add (keyItemNum);} // change the Item value for (int j = 0; j <calList. size (); j ++) {gameMatrix [j] [I]. setNum (calList. get (j);} for (int m = calList. size (); m <gameLines; m ++) {gameMatrix [m] [I]. setNum (0);} // reset the row parameter keyItemNum =-1; calList. clear () ;}/ *** slide event: Bottom */private void swipeDown () {for (int I = gameLines-1; I> = 0; I --) {for (int j = gameLines-1; j> = 0; j --) {int currentNum = g AmeMatrix [j] [I]. getNum (); if (currentNum! = 0) {if (keyItemNum =-1) {keyItemNum = currentNum;} else {if (keyItemNum = currentNum) {calList. add (keyItemNum * 2); Config. scroe + = keyItemNum * 2; keyItemNum =-1;} else {calList. add (keyItemNum); keyItemNum = currentNum ;}} else {continue ;}} if (keyItemNum! =-1) {calList. add (keyItemNum);} // change the Item value for (int j = 0; j <gameLines-calList. size (); j ++) {gameMatrix [j] [I]. setNum (0);} int index = calList. size ()-1; for (int m = gameLines-calList. size (); m <gameLines; m ++) {gameMatrix [m] [I]. setNum (calList. get (index); index --;} // reset the row parameter keyItemNum =-1; calList. clear (); index = 0 ;}}/*** sliding event: left */private void swipeLeft () {for (int I = 0; I <game Lines; I ++) {for (int j = 0; j <gameLines; j ++) {int currentNum = gameMatrix [I] [j]. getNum (); if (currentNum! = 0) {if (keyItemNum =-1) {keyItemNum = currentNum;} else {if (keyItemNum = currentNum) {calList. add (keyItemNum * 2); Config. scroe + = keyItemNum * 2; keyItemNum =-1;} else {calList. add (keyItemNum); keyItemNum = currentNum ;}} else {continue ;}} if (keyItemNum! =-1) {calList. add (keyItemNum);} // change the Item value for (int j = 0; j <calList. size (); j ++) {gameMatrix [I] [j]. setNum (calList. get (j);} for (int m = calList. size (); m <gameLines; m ++) {gameMatrix [I] [m]. setNum (0);} // reset the row parameter keyItemNum =-1; calList. clear () ;}}/*** slide event: right */private void swipeRight () {for (int I = gameLines-1; I> = 0; I --) {for (int j = gameLines-1; j> = 0; j --) {int currentNum = GameMatrix [I] [j]. getNum (); if (currentNum! = 0) {if (keyItemNum =-1) {keyItemNum = currentNum;} else {if (keyItemNum = currentNum) {calList. add (keyItemNum * 2); Config. scroe + = keyItemNum * 2; keyItemNum =-1;} else {calList. add (keyItemNum); keyItemNum = currentNum ;}} else {continue ;}} if (keyItemNum! =-1) {calList. add (keyItemNum);} // change the Item value for (int j = 0; j <gameLines-calList. size (); j ++) {gameMatrix [I] [j]. setNum (0);} int index = calList. size ()-1; for (int m = gameLines-calList. size (); m <gameLines; m ++) {gameMatrix [I] [m]. setNum (calList. get (index); index --;} // reset the row parameter keyItemNum =-1; calList. clear (); index = 0 ;}}}



PS source code is required. Please leave a message


PS source code is required. Please leave a message

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.