Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Android 5: Wari 1 2 Introduction • This set of overheads is more than just Wari • It begins with a simple app where the sendMessage() method is small, but contains some significant code • It is a lead-in to debugging • As soon as code gets more complicated you have to be able to debug • It is also a lead-in to the code for Wari 3 • Wari illustrates both code logic and a more complicated layout • There are two perspectives on what’s going on: • First of all, it should be apparent that things are easier because GUI layout work is separate from the Java code • On the other hand, in order to deal with this separation between logic and layout, the implementation of Wari will differ significantly from implementations you’ve seen before 4 • • • • • • • • 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 The OneButtonRecursion app Unhelpful Error Messages Logging Output Wari—General Remarks layout.xml for Wari strings.xml for Wari R.java for Wari MainActivity.java for Wari 5 5.1 The OneButtonRecursion app • The OneButtonRecursion app will be presented in the order in which it was developed: • 1. activity_main.xml, the layout • 2. strings.xml, the resources • 3. Look at R.java, the resources as made available by the system • 4. MainActivity.java, the code for the app 6 • As you might guess, part of what makes the app interesting is the fact that it includes recursion • This is a preview of the fact that recursion will be used in the implementation of Wari 7 • The other thing that makes the app interesting, and relevant to Wari, is that the contents of the text view are changeable, and are treated as an integer • This introduces some syntax, which in turn, introduces the possibility of errors • These errors turn out to be runtime errors, so it behooves us to consider the topic of debugging in Android 8 activity_main.xml for OneButtonRecursion • A screenshot of the layout of the OneButtonRecursion app in the development environment is shown on the following overhead • It is a simple layout, containing a button and a text view 9 10 • This app happens to use relative layout • There is nothing particularly striking about the syntax for that • The XML code for the layout is given on the following overheads for reference 11 • • • • • • • • • <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > 12 • <Button • android:id="@+id/button1" • style="?android:attr/buttonStyleSmall" • android:layout_width="wrap_content" • android:layout_height="wrap_content" • android:layout_alignParentLeft="true" • android:layout_alignParentTop="true" • android:text="@string/button1Contents" • android:onClick="sendMessage" /> 13 • • • • • • • • • • <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button1" android:layout_alignBottom="@+id/button1" android:layout_toRightOf="@+id/button1" android:text="@string/textView1Contents" /> </RelativeLayout> 14 • There were some items in the XML that haven’t come up before • Where did they come from? • If you use the graphical tools to create the basic layout, the system will generate the XML • You can then edit the XML, if necessary, to tailor the layout to the specific app you’re trying to create 15 strings.xml for OneButtonRecursion • The strings.xml file for the app is shown on the following overhead • There are no surprises • The button and the text view have string resources associated with them 16 • • • • • • • • • <?xml version="1.0" encoding="utf-8"?> <resources> <string <string <string <string <string name="app_name">One Button Recursion</string> name="action_settings">Settings</string> name="hello_world">Hello world!</string> name="button1Contents">Button1</string> name="textView1Contents">4</string> </resources> 17 R.Java for OneButtonRecursion • As you recall, the R.java file is generated for you • It’s important because it’s the place where you can access resources when writing the Java code for MainActivity • The relevant parts of R.java are shown on the following overhead 18 • • • • • • • • • • • public static final class id { … public static final int button1=0x7f080000; public static final int textView1=0x7f080001; } … } public static final class string { … public static final int button1Contents=0x7f050003; public static final int textView1Contents=0x7f050004; 19 MainActivity.java for OneButtonRecursion • The logic of OneButtonRecursion is quite simple • The TextView is initially set to a value of 4 • When you click the button, you call sendMessage() 20 • sendMessage() checks to see what the current value is • If the value is >0, then a call is made to a method named playNextCup() and the value is passed in 21 • playNextCup() decrements the value • It updates the text area to this new value • If the value has not yet reached 0, it calls itself recursively • The end result of this sequence of actions is that the value in the text view goes 4, 3, 2, 1, 0—too fast for the eye to see • One click of the button causes the text view to go from 4 to 0, recursively 22 • The logic is simple, but the code will look needlessly complex • It repeatedly gets a handle on the text view and passes this around—which is needless, considering there is only one text area • It also includes if statements to check “which button was clicked” when there is only one button 23 • The code is written in this way because it is a preview of what will have to be done to implement Wari • It is clumsy here, but it’s easier to first get an idea of what’s involved in a mindless recursion program with only one text view and one button 24 • Then, in an app with >1 text view and button, it becomes apparent that it is necessary to repeatedly get references and pass them around and check which button was clicked 25 An Import and a Declaration and Initialization for Debugging • The import of the Log class and the TAG string definition shown here will be useful for logging and debugging • They come at the beginning of the MainActivity class, so they are shown now • Further explanations will be given later • import android.util.Log; • public class MainActivity extends Activity { • private static final String TAG = "OneButtonRecursion"; • … 26 sendMessage() for OneButtonRecursion • The code for sendMessage() is shown on the following overhead • Note that the calls to findViewById() and playNextCup() are floating in space • They are calls on the MainActivity itself • The concept of activities is important and will be pursued further in later sets of overheads 27 • • public void sendMessage(View view) { Button clickedButton = (Button) view; • • • • • • • • • if(clickedButton == findViewById(R.id.button1)) { TextView cup = (TextView) findViewById(R.id.textView1); int handFull = Integer.parseInt(cup.getText().toString()); if(handFull > 0) { cup.setText(handFull + ""); playNextCup((TextView) findViewById(R.id.textView1), handFull); } • } • • • • else { } } 28 playNextCup() for OneButtonRecursion • playNextCup() contains the recursive call • It also contains the uses of Log and TAG • These will be explained in a moment 29 • • • • • • • • • • • • • public static void playNextCup(TextView cupIn, int handFullIn) { handFullIn--; cupIn.setText(handFullIn + ""); if(handFullIn != 0) { playNextCup(cupIn, handFullIn); Log.i(TAG, "In recursion " + handFullIn); } else { } } 30 5.2 Unhelpful Error Messages • When writing the code even for this simple app, I made mistakes (go figure) • It quickly became apparent that I would need to be able to debug in the Android environment • I’m not referring now to the debugging tools in Eclipse—they’re beyond the scope of this course • I’m referring to simply figuring out what was going on 31 • Compiler errors are shown at the bottom of the screen under the “Problems” tab, and they’re marked in red there and flagged in your code • You will find that Eclipse has a helpful “Quick Fix” tool that frequently tells you pretty clearly what’s wrong and how to fix it • These things are illustrated on the following overhead 32 33 • I also got two good (bad) examples with OneButtonRecursion of what can go more seriously wrong and the quandary you’re left in • These were runtime errors, and they illustrated two features of the development environment 34 • 1. In Java programming, you may be used to the fact that even runtime errors show the line numbers in your code where the errors occur • This does not appear to be the case with Android • You do see a trace of calls, but it’s up to you to figure out where that trace intersects your code and the exact location of the problem 35 • 2. The second aspect accounts for the heading of this section • Like with many systems, the error messages are not necessarily helpful • As usual, being able to look the error message up on the Web was very helpful in trying to figure out what it meant 36 Example 1 • Here is a snippet of code that’s in error: • • • int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull); • Here is the error message you get: • No package identifier when getting value for resource number HideousHexValue 37 • This is not helpful • It seems to suggest some deep problem with the use of resources (like the values in R.java) or maybe with passing parameters, like the activity, around • It doesn’t identify which method call is the source of the problem 38 • The explanation turns out to be much simpler • When writing the incorrect code, I heedlessly assumed that setText() converted whatever parameter was sent to it to a string by an internal call to toString() • This is not so • There is a version of setText() which accepts an integer parameter, where the integer is the id for a resource 39 • The value contained in handFull doesn’t agree with any defined resource id value, so the system has a runtime problem • (Imagine the fun you’d have if, by accident, handFull did contain a valid resource id, and you got inexplicable results instead of a runtime error) 40 • In any case, once you know what’s wrong, the solution is simple • This is the corrected code: • • • int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull + “”); 41 Example 2 • The same two lines of code contain a call that can also generate another unhelpful runtime error • • • int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull + “”); • Consider the call to parseInt() • parseInt() will fail if you apply it to a string that can’t be parsed as an integer 42 • If you write the code as shown and the text view you’re getting the string from doesn’t contain an integer • You will get this runtime error message: • FATAL EXCEPTION: main java.lang.IllegalStateException • It sounds grievous, doesn’t it? 43 • The tracing of calls that’s presented eventually reaches the parseInt() call, but it’s not immediately apparent what it is about that call that’s causing such a serious problem • The error message obviously doesn’t tell you something simple, like the parameter passed to the method isn’t right 44 • This kind of problem is the result of simple carelessness in coding • A runtime error can be avoided by careful coding or by putting the call in a try catch block • As a garden variety programmer, I made the mistake • Because the error message wasn’t helpful, I had to sort this out with old fashioned debugging, the topic of the next section 45 5.3 Logging Output • A screenshot of the current example is shown on the following overhead • The playNext() method is shown in the editor • The LogCat tab has been selected at the bottom • This shows the non-graphical output of the app 46 47 • In order to do simple debugging, you need to be able to print output strings from your code, like calling System.out.println() in Java code • The Android system will write to LogCat • The programmer can also send non-graphical output there 48 • These are the lines of code in the application related to logging • import android.util.Log; • public class MainActivity extends Activity { • • • private static final String TAG = "OneButtonRecursion"; … Log.i(TAG, "In recursion " + handFullIn); 49 • In order to write to LogCat you need to import the Log class • Log contains static methods, like “i”, which stands for “information” (as opposed to println() for System.out) • These log methods take two strings as parameters, a tag, and the actual output 50 • It’s simplest to just define a TAG so that every line from a given app is clearly identified in the LogCat • Then at strategic places put calls to Log.i() to see what’s happening • Eclipse has fancier debugging tools, but I’ve always done it by hand in this way 51 An Example • On the following overhead is a block of code that gave me a runtime error • As noted earlier, the runtime error messages are not always as helpful as they might be • You’re not told which line of code caused the runtime error • I couldn’t tell what exactly was wrong—it was the highlighted parseInt() call 52 • TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView16); • int capturedCount = Integer.parseInt(capturedCup.getText().toString()); • capturedCount += seedCount; • capturedCup.setText(capturedCount + ""); 53 • The code on the following overhead shows how I picked the block apart and was able to identify exactly which line and which call was causing the problem 54 • • • /* Debugging code /* Log.i(TAG, "1"); • TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView16); • Log.i(TAG, "2, capturedCup id: • CharSequence tempText = capturedCup.getText(); • Log.i(TAG, "3"); • String tempString = tempText.toString(); • Log.i(TAG, "4, tempString contents of capturedCup: • int capturedCount = Integer.parseInt(tempString); • Log.i(TAG, "5"); • capturedCount += seedCount; • Log.i(TAG, "6"); • capturedCup.setText("x"); //(capturedCount + ""); • • Log.i(TAG, "7"); */ */ " + capturedCup); " + tempString); 55 5.4 Wari—General Remarks 56 Wari in CSCE 202 • Obviously, the point of using Wari as an example is that it needs no introduction • For those who didn’t take CSCE 202 from me, go to the link for that course on my Web page for full information • May the tutelary deities of Wari be your guide 57 58 59 • You may recall these characteristics of the implementation of Wari in CSCE 202 • There was a Cup class • The board consisted of an array of cups • Each cup contained a reference to the next cup, so they were linked together in circular fashion, the way play progressed around the board 60 • The cups also had text fields • In assembling the overall graphical user interface for the application, the text fields belonging to the cups were presented in panels on the screen • The design was approaching a model-viewcontroller design, but it’s true that components were still tightly integrated 61 • In Java, with the information given in CSCE 202, it was not so hard to simply create a “dead” graphical user interface, with all of the visual components displayed on the screen but no functionality • The purpose of this brief review is remind you of the issues of layout, design, and functionality as they were introduced when working with Java swing 62 Wari in Android • As you have already seen, although based on Java code, the tools for Android app design are different • This is a simple description of the plan for developing Android apps: • Using widgets, develop a graphical layout (activity_main.xml) • Acquire handles on these widgets through R.java • Use these widgets in your Java code, MainActivity.java 63 • The widgets and their layout are separately defined in their own XML file • They have a life of their own independent of the MainActivity.java source file • In other words, there’s been no indication so far that an Android version of Wari would mimic the straight Java implementation 64 • Although it may be possible, there’s been no consideration of the following: • Constructing arrays of widgets • Devising application classes where instance variables of those classes are widgets • Trying to link widgets or objects containing them together • In fact, you can do swing-like things in an Android app, but it is not the default approach, and it can be counterproductive 65 • The goal of the Wari example given in this set of overheads is to implement roughly the same functionality as the swing version in Java • But the intention is not to try and duplicate the earlier implementation, where the game logic and the graphical view were integrated into the same Java code 66 • The goal is to take the default Android approach and implement the same functionality while leaving the widgets as independent graphical items in the interface • The implementation will still use buttons for play • This introduces another Android constraint: • There will be one sendMessage() method for the app • It will handle clicks from all of the buttons in the GUI 67 Implementation Approach • The fundamental beginning step in Wari is picking a cup to play • If the cup contains seeds, you then move to the next cup • The description so far implies that in the Android app, the widgets representing the cups won’t be linked 68 • If the cups aren’t linked together by references, how can you implement moving from one cup to another in this way? • The cups can be linked together functionally, by logic in the method that is called when a button is clicked to play a cup 69 • The method needs to identify the cup that was clicked • The method code will contain a sequence of if/else if statements that encapsulate this logic, hardcoding the id’s of the cups: • If you’re on cup x, the next cup is y; else if you’re on cup y, the next cup is z; and so on, all the way around the board 70 • You can progress around the board as far as needed and no further by doing recursion on the value of handFull that you pick up in the first cup • (Note the similarity with simple example given earlier) • The stopping condition is easy and natural: • When the handFull is empty (== 0) you’re done 71 Coming Attractions • This unit contains the first assignment, where you’re expected to implement something Wari-like as an Android app • In the following sections, further explanations will be given of how to do this, some example code will be shown, but complete code will not be given or posted 72 • It will be up to you to fill in the missing spaces and get it to work • I know it can be done because I did it • The incomplete example work you’re being shown consists of selections from the code of a working app 73 5.5 layout.xml for Wari • Step 1: Create a layout that presents a Wari-like interface with the necessary components • I used buttons for play and text views to hold the contents of cups • I decided to use a table layout • Android has something called a grid layout, but it’s not exactly the same as a Java grid layout • The Android table layout is similar to a Java grid layout 74 • I decided that it would be helpful to use the graphical tools in Android rather than trying to master the XML syntax • This was not trouble-free 75 • More than once I had to start over and create components in a different order so that the default names they received would be consistent with the logic of their use in my code • There were 12 buttons and 12 text views in the layout • I wanted them numbered 1-12 in the order they would be played in the game 76 • I also discovered that my machine was underpowered or something • Some of the tools caused my system to crash • The main lesson there was don’t touch those tools • I tried to upgrade to a different machine, but it was impossible to install the Google driver, so I was stuck with the lesser of two evils 77 • The following overhead shows a screenshot of my layout in the development environment • I’m showing you this in order to remind you of the graphical tools • My layout consisted entirely of text view and small buttons • Notice that among the tools is an option to choose a layout • This is where I found the table layout 78 79 • The following overheads show the XML code that was generated up through the first row of the table layout • The full file goes on at length • This is where you can check to see what default names your widgets are being given • They are numbered in creation order • Your code doesn’t have to be the same, but it will at least be similar 80 • • • • • • <?xml version="1.0" encoding="utf-8"?> <!-- This is the activity_main.xml file for Wari. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/androi d" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > • • • • • <TextView android:id="@+id/textView13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/textView13Contents" /> • • • • • <TextView android:id="@+id/textView14" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/textView14Contents" /> 81 • • • • • • • <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TableRow android:id="@+id/tableRow1" android:layout_width="wrap_content" android:layout_height="wrap_content" > • • • • • • • <Button android:id="@+id/button1" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button1Contents" android:onClick="sendMessage" /> • • • • • <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/textView1Contents" /> 82 • • • • • • • • • • • • • • • • • • <TextView android:id="@+id/filler1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/filler" /> <TextView android:id="@+id/textView12" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/textView12Contents" /> <Button android:id="@+id/button12" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button12Contents" android:onClick="sendMessage" /> 83 5.6 strings.xml for Wari • Creating a strings.xml file for an app isn’t too difficult • Largely you can just copy the layout.xml file as your starting point and then edit it • It already contains all of the named items that were created in the layout that are referred to in strings.xml • The first step is deleting all of the layout specific stuff surrounding these names 84 • In strings.xml you give these named items initial values • You replace the stuff you removed with the right syntax for a strings.xml file • You can also add any other strings necessary for your app • A subset of the code for strings.xml for Wari is shown on the following overhead 85 • • <?xml version="1.0" encoding="utf-8"?> <resources> • • • • • <string <string <string <string … • • • <string name="textView1Contents">4</string> <string name="textView2Contents">4</string> … • <string name="filler">" • </resources> name="app_name">Wari</string> name="action_settings">Settings</string> name="button1Contents">P1, C1</string> name="button2Contents">P1, C2</string> "</string> 86 • What I’m saying is that you start with something like this: • • • • • <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/textView1Contents" /> • And you use it as the starting point to make this, for example: • <string name="textView1Contents">4</string> 87 5.7 R.java for Wari • As you recall, R.java is auto-generated • If your layout and strings files were complete, R.java will have everything you need in it • The point is that when writing the code for MainActivity.java, you refer to R.java • A subset of R.java is shown on the following overhead 88 • • • • • • • • • • … public final class R { … public static final class id { public static final int action_settings=0x7f080028; public static final int button1=0x7f080003; public static final int button10=0x7f080013; public static final int button11=0x7f08000d; public static final int button12=0x7f080007; public static final int button2=0x7f080009; 89 5.8 MainActivity.java for Wari • There is nothing special about the onCreate() and onCreateOptionsMenu() methods for Wari • They’re just copied as usual • There’s also nothing unusual about the imports • Some need to be added so that the code can work with various classes, but they won’t be detailed • The logic of the app is in the sendMessage() and playNextCup() methods 90 sendMessage() for Wari • As always, sendMessage() is the method called on a button click • This is critically important to this application: • Each of the 12 buttons in Wari is linked to the one sendMessage() method 91 • This goes back to a discussion that occurs at the end of CSCE 202 • You may recall that it’s possible to have one event and many listeners • It’s also possible to have many events and one listener 92 • You may also recall that in the development of Wari in swing, the possibility of having a listener full of if statements was mentioned in passing and rejected as not the ideal solution • We have now come full circle • sendMessage() is like a common listener for clicks on multiple different buttons 93 • sendMessage() determines which button was clicked • There is then a series of if statements • In each if statement, effectively the same logic is implemented • The different cases only differ by which button/cup/next cup are involved 94 • Not only is this method the one listener for all of the buttons • This is the part of the app code that creates the functional connection between the different, independent widgets in the app • In other words, sendMessage() functionally implements the structure of the game board • The sendMessage() method calls the playNextCup() method, which implements the logic of playing the game 95 • The if/else if code in sendMessage() is highly redundant • No claim is made that this is the ideal solution • It is presented as a quick and dirty approach which is relatively easy to understand in the context of Android widgets • The redundancy actually makes it easy to write • You just copy and paste and change the numbers identifying the buttons and cups 96 • The first two if cases for the sendMessage() method are shown on the following overhead • The full method just continues the pattern • If you need more knowledge in order to understand what’s going, you’ll have to figure it out • In other words, this is part of what you’ll do for the assignment 97 • • public void sendMessage(View view) { Button clickedButton = (Button) view; • • • • if(clickedButton == findViewById(R.id.button1)) { TextView cup = (TextView) findViewById(R.id.textView1); int handFull = Integer.parseInt(cup.getText().toString()); • • • • if(handFull > 0) { cup.setText("0"); playNextCup(this, (TextView) findViewById(R.id.textView2), handFull); } } else if(clickedButton == findViewById(R.id.button2)) { TextView cup = (TextView) findViewById(R.id.textView2); int handFull = Integer.parseInt(cup.getText().toString()); • • • • • • • • • • • • • if(handFull > 0) { cup.setText("0"); playNextCup(this, (TextView) findViewById(R.id.textView3), handFull); } } … 98 • There is one last thing to mention because it’s a segue into an important aspect of the playNextCup() method, which will be the next topic • Note the calls to findViewById() • This has come up before, but it bears repeating: • These calls are floating in space 99 • When the app runs, an instance of the MainActivity class is what’s running on the Dalvik Virtual Machine • The calls on the implicit parameter are on this activity, the MainActivity • This is relevant to playNextCup() and the concept is important overall and will be discussed in greater depth in the future 100 playNextCup() for Wari • playNextCup() is the method that’s called if a player clicks a cup that is not empty • It is a recursive method that jumps to the next cup in line • Each successive recursive call jumps to the succeeding cup on the board • Seeds continue being dropped in each cup until handFull is empty • This is the condition that ends the recursion 101 • playNextCup() is redundant, like sendMessage() • Just like in sendMessage(), it’s necessary to know which cup is being played • Which is the next cup is determined by which is the current cup • Since the cups are found by their id, there has to be a separate case for each of the 12 cups on the board 102 • Again, the fact that the code is redundant actually makes it relatively easy to write • Figure out one of the cases • Then copy and paste and change the numbers identifying the cups 103 • The code for this method does have an additional characteristic that needs to be brought out • It’s already evident in the signature line, which is shown here: • public static void playNextCup(Activity activityIn, TextView cupIn, int handFullIn) 104 • Not only does the logic of play and recursion require that the cup and handFull be passed in • The first parameter passed to the method is an activity • If you go back to sendMessage(), the calls look like this, for example: • playNextCup(this, (TextView) findViewById(R.id.textView3), handFull); • The activity that is passed in is the MainActivity 105 • Passing in this parameter supports calls like these in the body of the method: • activityIn.findViewById(R.id.textView1) • findViewById() is called on the activity • findViewById() was also called on the activity in sendMessage(), but it was a call floating in space • It wasn’t necessary to make the call on “this” 106 • In playNextCup() you will get a compiler error if you don’t pass in the activity so you can call findViewById() on it • This is the message: • “Cannot make a static reference to the nonstatic findViewById(int) from the type Activity” 107 • This error message is more helpful than the ones previously looked at • playNextCup() is a recursive method which is declared static • The error message is telling you that in a static method there is no “this”, there is no object, which findViewById() can be called on • Therefore, in order to make the implementation work, you have to pass in MainActivity when making the call to playNextCup() 108 • The first two if cases for the playNextCup() method are shown on the following overheads • The full method just continues the pattern • If you need more knowledge in order to understand what’s going, you’ll have to figure it out • In other words, this is just like sendMessage() • Doing this is part of what you’ll do for the assignment 109 • • • • • • • • • • • • • • • • • • • • • public static void playNextCup(Activity activityIn, TextView cupIn, int handFullIn) { handFullIn--; if(cupIn == activityIn.findViewById(R.id.textView1)) { TextView nextCup = (TextView) activityIn.findViewById(R.id.textView2); int seedCount = Integer.parseInt(cupIn.getText().toString()); seedCount++; cupIn.setText(seedCount + ""); if(handFullIn != 0) { playNextCup(activityIn, nextCup, handFullIn); } else if(seedCount == 2 || seedCount == 3) { TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView14); int capturedCount = Integer.parseInt(capturedCup.getText().toString()); capturedCount += seedCount; capturedCup.setText(capturedCount + ""); } } 110 • • • • • • • • • • • • • • • • • • • else if(cupIn == activityIn.findViewById(R.id.textView2)) { TextView nextCup = (TextView) activityIn.findViewById(R.id.textView3); int seedCount = Integer.parseInt(cupIn.getText().toString()); seedCount++; cupIn.setText(seedCount + ""); if(handFullIn != 0) { playNextCup(activityIn, nextCup, handFullIn); } else if(seedCount == 2 || seedCount == 3) { TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView14); int capturedCount = Integer.parseInt(capturedCup.getText().toString()); capturedCount += seedCount; capturedCup.setText(capturedCount + ""); } } … 111 Summary and Assignment • • • • The summary is simple: Can you do this? The assignment is equally simple: Do this. Implement Wari or Togiz Kumalak You get to choose the number of cups per side and the initial number of seeds per cup, as long they are >= 6 and 4, respectively 112 • You will turn this in by demonstrating your app to me on your tablet or whatever Android device you’ve decided to develop on • You can come to my office to do this • You can do it any time on or before the due date • I’m begging you, please, don’t push this beyond the due date • I make this humble entreaty because it’s for your own good… 113 The End 114