How to Implement hellope's Android Project)

Source: Internet
Author: User

This article introduces the architecture of the project, analyzes the functions, and develops the boardview class and time control class and introduces several interfaces. This time, we will complete the game board drawing and touch event processing, as well as the game core.AlgorithmAnd hints automatically help the algorithm and determine whether there is no solution to the algorithm. TheseCodeAre all processed in the gameview class inherited from the boardview class.

First, add the Code implementing the main algorithm of the game in the gameview class, that is, the Code connecting the algorithm (the icons used to determine the given two locations can be connected ):

/*** This game's core algorithm determines whether two connection points can be connected, the two points we click here are converted to the index value * @ Param P1 * @ Param P2 */list <point> p1expand = new arraylist <point> (); list <point> p2expand = new arraylist <point> (); Public Boolean Link (point P1, point P2) {If (p1.equals (P2) {return false;} path. clear (); If (Map [p1.x] [p1.y] = map [p2.x] [p2.y]) {If (linkdirect (P1, P2) {path. add (P1); Path. add (P2); Return true;}/*** an inflection point judgment */point PX = new point (p1.x, P 2. y); // assume that the first possible vertex is if (Map [p1.x] [p2.y] = 0 & linkdirect (P1, PX) & linkdirect (PX, P2 )) {path. add (P1); Path. add (PX); Path. add (P2); Return true;} Point py = new point (p2.x, p1.y ); // assume the second possible point is if (Map [p2.x] [p1.y] = 0 & linkdirect (P1, Py) & linkdirect (PY, P2 )) {// first, determine whether the map [p2.x] [p1.y] mediation point has an icon path. add (P1); Path. add (Py); Path. add (P2); Return true;}/*** two discount points (Corner) */expandx (P1, p1expand); expandx (P2, p2expand); For (INT I = 0; I <p1expand. size (); I ++) for (Int J = 0; j <p2expand. size (); j ++) {If (p1expand. get (I ). X = p2expand. get (j ). x) {If (linkdirect (p1expand. get (I), p2expand. get (j) {path. add (P1); Path. add (p1expand. get (I); Path. add (p2expand. get (j); Path. add (P2); Return true ;}} expandy (P1, p1expand); expandy (P2, p2expand); For (point exp1: p1expand) for (point exp2: p2expand) {If (exp1.y = exp2.y) {If (linkdirect (exp1, exp2) {path. add (P1); Path. add (exp1); Path. add (exp2); Path. add (P2); Return true ;}}return false; // The last three methods cannot be connected. Return false is required. Otherwise, no return value is returned under two identical icons !} Return false;}/*** determines whether a straight line link has no corner. The uploaded vertex value is screentoindex, but not necessarily the clicked vertex, it may also be our corner point (secondary point) * @ Param P1 * @ Param P2 */Public Boolean linkdirect (point P1, point P2) {// If (Map [p1.x] [p1.y] = map [p2.x] [p2.y]) {// vertical line if (p1.x = p2.x) {int Y1 = math. min (p1.y, p2.y); int y2 = math. max (p1.y, p2.y); Boolean flag = true; For (INT y = Y1 + 1; y <Y2; y ++) {// two adjacent conditions are easily missed in this loop, so the above flag style if (Map [p1.x] [Y] is added. = 0) {flag = false; break;} If (FLAG) {return true ;}// returns if (p1.y = p2.y) {int X1 = math. min (p1.x, p2.x); int X2 = math. max (p1.x, p2.x); Boolean flag = true; For (INT x = X1 + 1; x <X2; X ++) {If (Map [x] [p1.y]! = 0) {flag = false; break ;}} if (FLAG) {return true ;}///} return false ;}/ *** extends to X, the uploaded vertex is * @ Param p * @ Param list */Public void expandx (point P, list <point> List) {list. clear (); For (INT x = P. X + 1; x <xcount; X ++) {// note that the value of IF (Map [x] [p. y]! = 0) break; List. add (new point (X, p. y);} For (INT x = P. x-1; x> = 0; X --) {If (Map [x] [p. y]! = 0) break; List. add (new point (X, p. y);}/*** extends to Y. The passed vertices are indexed, list is the value to be saved as the "Return Value" * @ Param p * @ Param list */Public void expandy (point P, list <point> List) {list. clear (); For (INT y = P. Y + 1; y <ycount; y ++) {If (Map [p. x] [Y]! = 0) break; List. add (new point (P. x, Y);} For (INT y = P. y-1; y> = 0; y --) {If (Map [p. x] [Y]! = 0) break; List. Add (new point (p. x, y ));}}

Add comments as much as possible in the Code. In this code segment, algorithm analysis is implemented in the first article. Link (point P1, point P2) functions are truly complete implementers of the algorithm, the main logic of the algorithm is its implementation ,

linkdirect (point P1, point P2) the function is used as a tool function to determine the given two locations (note that it is not two icons, because the given position does not necessarily contain icons, when we determine

This is the case when" one-off "and" two-off "are used ). expandx (point P, list List) and expandy (point P, list List) is also used as a tool function,

It will be used when determining the "Twenty" situation, that is, the aforementioned "horizontal scan" and "vertical scan ". ForIn the Link (point P1, point P2) function, our logic is stillBig problems are converted into small problems.

Finally, it is decomposed into calls.The linkdirect (point P1, point P2) function is used to process a "Straight Line.

The above isProgramIn addition to understanding the program algorithm logic, you also need to note that when judging, if we can connect, we have

Private list <point> Path = new arraylist <point> (); Save the value attached to the path of the connected path. RememberLinkWhen the function returns true, a path is saved in the path!Finished

Connection algorithm. Next we will rely on the implementation of the connection algorithm to complete the scan to see if the current map has no solution, because the map of the program is randomly generated, sometimes there will be no solution;

The following describes how to determine whether a database is in the unsolvable state and implement the function:

/*** Is used to determine whether there is no solution currently */Public Boolean die () {for (INT y = 1; y <ycount; y ++) // indicates that an element in this row starts scanning (starting point) for (INT x = 1; x <xcount; X ++) {// indicates the specified column in this row, form the scanning start point if (Map [x] [Y]! = 0) {for (Int J = y; j <ycount; j ++) {// indicates the row being scanned if (j = y) {// Why is the first scan in a loop special? Because at this time it is not necessarily starting from the first element in a row to scan for (INT I = x + 1; I <xcount-1; I ++) {If (Map [x] [Y] = map [I] [J] & Link (new point (x, y), new point (I, j ))) {return false ;}} else {for (INT I = 1; I <xcount-1; I ++) {If (Map [x] [Y] = map [I] [J] & Link (new point (x, y), new point (I, j ))) return false ;}}}return true ;}

The Code also has corresponding comments. Each judgment is equivalent to traversing the board. Note that if the die () function returns false, this proves that the link () function returns true! We have already reminded you that when link returns true, we will save the set of points in a connection path in the path object of the connection path, but in die () the function runs in the traversal order, not the two start points and end points we specify. Therefore, you can use die () to judge, complete the third feature of our algorithm implementation, that is, the automatic help of hint!

/*** Called when the Help button is clicked, it will help players eliminate a pair of icons */Public void autohelp () {If (help = 0) {// soundplay. play (id_sound_error, 0); return;} else {// soundplay. play (id_sound_tip, 0); help --; toolschangedlistener. ontipchanged (HELP); drawline (path. toarray (new point [] {}); refreshhandler. sendrefresh (500 );}}

Of course, here we need to introduce the origins of the last line of code:

 
Class refreshhandler extends handler {@ overridepublic void handlemessage (Message MSG) {super. handlemessage (MSG); If (MSG. what = refresh_view) {gameview. this. invalidate (); If (WIN () {setmode (WIN); isstop = true; iscontinue = false;} else if (die () {// call the die method once! In this case, if the return value of die is false, change () can be connected. // The value in path is added because the link method is used in die ,} // This is convenient for us to use the autohelp Method !!!}} /***** @ Param delaytime */Public void sendrefresh (INT delaytime) {message MSG = new message (); this. removemessages (0); MSG. what = refresh_view; this. sendmessagedelayed (MSG, delaytime );}}

Of course, it is relatively simple to determine whether or not the WIN () function is used to scan the board. If the MAP value at all locations is 0, it will win. If not, it will not be completed; no code is posted here.

Another function of the gameview class is to initialize a board:

 
/*** Initialize map */Public void initmap () {int x = 1; int y = 0; For (INT I = 1; I <xcount-1; I ++) for (Int J = 1; j <ycount-1; j ++) {map [I] [J] = x; If (y = 1) {x ++; y = 0; If (x = iconcounts) {x = 1 ;}} else {y = 1 ;}} change (); gameview. this. invalidate ();}

When initializing a board, we use the initial algorithm technology described above to traverse the board and fill the board first, but there is also a rule that each icon must be filled with two at the same time, is set for each type of icon for an even number! The change () function called at the end is also based on the initial algorithm of the first board. It is used to randomly disrupt the icons in the Board:

/*** Randomly disrupt the existing layout and re-deploy it. The number of existing icons in the map remains unchanged, which is equivalent to a refresh */Public void change () {random = new random (); int TMP, xtmp, ytmp; For (INT x = 1; x <xcount-1; X ++) {for (INT y = 1; y <ycount-1; Y ++) {xtmp = 1 + random. nextint (xcount-2); ytmp = 1 + random. nextint (ycount-2); TMP = map [x] [Y]; Map [x] [Y] = map [xtmp] [ytmp]; map [xtmp] [ytmp] = TMP ;}} if (die () {// if no solution is available, change () needs to be randomly disrupted again ();}}

The gameview class is still a view. In this class, we also need to override the ontouchevent method of the View:

/*** For processing the selection, if it is the first press, it will be added to the selected, * if it is the second (selected. size () = 1), first determine whether it can connect */@ overridepublic Boolean ontouchevent (motionevent event) {int SX = (INT) event. getx (); int Sy = (INT) event. gety (); point P = screentoindex (sx, Sy); If (Map [p. x] [p. y]! = 0) {If (selected. size () = 1) {If (Link (selected. get (0), p) {// It can be connected. If the data in the path is returned when the link determines, the data has been added to the selected method. add (p); drawline (path. toarray (new point [] {}); refreshhandler. sendrefresh (500);} else {// selected cannot be connected. clear (); selected. add (p); gameview. this. invalidate (); // refreshhanler here. sendrefresh (INT) is called by gameview. this. invalidate () Difference // in addition to the refresh display of the latter, the former also adds an operation to determine whether there is no solution and whether the task has been completed .}} Else {// The size in selected can only be equal to 0selected. Add (p); gameview. This. invalidate () ;}} return Super. ontouchevent (event );}

The selected used in the method is the protected list <point> selected = new arraylist <point> () in the boardview; the function and implementation are annotated in the code.

At this point, we can provide the startgame interface for calling in the activity of the program:

 
Public void startplay () {help = 3; refresh = 3; iscontinue = true; isstop = false; toolschangedlistener. onrefreshchanged (refresh); toolschangedlistener. ontipchanged (HELP); lefttime = totaltime; initmap (); refreshtime = new refreshtime (); thread t = new thread (refreshtime ); // correctly start a Thread class t that implements the runnable interface. start (); gameview. this. invalidate ();}

Note that the gameview does not implement related custom interfaces, but we will implement the three interfaces involved in the project in the program activity. However, we can register in gameview:

 
Public void setontimerlistener (ontimerlistener) {This. timerlistener = ontimerlistener;} public void setontoolschangedlistener (ontoolschangelistener toolschangelistener) {This. toolschangedlistener = toolschangelistener;} public void setonstatechangelistener (onstatelistener statelistener) {This. statelistener = statelistener ;}

Then, call the relevant functions of gameview in the activity of the Program for initialization registration. In this way, according to the principle of polymorphism, the functions in the related interfaces called in the gameview, that is, the functions in the interfaces implemented in the activity. This is also a way to implement and register interfaces in Android programs.

The above describes the functions and main implementations of gameview. In summary, the map Initialization is implemented, the touch time processing function is rewritten, and the connection algorithm of the program is completed. The hint automatically helps the algorithm and the no-solution judgment algorithm of the die, there is also the implementation of internal classes inherited from handler for update display. The entire project has been basically formed.

I would like to reiterate that this seriesArticleIn order to record the experiences of small Android projects and increase the practical capabilities, we will make a summary. Not just to make a novel project, but also to learn from many netizens!

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.