This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Beginning Scripting Through Game Creation Jeanine Meyer Publisher and General Manager, Course Technology PTR: Stacy L. Hiquet Associate Director of Marketing: Sarah Panella Manager of Editorial Services: Heather Talbot
2008 Course Technology, a part of Cengage Learning. C
ALL RIGHTS RESERVED. No part of this work covered by the copyright herein may be reproduced, transmitted, stored, or used in any form or by any means graphic, electronic, or mechanical, including but not limited to photocopying, recording, scanning, digitizing, taping, Web distribution, information networks, or information storage and retrieval systems, except as permitted under Section 107 or 108 of the 1976 United States Copyright Act, without the prior written permission of the publisher.
Marketing Manager: Jordan Casey Acquisitions Editor: Heather Hurley Project/Copy Editor: Karen A. Gill Technical Reviewer: Jason Darby PTR Editorial Services Coordinator: Erin Johnson Interior Layout Tech: ICC Macmillan Inc.
For product information and technology assistance, contact us at Cengage Learning Customer & Sales Support, 1-800-354-9706 For permission to use material from this text or product, submit all requests online at cengage.com/permissions Further permissions questions can be e-mailed to [email protected]
Cover Designer: Mike Tanamachi Indexer: Kevin Broccoli
Library of Congress Control Number: 2007941721
Proofreader: Kim Benbow
ISBN-13: 978-1-59863-511-9 ISBN-10: 1-59863-511-5 eISBN-10: 1-59863-670-7 Course Technology 25 Thomson Place Boston, MA 02210 USA
Cengage Learning is a leading provider of customized learning solutions with office locations around the globe, including Singapore, the United Kingdom, Australia, Mexico, Brazil, and Japan. Locate your local office at: international.cengage.com/region Cengage Learning products are represented in Canada by Nelson Education, Ltd. For your lifelong learning solutions, visit courseptr.com Visit our corporate Web site at cengage.com
Printed in the United States of America 1 2 3 4 5 6 7 11 10 09 08
To Esther, Daniel, Aviva, and Anne, and to Joseph Minkin, who is still part of my life
Acknowledgments
I want to thank my students and colleagues at Purchase College/SUNY, project editor Karen Gill, and technical reviewer Jason Darby for their contributions to this project.
About the Author
Jeanine Meyer started programming at the University of Chicago while majoring in mathematics, before it was possible to major in computer science. She received an M.A. in mathematics from Columbia University and then worked in computing at various major companies before earning her Ph.D. from New York University. Jeanine joined IBM Research in Yorktown Heights, New York, working in the robotics group. She produced one of the first applications for the IBM PC, a programming system for a robot. She later became a manager in manufacturing systems and then a research consultant for IBM’s educational grants. Jeanine was one of many people who were captivated by computer games such as Tetris. When she left IBM to become a teacher, first at Pace University and later at Purchase College/SUNY, she decided that making games would be an excellent way to engage students in learning programming, not just because games are fun, but because they are challenging to build. Jeanine is a tenured, full professor, the coordinator of the Mathematics/ Computer Science Board of Study, and a member of the New Media Board of Study. She’s authored three textbooks prior to this one, written numerous academic papers, and makes presentations at conferences on a variety of topics. She is a member of Phi Beta Kappa, Sigma Xi, the Association for Women in Science, and the Association of Computing Machinery. In addition, she is a featured reviewer for ACM Computing Reviews and is a frequent panelist for National Science Foundation grants.
vi
About the Author
When she’s not programming, Jeanine enjoys politics, origami, gardening, knitting, crocheting, cooking, and eating. She presently is building the Hudson Trail, a long hiking trail from Manhattan to Mt. Marcy with Bob Jessen, her partner in many things. (See their blog at http://hudsontrail.wordpress.com.) If you have comments or questions about this book, you can reach Jeanine at [email protected]. Feel free to also look at her academic activities by visiting http://newmedia.purchase.edu/~Jeanine.
Beginning Scripting Through Game Creation is an introduction to scripting, focusing on logic, event handling, and application development. The major examples in the text are done using Hypertext Markup Language (HTML) with JavaScript. Most of the sample projects are simple games. Games are used because they provide challenging but understandable examples, and the users, the players, are easy to keep in mind when doing the work. Practically all the games are one-player. With the exception of Rock, Paper, Scissors, in which the computer’s moves are defined by a calculation using a pseudo-random facility, the computer program does not play the game, but provides the environment and enforces the rules. The goal of this book is to help the reader understand fundamental concepts in scripting and programming by examining the concepts in actual use in interesting applications. Much of the discussion is language-independent; that is, it applies to a variety of computer languages. However, the approach is for the readers to see and practice producing working examples for themselves. This means time spent on the details of specific programming languages and comparisons between different languages.
How Much You Should Know This book is aimed at beginners in terms of scripting or programming. However, you do need to be comfortable using a computer, keeping track of files, and using a browser to access the Web. xiv
Introduction
If you have surfed the Web, you definitely have viewed pages made using HTML. If any of the sites you visited involved dynamic (changing) content, you probably saw JavaScript in use. It is possible to produce the applications featured in this text because of the inherent power in programming systems such as HTML with JavaScript. The applications are run using the powerful software products called browsers, the tools you use to surf the Web. It is your code with the browser code that provides the functionality for your work. Game programming is difficult, but fun. It exercises your creativity. You can build on these simple projects to make them your own.
How to Use This Book The requirement to produce working programs from the very beginning means that several concepts and mechanisms need to be explained quickly just to get started. The text returns to the important concepts over and over. Each chapter begins with ‘‘Motivating Example,’’ continues with ‘‘Introduction to Concepts,’’ and moves on to presenting the implementation with ‘‘Review of Previous Examples’’ (if applicable), ‘‘Plan of Attack,’’ ‘‘Use of Concepts in Implementation,’’ and ‘‘What Can Go Wrong.’’ At the end, the ‘‘Chapter Summary’’ contains ‘‘What You Have Learned,’’ ‘‘In the Real World,’’ ‘‘What’s Next,’’ ‘‘Review Questions,’’ and ‘‘On Your Own,’’ a section describing projects. Read the whole chapter first and then, if you want to reproduce the examples for yourself, which is highly recommended, go back to the implementation sections, starting with ‘‘Plan of Attack,’’ and study and copy the scripts using a text editor. The book will tell you what image files to create. Follow the suggestions for working incrementally; that is, don’t jump to build the final application, but do the simple ones first and test (save the file, open it in a browser, and check if it works) frequently.
Requirements To follow along and produce your versions of the applications described in this book, you need a text editor such as TextPad and a browser such as Mozilla Firefox or Internet Explorer. You can use a PC or a MAC. In addition, you need a graphics program such as Paint Shop Pro or Photoshop to create graphics files.
xv
xvi
Introduction
Overview of Chapters The first nine chapters introduce fundamental concepts. The last three introduce advanced concepts that are strongly motivated by games but are important for other applications as well. Chapter 1, ‘‘Development Environment,’’ shows how to prepare (develop) an HTML document. You will get a quick, informal introduction to HTML. The motivating example is a Web page describing Favorite Web Sites. Chapter 2, ‘‘Basics,’’ presents the building blocks of programming languages: statements and expressions. These are roughly analogous to the sentences and phrases of English and other so-called natural languages. This chapter also shows ways to communicate with the person using the computer. This is termed input/ output. The applications are several calculator programs, including ordering in a coffee shop. Chapter 3, ‘‘Extending the Basic Language,’’ introduces the fundamental concept of procedure: a way to package and name a sequence of code statements so you can use them many times. Procedures are defined and then invoked. The focus in this chapter is on built-in procedures, or procedures that come with the language. Chapter 6 will focus on programmer-defined procedures, which are the ones that you, the programmer, create. The motivating applications are HTML documents with different images displayed as backgrounds. This chapter introduces the notion of pseudo-random processing, which is critical for many games. Chapter 4, ‘‘Events and Event Handling and the Graphical User Interface,’’ showcases the defining feature of modern programming: specifying that you want a particular action (the event handler) to be taken when the underlying programming system detects that a particular thing (the event) has occurred. The chapter also demonstrates the use of a coordinate system to define areas within an image. The motivating application is a Find game using digital photographs. Chapter 5, ‘‘Variables and Datatypes,’’ focuses on how you, the programmer, can give a name to a value, a piece of data, so that you can refer to the value. There are different kinds of values. For example, the datatype for a variable can be an integer, another type of number called floating-point, a string of characters, or other possibilities. The applications are a set of coin flip games. Chapter 6, ‘‘Functions and Parameters,’’ returns to the important concept of procedures, this time focusing on procedures defined by the programmer. The
Introduction
motivating application is a computerized version of the playground game Rock, Paper, Scissors. The application is built up from a basic version just using text to one using graphics for buttons and for displaying the result. Chapter 7, ‘‘Application State,’’ addresses the requirements for applications to maintain information and to implement logic: the rules of the game, for example. The mechanisms include global variables (variables that persist and are accessible independent of procedures starting and stopping) and local variables (variables defined for use within a procedure), objects (aggregations of data and code), and if and switch statements (code for testing and acting on conditions). The example is the dice game of Craps. Chapter 8, ‘‘Automating a Physical Application,’’ focuses on the mechanism for defining and manipulating sets of things. An array variable is a variable holding a set of values. This chapter also features use of timed events. The motivating application is the familiar card-matching game called Memory or Concentration. In this chapter, the implementation is done using HTML. Chapter 9, ‘‘Objects,’’ focuses on the important concept of objects. The motivating application is a game I invented called Picture Quiz. Basic questions require you to answer a question by selecting one of four options. What I term special questions ask a follow-up question provided in an HTML prompt window. The requirement to implement these two types of questions provides a demonstration of the inheritance facility in object-oriented programming. Chapter 10, ‘‘Computed Animation,’’ demonstrates the use of computed animation for simulation. The simulation is categorized as discrete because it produces a series of displays corresponding to set time intervals. You can think of the displays as snapshots taken of a virtual world. The program generates the snapshots. The motivating application is a ball bouncing against the walls of a 2-D box. Chapter 11, ‘‘Ballistics Simulation,’’ builds on the previous chapter for a more complex simulation. The concepts include the equations of motion and collisions. The application is the simulation of a cannonball shooting out of the mouth of a cannon, tilted up at an angle, and at a specified speed. The exposition demonstrates a way to do the implementation in steps. Chapter 12, ‘‘Discrete State Simulation,’’ shows how to build a program to simulate a phenomenon with timed, deterministic, and random factors. The motivating application is a virtual dog that can be petted and fed. Although this
xvii
xviii Introduction
application, with my crude drawings, is silly, discrete state simulation is the basis for complex games and for serious science. To round off the book, Appendix A lists the answers to all the end-of-chapter review questions, and Appendix B offers a glossary of the book’s italicized terms.
About the Book’s Web Site The book’s Web site is at Courseptr.com. Just click the Downloads link at the top of the page; enter the title, ISBN, or author name; and click Search Downloads. The site has the code for each chapter’s applications. It also contains tips for teachers.
chapter 1
Development Environment This chapter focuses on how an application is created, which is termed the development process. This process is accomplished using or in a development environment. After studying this chapter, you will n
Understand the difference between development time and runtime.
n
Understand the basic features of a development environment.
n
Acquire experience using a simple development environment to produce a Web page linking to favorite or useful Web sites. While doing this, you will learn the basic tags of HTML.
Motivating Example To demonstrate concepts concerning the development environment and to get you started for the rest of the sample applications in this text, I use Hypertext Markup Language (HTML) to create a Web page with short descriptions and links to other Web sites. This application will be a Web page about other Web sites. For each Web site, the page will contain the name, a short description, an image, and a working hyperlink. If a visitor clicks on a hyperlink, the browser goes to the target site.
1
2
Chapter 1
n
Development Environment
Figure 1.1 Listing of favorite Web sites, with images as links.
Note For the Favorite Web Sites application, an appropriate name for a user is ‘‘visitor.’’ It is a good practice to identify the users of your application.
Figure 1.1 is a screen shot of my Web sites. The three images are working hyperlinks: when a visitor to this site clicks on each link, the browser displays the indicated site. The critical features required by this example include n
A development environment—namely, a way to produce HTML.
n
A feature to produce a clickable image, also known as an icon, that makes the browser load a new page. Using the metaphor of the Web, this takes the user to a new site. In the technical jargon of the Web, this is a hyperlink.
Introduction to Concepts
Introduction to Concepts The aim of this book is to introduce you to the general ideas of preparing applications to run on computers, including problem-solving, specifying logic, designing how people and computer applications communicate, and application development. This preparation is done by coding (writing) in one or more of a number of specific computer languages. The file you prepare is called the source file. In some languages, the code is stored more or less as you wrote it and translated statement by statement as needed by a specific program. These languages are said to be interpreted, and the languages are called scripting languages. JavaScript is a scripting language, as are Python and PHP. Statements in JavaScript are interpreted by Web browsers. In the case of many other languages, the source code is translated all at once into another form, the executable file, which is what is run or executed directly by the basic hardware of a computer. The translation process is called compilation, and the executable file is in the machine language of the computer. These languages are called programming languages. Examples are Java and C++. The main focus of this text is on the JavaScript language, but comparisons are given to other languages. The examples in this text mainly use HTML with JavaScript and browsers such as Internet Explorer or Mozilla. The development environment for HTML with JavaScript will be a text editor. Notepad, found on most PCs, and TextPad, a readily available shareware tool, are examples of text editors. Note Two of the most common programming languages in use are C++ and Java. A significant number of applications still in active use today were written in COBOL, one of the first programming languages. Actually, a growing phenomenon is for applications to be made up of many parts in different programming languages connected by both standard and ad-hoc methods. JavaScript is not Java, but the two do have some similar syntax. Syntax refers to the use of notation and symbols in a computer language.
There are general concepts important for any computer application, independent of choice of programming language. These include n
Representing a problem
n
Logic
3
4
Chapter 1
n
Development Environment
n
Event handling
n
Attention to the human-computer interface
The approach used in this text is to describe what I term the motivating example: focus on concepts, put those concepts to work in applications, and then reflect on what has been discussed, including giving examples of what you would do if you worked in the industry. Although some computer specialists may disagree, programming languages have more similarities than differences. Caution Details matter in programming languages, so they require your attention. Please try to ‘‘come up for air’’ frequently and consider the general comments in this book and reflect on your own experiences.
You will use a text editor to create the HTML file for Favorite Sites. You will then test your work using a browser such as Mozilla or Internet Explorer.
Application Development Environments Building a programming application is like writing an essay, cooking a meal, or composing a piece of music. In each case, a ‘‘product’’—the program, essay, meal, or song—is first created and then used or presented for use. When you write an essay, there is a point in time in which you are writing and then other times in which you read the essay yourself, you show it to others to read, and maybe you even publish it. The cook prepares a meal and people eat it. A composer writes a song, and musicians perform it. In programming, the creation phase is described as development time, and the using phase as runtime. Like most analogies, these are not perfect. You prepare an application; this is called development time. You are programming. Then you put the application into operation; this is called runtime. You are running, invoking, or executing the program. Of course, when you are programming (and writing, cooking, and composing), there will be iterations: create, test, go back and fix or enhance your code, and then test again. There also may be a distinction between testing a single program and installing and deploying the new program within a total system. An application may consist of a file holding a single program or several files holding programs and other things, such as images or databases. Unit test refers to testing one unit or
Introduction to Concepts
module, and system test refers to testing the whole system. The simple, but fairly powerful, Web page application featured in this chapter involves multiple files. You cannot easily examine the code of a compiled program in a programming language such as Java. For example, you cannot examine the code of a Flash movie, a common part of many Web applications. But you can examine the source of an HTML document with JavaScript code. For example, in the Mozilla Firefox browser, click on View and then Page Source (see Figure 1.2). One common situation in these times is that an application consists of multiple files. These files may even be in different languages. Your task may be to work on just one file, but you need to know about other files to know how to proceed and to do a proper test. The development environment includes some or all of the following: n
An editor for the creation and editing of source files. One important attribute of the editor is the ease in which you, the programmer, can go back and forth between multiple source files, for information and for copying.
n
A procedure, maybe part of the editor and maybe not, for managing the multiple files.
n
A compiler, if required.
Figure 1.2 Screen shot showing use of Mozilla Firefox View menu to get the page source.
5
6
Chapter 1
n
Development Environment
n
A program for running the application. This could be part of the operating system for the computer.
n
Optionally, a debugger—that is, a version of the program for running the application that provides help in finding mistakes.
n
A facility for referring to the requirements generated by customers and others for the application.
n
A facility for documenting the application, including managing versions and status with respect to testing and deployment.
The term editor is used for the initial creation, editing, and refining of the work. The editor may treat the code as plain text or may have features relating specifically to the language. For example, the editor may use colors to display the code or may provide options to complete parts of the coding. You will see examples of the former in the use of TextPad and examples of the latter in Flash. The last two facilities—references to lists of requirements and documentation— are common in development environments in organizations. More generally, large organizations may have quite elaborate development environments that are a mixture of off-the-shelf, customized, and home-grown tools.
Favorite Sites The Favorite Sites application is a Web site with text, images, and hypertext. It uses the basic and substantial capabilities of HTML, without JavaScript.
Plan of Attack for Favorite Sites The steps for implementation are 1. Identify the addresses, called URLs (uniform resource locators). 2. Find and download images, perhaps the logos of the sites. 3. Compose the accompanying descriptive text. 4. Prepare the HTML file. I will demonstrate this using a basic (Notepad) and a specialized (TextPad) editor.
Favorite Sites
5. Test using any browser. This corresponds to executing or running the file. 6. Optionally, upload all the files of the application to a Web server using an FTP (file transfer protocol) program such as WS_FTP or FileZilla. In this simple example, you most probably will compose the text as you are preparing the HTML file; it will not be a separate step. I list the steps as distinct to emphasize that in this, as in other, applications, you should try to separate what you want your final product to accomplish from the technical details of the implementation. You will need to use the Save Image (Save Picture) feature of browsers to acquire the image files. Any HTML file is composed of text interspersed with what are called tags. Examples of tags are , , , and . Tags provide information to the browser that affects the display of the document. For example, putting text between and tags, The word italic is in italic.
causes that text to be displayed in italic. Using
and
tags formats the contained text as a paragraph. This generally means simply skipping lines. A forces a line break—that is, going to the next line. Line breaks, skipped lines, and extra spacing—all of which is termed whitespace—are generally ignored in an HTML document, but you should use them to make the document easier for you to read. The and tags designate hyperlinks: Visit the Purchase College Web Site
An HTML document formally is an element that contains head and body elements. Elements are made up of starting and ending tags and, possibly, stuff in between. The stuff in between constitutes the content of the element. Elements can contain other elements and text or be empty. Elements can have attributes, which are extra information in the starting tag. The following tag demonstrates an empty or singleton element with two attributes:
The src stands for source. This tag tells the browser to look for a file named home2.gif in the same folder as this HTML file. If it is found, the browser will
7
8
Chapter 1
n
Development Environment
display it, making the width 100 pixels and the height whatever height preserves the original proportions (aspect ratio) of the image. Caution You will see working examples with and without the closing slash. Including closing slashes on tags that do not have content, using lowercase for tag names, and including quotation marks around attribute values are part of the new, stricter standard called XHTML, but at this point in time many examples do not follow these rules and still work.
The following a element containing an img element demonstrates how to implement an icon, an image that serves as a hyperlink.
The href attribute of the tag indicates what URL the browser should jump to. Because a complete Web address is not given, the browser will look for a file named index.html located in the origami folder.
Use of Concepts in Implementation An HTML document can be produced in any text editor, including the Notepad program that comes with any Windows-based personal computer. You can have several Notepad sessions open at one time. The critical step is that you must be sure to save the file with the extension .html after changing the Save As Type to All Files. Note There are other tools for creating HTML documents, such as Dreamweaver by Macromedia and FrontPage by Microsoft. The browsers Mozilla Firefox and Netscape also provide editors for HTML. All these tools practice What You See Is What You Get (WYSIWYG, pronounced whis-ee-wig). You generally do not see the tags, which are placed in the file for you. A disadvantage is that the tool sometimes does not do what you intended, and it is necessary to make changes in the tags. For example, the tool may construct the value of an src attribute using the location of the file on your home computer. This generally is not what you want when you upload it to a Web server. Alternatively, the tool may assume all images are in a subfolder, which may or may not be appropriate. An argument in favor of the more sophisticated tools is that they handle some file management, including uploading the files.
A tool that is between the plain text editors and the fancier What You See Is What You Get offerings in how it is used is TextPad. TextPad is shareware (http:// www.textpad.com), and you should pay for it if you use it beyond a trial period.
Favorite Sites
Figure 1.3 TextPad screen for Web sites example.
Figure 1.3 is a screen shot showing this example done using TextPad. On the screen, tags are blue, quoted attribute values are aqua, and ordinary text is black. The panel at the upper left indicates that one file is open; it is possible to have multiple files open. The TextPad tool ‘‘knows’’ about certain languages, including HTML, C and C++, and Java, and after saving a file as one of those types, it uses colors for the different parts. This provides the programmer a quick way to check for many syntactic errors, such as use of quotation marks and pointy brackets. Word wrap has been turned on, but the line numbers correspond to the lines in the original document (notice line 20). This is helpful when using the JavaScript console editor in Mozilla. Tip You can switch among the editors and among the browsers while preparing a single application, although, as hinted at previously, the development environments such as FrontPage may produce so many extra tags and make naming choices with the files that once you start using it, you may not be able to easily change to another system. Trying out your application with different browsers and on different operating systems and different computers is considered essential for professional work. In later chapters of this text, you will read about ways to handle browser differences.
9
10
Chapter 1
n
Development Environment
To best understand the HTML, the reader should examine together the screen shot in Figure 1.1 and the source code that produced it in Figure 1.3. The html element contains a head and a body element. The head element contains a title element. This title text appears at the upper corner of the browser in Figure 1.3. The body element contains three p (paragraph) elements. Each of these contains an a element containing an img element, a line break tag , and brief text. If you decide to upload this application to a server on the Internet so everyone can view it, you need to use a file transfer protocol program. The critical step is to realize that your application includes several files. For the example shown here, the application is the websites2.html file plus home2.gif, hudsontrail.gif, and closeupsmall.jpg.
What Can Go Wrong The most obvious and most common error in HTML coding and other programming is syntactic: you mess up the punctuation, in HTML usually by forgetting or mistyping a bracket or quotation mark. Here is where a benefit of HTML, the fact that the browser will ‘‘try’’ to produce something, is a disadvantage. It would be nice if these errors were caught. You will come to welcome the error messages produced by the Flash system. Compiled languages such as C++ and Java will indicate syntactic messages at compile time. In later chapters, you will see screen shots of the JavaScript console available in Mozilla and Netscape that provide some help. My main advice to you is to proofread, test, and try again. A common type of error in the Favorite Sites example occurs when the references to images or to the sites are well formed but incorrect. For images, the name and the extension of the file must be correct and, if you use just the name and file extension, the file must be in the same folder as the HTML file. Figure 1.4 shows the Mozilla browser’s display of an HTML file that has been modified to refer to a nonexistent image file. Note also the title in the upper-left corner. The image indicating a missing image still will work as a link. Two things will cause problems with the site references. The address can be incorrect, or the site may have moved. The latter may be beyond your control. Another problem with HTML implementation is that it is easy to have multiple copies of the document open in one or more editors. You may be testing an older version of the document when you have corrected errors in another version. When the applications become more complex and development involves more
Chapter Summary
Figure 1.4 Missing image.
people, you will appreciate a system of version control using file-naming conventions and systematic commenting of the code.
Chapter Summary This chapter demonstrated the development of applications. A critical concept was the distinction between development time and execution or runtime.
What You Have Learned The development environment for creating and running the Favorite Sites Web site consisted of the following programs: n
A text editor—Notepad, TextPad, or the equivalent—to create and edit the HTML file
11
12
Chapter 1
n
Development Environment
n
A browser—the Open Source Mozilla or Microsoft Internet Explorer would do—for finding the sites, for acquiring images for illustration, and then for testing (showing and using) the finished product
n
An FTP (file transfer protocol) program—such as FileZilla or WS_FTP—to upload the application (the four files) to a Web server on which you have an account to deploy the project to the Web
You cannot test the HTML program using the editor by itself, although editors may have links to invoke the browser. The Favorite Sites application is dependent on the cited sites being operational. This interdependency is typical of most computer applications today. The burden of managing the files (see above for what can go wrong) is on you. The benefits of this development environment are that all these tools are relatively easy to understand, they do not produce extra code or extra files for you to manage, and they are typically already installed on your computer or freely downloadable.
In the Real World If you are working by and for yourself, you can choose the development environment you like and can afford. However, if you join an organization, you need to use the environment in place (although, with experience, you can lobby for new choices). One aspect of an industrial setting is that the development environment may be linked to a larger system that keeps track of requirements, versions, and reported bugs (bug = error) and maintains documentation. Application development in medium and large enterprises generally involves formal procedures and includes the use of software products—software for building software. The first step in developing any application is to identify the critical requirements. This is called logical design. An example of logical design would be if you were asked to develop a Web site to be used by members of your organization giving links, information, and assessments on internal and external Web sites. You would and could gather this information independently of the implementation. Next, you would decide how to implement these features. This would include choosing technologies (physical design). Then you would plan your implementation. Testing would be done as you went along and when the implementation was complete. The terms ‘‘unit test’’ and ‘‘system test’’ may apply; unit test could be testing a single program. This may not be possible, so it
Chapter Summary
is testing the smallest unit that can be tested. A system test involves testing the whole system. That also may be difficult to manage, but it is the ideal. The last steps are deployment (install, distribute, or publish your product) and monitoring the use. In most real-world situations, this involves the reporting of problems (software bugs) and planning new releases with bug fixes and enhancements. One factor in assessing the software maturity of organizations is to determine the extent in which the organization tracks how errors arise and adapts the development systems to prevent reoccurrences. Application development is a large, complex subject, with new ideas and products emerging all the time. The sad fact is that many—perhaps most—computer development projects are less than successful, either failing totally, coming in late or over budget, or not performing as promised and containing bugs (flaws) that customers and clients discover. This may be disheartening to you, but it also could boost your confidence to know that professionals also have problems. One accusation made concerning computer professionals is that they do not think about the people who will use their programs. I hope that that does not apply to you. (Try out the Favorite Web Site on your friends, family, and colleagues.) If you consider the specific features of the example described in this chapter, Favorite Sites, this could be the basis of a serious project. For example, you may be asked to prepare a list of sources on a specific topic for customers or clients. It may be that any Web site for the organization needs to contain the company logo at the top and certain information at the bottom or side. The development environment may help you include these features. Use of images may involve copyright issues. The Favorite Sites example generally is safe because it is analogous to a review of a book or movie. Web site owners generally appreciate any links to the site, even if accompanied by less than favorable remarks. It is not okay to use an image from another site to decorate your site unless you have permission. A consideration for either application is the issue of scale. If the number of sites or the steps in the directions is large or is changeable, then eXtended Markup Language (XML) by itself or with eXtended Stylesheet Language (XSL) are technologies to investigate. XML files hold content. XSL files can be created to transform and format the XML into HTML. Flash/ActionScript and other languages such as Java and PHP have XML methods to access and incorporate the content into applications.
13
14
Chapter 1
n
Development Environment
What’s Next In later chapters, you will learn more programming features, some of which you have been introduced to in this chapter. These features include statements, expressions, functions, variables, and events to understand how to create more complex and more dynamic applications. You will use the debugging features of the two development environments and see the benefits of staged development.
Review Questions 1. Explain what is meant by development time versus runtime. 2. Explain the relationship of the HTML elements html, head, body, p, img, and a. Which elements go inside which elements? 3. What is the HTML for producing a hyperlink that will take the user to a site with the address http://www.irs.gov if the user clicks the words TAX INFORMATION? 4. What is the HTML for displaying the image file snow.jpg? 5. In HTML, Jeanine Meyer’s Site would a. Print out a copy of the text book b. Construct a hyperlink so you can click on http://newmedia.purchase .edu/~Jeanine and go to that site c. Construct a hyperlink so you can click on Jeanine Meyer’s Site and go to http://newmedia.purchase.edu/~Jeanine d. Produce a picture of Jeanine Meyer
On Your Own 1. Write the HTML to produce a clickable icon, a graphic that, when pressed, causes the browser to display a new Web page. Let the new Web page be located at http://newmedia.purchase.edu/~Jeanine/origami/home.html and the graphic be bird.gif. 2. Write the HTML to produce a clickable icon with the graphic dorm.jpg that, when pressed, causes the browser to display the page at http://www.purchase.edu/dorms.html.
chapter 2
Basics
This chapter will focus on the basics in any computer language—namely statements, expressions, and communication with the end user. After studying this chapter, you will n
Understand what is meant by a statement in scripting and programming languages
n
Understand several statement types common to most computer languages
n
Learn how an expression performs an arithmetic or logic calculation
n
Acquire experience using statements, expressions, and simple input/output operations using HTML and JavaScript
Motivating Examples To demonstrate basic concepts, I use two examples. Using Hypertext Markup Language (HTML) and JavaScript, you will create two simple applications requiring user input. The first example turns the computer into an adding machine. Don’t be concerned: the examples will get more interesting. Figure 2.1 shows the initial screen.
15
16
Chapter 2
n
Basics
Figure 2.1 Simple calculator display.
Figure 2.2 Calculator showing the sum.
After the user enters numbers into the first three boxes and clicks on the Add Up button, the screen will resemble Figure 2.2. The second example is a specialized calculator for orders at a coffee shop. This example demonstrates the use of drop-down menus and radio buttons. Note In the early days, many car radios featured buttons instead of or in addition to dials. Only one button could be depressed at a time. If you pressed a second button, the first one would pop up. Most modern car radios have the mechanism to set a small set of buttons to your favorite stations. HTML radio buttons provide a computer analog to this feature. The selection is done using the mouse.
Motivating Examples
Figure 2.3 Coffee shop form.
Figure 2.4 Drop-down menu with choices.
Figure 2.3 shows the initial screen. Figure 2.4 shows the look of the screen after the customer has clicked on the down arrow to reveal the drop-down menu and then selected Hot Cocoa. The next step is to select a size. The choices of size are implemented using a radio button group. This means that only one button can be selected. If and when a second one is clicked, the first button changes to the unselected state. Figure 2.5 shows the screen after a size has been chosen and the Order button has been pressed. The text fields reveal the total amount charged. The critical features required for these applications include n
Ways for the user to enter information (input)
n
Ways for the application to display information to the user (output)
n
Mechanisms for storing information such as prices
17
18
Chapter 2
n
Basics
Figure 2.5 Screen after Order button has been clicked. n
Mechanisms for calculations
n
Mechanisms for examining strings to format dollars and cents in the standard way
Introduction to Concepts Programming or scripting languages are defined by grammars and sets of rules, and they’re made up of statements in the same way that formal written language is made up of sentences. The adjective ‘‘formal’’ is important here. The principle difference between programming languages and natural languages such as English is that programming languages must be grammatically correct to work at all. In contrast, you can understand other people even if they are not speaking correctly. It even is possible to understand people who make up words and idioms. You do not have that luxury when you are programming. The underlying programming system translates correctly formed code people write, called the source code, into a form that the computer circuitry can run. If the source code is not correctly formed, in some cases (for example, Flash’s ActionScript or Java), no translation takes place. In other cases, notably with JavaScript and HTML, something will appear, but it may be very different from the programmer’s intention. The translation and execution process may happen all at once or may involve multiple steps. Continuing the analogy, natural languages are made up of sentences, and sentences come in different types, such as declarations and questions. Sentences themselves are strings of letters, blanks, and symbols such as periods and question marks. Programming languages generally have several different types of statements. Some statement types are called compound statements because they contain or
Introduction to Concepts
can contain multiple statements. Statements are themselves made up of characters and symbols. For example, in several languages, statements are ended with a semicolon, and compound statements involve the use of brackets. A set of statements surrounded by brackets can be treated as a single statement. In the next section, you will read about assignment statements and two types of compound statements, common to many languages. Computer programs often require interactions with someone. This someone is termed the user or end user, although a first step in good design is to identify these people with a more appropriate name. For the second example in this chapter, the term ‘‘customer’’ will be used. In chapters in which the examples are games, you are targeting a player. The interaction of a person with a computer is called input/output (I/O) or human/computer interaction (HCI). The devices demonstrated in this chapter are drop-down lists, radio buttons, and text fields. Later chapters will demonstrate other ways for players to make moves. The adding three numbers application required the user to enter three numbers and then click a button. The application performed the addition and then displayed the result. The coffee shop application presented the customer with dropdown lists displaying the types of drinks and buttons indicating the sizes. The application calculated the price and displayed a formatted result.
Expressions In teaching programming, it is difficult to introduce some concepts without assuming or mentioning others. This chapter will touch on a few topics—for example, variables and arrays—that will receive more attention later. The idea is to show concepts in actual use right away. At this point in the chapter, there is a problem in what to explain first: expressions or statements. Expressions are combinations of terms using operators such as the plus sign (þ). In fact, most computing languages have a large set of operators, including the standard ones from arithmetic, operators for making comparisons, and operators that work on logical values. By my going on to explain statements, you will be able to see how expressions are used in programming.
Statements Computer languages come with several different types of statements. Common ones include n
Assignment statements
n
Function or method calls
19
20
Chapter 2
n
Basics
n
Conditional statements—specifically, the if statement
n
Looping statements—specifically, the for statement
An assignment statement sets or assigns a value—perhaps a calculated value—to a place in memory. The term for the calculation is expression. More abstractly, the assignment statement associates a value with a name. The following statement population = 3000000;
when executed, gave the population variable the value 3000000. The semicolon at the end indicates the end of the statement. Many programming languages use the semicolon; others use a line break to indicate the end of a statement. Some use both; that is, you can combine statements in one line by separating them with semicolons. If you consider the matter, you will realize that a period is not a good choice just in case any statement involves a number with a decimal point. Actually, periods may have other uses as well, so semicolons are good candidates for this role. Note The equal sign is used in many programming languages for assignment statements even though it can be confusing. The language APL (for A Programming Language) uses an arrow (/), but most other languages use the equal sign.
One way of reading or thinking about assignment statements is to say Make it be the case that the variable population is now equal to 3000000. Another example of an assignment statement is totalwithtax = total + taxrate*total;
Interpret this statement as follows: Assuming that total and taxrate are variables that have values, fetch both values and multiply them. Then take that result and add to it the value of total. Assign this to the variable totalwithtax. If the total was 100 and the tax rate was .04, the totalwithtax variable would be 104. The right side of the assignment statement is an expression. The plus sign is an example of an operator and, in this case, stands for addition of numbers. You
Introduction to Concepts
may say, ‘‘Of course, it stands for addition of numbers.’’ However, in JavaScript, as well as many other programming languages, the plus sign, in a different context, means combining, also called concatenating, strings: "abc" + "def"
yields
"abcdef"
Assuming that title is a variable holding the value "Logic", then "The name of the book is "+title
yields "The name of the book is Logic"
This double duty for the þ operator is called operator overloading and will be used in the first example in this chapter. Most programming languages support expressions of more or less unlimited complexity with operators for arithmetic, comparison, and logical operations. An example of an expression involving a comparison operator would be score >= average
Making the assumption that score and average are variables holding numbers, this expression has the value true if the value of score is greater than or equal to the value of average, and false otherwise. Note Programming languages differ in how true and false (also called Boolean values after mathematician George Boole) are encoded, with some languages defining Booleans as one distinct type and others assigning Boolean values (true or false) to numbers.
Logical operators take true and false values as operands. A typical example would be the following: (xpos < rightwall) && (xpos > leftwall)
In this example, the two comparison operators return a logical value. The && symbol stands for the logical AND operation. This operator will return true if both operands are true; otherwise, it returns false. The sample expression here computes if a value xpos is between the values rightwall and leftwall. The language processor performs three operations to compute the result: the two comparisons and then the logical operation on the two results. Later in this chapter, you will learn about the if statement, which uses Boolean values to control what statements are executed.
21
22
Chapter 2
n
Basics
Say rightwall was 600 and leftwall was 10. Consider the following cases: If xpos is 5, xpos is less than rightwall but it is not greater than leftwall, so the expression fails. If xpos is 650, xpos is not less than rightwall, although it is greater than leftwall. Again, the expression fails. If xpos is 200, xpos is less than rightwall and greater than leftwall. The expression would have the value true. The next example justifies what is a common shorthand form of statement in several languages. Consider turn = turn +1;
This may look strange. Remember that the equal sign does not stand for equals in this context. The interpretation is Take the value of the variable turn, add 1 to it, and then put this new value into turn. The 1 is exactly what it looks like: the numeric value 1. It is similar to the value of the character string "The name of the book", exactly those characters, with no further interpretation. Because adding 1 to a variable is a common occurrence, many languages have shorthand forms of assignment statements. The following means to increment the value of the variable turn: turn++;
Other shorthand forms exist, and some will be demonstrated later in this text. This construct can be used within an expression as well as by itself. The order of execution of operations is determined by a set of rules called precedence rules. These are fairly consistent across programming languages. For example, the expression 1+2*3
is executed with the multiplication performed before the addition, producing 7, not 9. You can overrule the precedence rules by using parentheses.
Introduction to Concepts Tip It is a good practice to use parentheses to make the expressions easier to read even if the precedence rules would make them unnecessary in a particular case. More generally, though, it may be possible to compress coding into a small number of characters, statements, or lines; ease of understanding is important for debugging (finding errors) and maintenance. This generally argues for many, simpler statements in place of fewer, complex statements. Do not economize on typing!
To summarize the assignment statement, the right side of the equal sign indicates the target, and the left side holds an expression. Functions, one of the most important concepts in scripting and programming, are the focus of Chapter 6, ‘‘Functions and Parameters.’’ However, some preliminary remarks are useful to make here in the context of statements. In mathematics, a function is a rule associating one value with another value or set of values. Think of independent variables and dependent variables or input and output. Similarly, when using a spreadsheet product such as Excel or Google Documents, you can employ any of a large set of functions, including average, pv (for present value), and power. The average function refers to a set of cells. pv and power have a specified number of inputs. Most programming languages have built-in functions that include the familiar ones from mathematics, finance, and statistics as well as a way for you, the programmer, to create your own functions. In JavaScript, a function is a set of statements set off in a particular format and generally with a name and a way to specify the inputs. The sequence of statements does not necessarily produce an output, making the programming concept more general than the mathematical one. This facility allows you and me to extend the language. In many programming languages, the term ‘‘procedure’’ is used in place of ‘‘function.’’ The term ‘‘function’’ is sometimes reserved for procedures—that is, sequences of statements—that produce a value and, as a consequence, can be used in an expression. A method is a function that is associated with an object. Objects are the focus of Chapter 9, ‘‘Objects.’’ However, I want to introduce two methods right now: Math.random and Math.floor. In JavaScript, the following statement dievalue = 1+ Math.floor(Math.random()*6);
23
24
Chapter 2
n
Basics
demonstrates the way JavaScript provides mathematical functions. Math.random() is the call of the method and, when this line of code is executed, produces a fractional value from 0 to 1. The result of the call is multiplied by 6, and this result is then fed into Math.floor. Math.floor truncates values to produce whole numbers. So the result of this step in the expression is to produce a whole number. Lastly, this number is added to 1. You will see this again when the discussion turns to dice games in Chapter 7, ‘‘Application State.’’ In this text, the examples will show many calls to built-in functions and methods and programmed-defined functions and methods. Another important group of statements found in programming languages are conditionals, which let the programmer direct the invocation of statements based on conditions. These statements are the heart of programming logic. They provide a way to go beyond simple formulas and express complex reasoning. What if you wanted to keep track of what was the best price of a desired product or the best test score? An example of an if statement in JavaScript is if (current > best) best = current;
The expression in parentheses following if is the condition. Assuming that current and best are two variables holding values that can be compared, say sales amounts or test scores, then if the condition is true —that is, if current > best yields the value true —the value of current is assigned to the variable best. If current was not greater than best, this line of code would have no effect. The code performed if the condition is true is termed the true clause. Again, if the condition is not true, no assignment takes place. A way to express the actions of an if statement pictorially is to use flowchart symbols, as demonstrated in Figure 2.6.
Figure 2.6 Flowchart of if statement.
Introduction to Concepts
The if statement is called a compound statement, with symbols or layout used to organize several statements. Another way to write the previous example in JavaScript is if (current > best) { best = current; }
The curly brackets can enclose any number of statements. It is good practice to use the brackets even if there is just the single statement. You may need to add another statement to the true clause, but this is easier using brackets. Building on the previous example, suppose I wanted to make sure that I knew the best price or test score, and I wanted to keep track of how often I needed to change the best value. The following if statement would accomplish this. if (current > best) { best = current; changes++; }
Note Some programming languages (Python or Visual Basic .NET, for example) use line breaks to define the statements executed when the condition is true.
A variant of the if statement is if/else: if (current > best) { best = current; changes++ } else { status = "no change"; }
This statement has the following effect: if the condition is true —that is, if the value of current is greater than the value of best —then the variable best is assigned the value of current, and the variable changes is incremented. If the condition is not true, a variable named status gets the value "no change". With an if/else statement, something always happens. When the condition is true, it is the code directly following the condition. When the condition is false, it is the code following the word else. Figure 2.7 represents this statement.
25
26
Chapter 2
n
Basics
Figure 2.7 Flowchart diagram for if/else.
The condition part of an if statement can be any expression that returns a true or false value. In some computer languages, there are rules on how to interpret any type of value as either true or false. Other languages are stricter. Conditions can consist of logical combinations of conditions. In a script for determining grades, assuming that scores between 80 and 90 received a B, I would write code that determines if the score is greater than 80 and determines if the score is less than 90. If both are true, the grade earned is a B. The following example is how it would appear in JavaScript: if ((score>80) && (score 90) { grade = "A"; } else if (score > 80) { grade = "B"; } else if ...
An alternative in this particular situation may be to use a mixture of computation and conditionals. (See Chapter 8, ‘‘Automating a Physical Application.’’)
Introduction to Concepts
Many languages provide another form of conditional statement called a switch or case select. Here is an example in Java and JavaScript format. switch (month) { case "Sep": case "Apr": case "Jun": case "Nov": number_of_days = 30; break; case: "Feb": number_of_days=28; break; default: number_of_days = 31; }
This code fragment uses the variable month to set the variable number_of_days. The variable month is presumed to hold the three-letter abbreviation for the name of a month. The language processor checks the value of month against the values following each instance of the word case. If there is a match, then no more matching is done, and statements are executed until the statement break is reached or the whole switch statement ends. The effect in this example follows the logic of the ditty: ‘‘30 days hath September. . . .’’ That is, the checking is Is it Sep? Yes, then fall through to the statement number_of_days = 30 and leave the switch statement. Is it Apr? Yes, then fall through to the statement number_of_days = 30 and leave the switch statement. Is it Jun? Yes, then fall through to the statement number_of_days = 30 and leave the switch statement. Is it Nov? Yes, then fall through to the statement number_of_days = 30 and leave the switch statement. Is it Feb? Yes, then fall through to the statement number_of_days = 28 and leave the switch statement. No matches? Yes, then fall through to the statement number_of_days = 31 and exit the switch statement at its close.
27
28
Chapter 2
n
Basics
Other programming languages may implement the switch construct differently, but most languages have a similar feature. It is worth trying to find this feature, because it can make code easier to write, read, and change. As an example, VB .NET has a statement called Select Case. It allows multiple case-type labels for clauses and does not have control flow down from the first matched case, removing the need for a break command. The days of the month would be implemented as follows: Select Case month Case "Sep", "Apr", "Jun", "Nov" number_of_days = 30 Case "Feb" number_of_days = 28; Case Else number_of_days = 31; End Select
The last category of statements to be described here provides a means for repeating groups of statements. These are powerful constructs and will be used repeatedly in this book. Their power is best shown with concepts to be introduced later. However, here is a simple example. Suppose that you needed [your code] to add up the integers from 1 to a specified value held in the variable top. A good strategy would be to begin by defining or selecting a variable to use in the calculation. Because you do not know the value of top, you cannot simply write sum = 1 + 2 + ...
Instead, start by assigning zero to the sum variable. Then add the values from 1 on, checking to see if the code has reached the variable top. The following code in JavaScript syntax performs the task. sum = 0; for (i=1;i Open script element, indicating coding in JavaScript. function addup() { Start function definition. f.sum.value = Start assignment statement. The calculated expression will be put into the value of the sum input element of the form named f. Because this must be a string (that is, text), a conversion will be done since the calculation produces a number. 1*f.one.value + 1*f.two.value Calculate the sum. The calculation is three multiplications (to force conversion to + 1*f. three.value; numbers) and then an addition. return false; Return false to prevent the refresh of the page. } End function definition. Close script element. Close head element. Open body element. Addition: Label and break to new line. Start form with name f. Specify action on submission to be calling the addup function and returning its value. Enter value: jfSet up text followed by input tag named one (name attribute set to one). Set up line break. Enter value: Enter value: The sum is:
Set up line break. Set up text and input tag named three. Set up line break. Set text and input tag that will be used for display. It has the name sum. Set up input tag of type submit. This will produce a button. The value is its label, add up. Set input tag of type reset. This will produce, with no other effort, a reset button. This code gives it the label clear. Close the form. Close the body and close the HTML.
Coffee Shop
To try this, you need to create the HTML document by using Textpad or some other editor for HTML, as demonstrated in Chapter 1, ‘‘Development Environment.’’ After entering the code, save it as .html. Textpad will use one color for HTML tags and another for strings, so you often can tell at a glance if you omitted a quotation mark or misspelled ‘‘input’’ or other similar built-in names. Open the file using the Globe feature to access the designated browser or directly from any browser (such as Mozilla or Internet Explorer). Note that the code is in the first column with explanations in the second column, so only copy the material in the first column. If you do this using Internet Explorer, you will be shown a security message stating that Internet Explorer has blocked content. When you click on this message, you will get a chance to click on Allow Blocked Content, and then you’ll be asked once more if ‘‘you are sure you want to let this file run active content.’’ Click on Yes, and you can continue.
What Can Go Wrong One example of what can go wrong that has already been suggested is the omission of the coding, the multiplying by 1, to convert each string input to a number. Another source of error is essentially typing mistakes involving the curly brackets ({}), parentheses, angle brackets, and quotation marks. One aggravating factor is that browsers are forgiving, so to speak, about these types of errors and go ahead and display something. You will see working examples online that omit quotation marks around attribute values, such as type=submit. It is good practice to use quotation marks for attributes, especially because it may be required in the future. In the next example, you will see the use of the javascript: console available in the Mozilla or Netscape browsers. This can be helpful in catching certain types of errors.
Coffee Shop This application demonstrates a somewhat more complex form of user input. In this case, you can imagine that the barista at a coffee shop makes use of a dropdown menu and radio buttons to enter the order.
Plan of Attack for Coffee Shop Application This application, although benefiting enormously from the built-in features of HTML and JavaScript, still has more functionality than meets the eye. The internal coding needs to contain the prices for the drinks. To show off expressions, this
35
36
Chapter 2
Basics
n
example uses a formula that multiplies a base price by a size factor. The tax rate is encoded as a variable initialized in the code. Lastly, the calculated total must be formatted to appear in proper dollars and cents format. An outline for this HMTL/JavaScript application is html
element
head
element
title
element
script
element
definition of addup function information necessary for calculations extract drink information extract size information calculate price calculate tax format as dollars and cents display body
element
form drop-down menu radio button group Submit button text boxes for display
Use of Concepts in Implementation The coffee shop application requires the prices and tax rate to be encoded in some way. For the tax rate, the approach here is to use a variable, called taxrate. The JavaScript var statement defines the variable for future use and can include an assignment of a value. This is referred to as an initial value, although in this application it will not be changed.
Coffee Shop
The JavaScript program also uses variables to hold intermediate values in the calculations. It is possible to avoid doing this, but doing so makes the program easier to understand and, in certain cases, it removes the need to calculate values more than once. The DOM specifies the way to determine the choice made in a drop-down menu and the way to determine the choice in a radio group. You may think that these two situations should be the same, but that is not how it works. The code performs each of these calculations using several statements. For the drop-down menu, the selectedIndex attribute produces a number that indicates which one of the set of choices was selected. This can be used to acquire the value of what was selected. Note The option elements within the select element make up an array of elements. Each element is accessible using the notation of square brackets and a number indicating the position, also called the index. The notation of arrays and objects will be discussed many times in later chapters.
For the radio group, it is necessary to check each member of the group. This is done using a for loop; inside the for loop is an if statement checking on the checked attribute. A break statement in the true clause of the if statement makes control jump out of the for loop. The following explains the code for an application that does not format the result for dollars and cents. JavaScript
Explanation
Calculation
Start html, head elements; give whole title element. Start script element. Start function definition. Declare variables used for intermediate values. Declare taxrate variable and set value. Extract the drop-down menu information. Extract the base value for the drink selected.
<script language="JavaScript"> function addup() { var total; var drinkbase; var taxrate = .08 ; var opts=f.drink; drinkbase = f.drink[opts.selectedIndex] .value; var sizefactor; var i; for (i=0;i Coffee
Hot Cocoa Chai Tall Grand Super
Set up for next size.
Define Submit button, with the label given in the value attribute. Line break. Set up line break and then an input tag that will be used for output. Set up input tag that will be used for output. Close html elements.
Try to get this example working. Do make changes in the look, the formatting, and the numbers to test your understanding of the concepts. When you have this working, you will quickly want to improve the formatting to avoid getting results such as 2.7 and 4.050000000000001. That is, you want your
Coffee Shop
code to produce a string that contains a decimal point and has exactly two characters to the right of the decimal point. This code uses a string method indexOf to find the position of the decimal point. If there is no decimal point, it produces a value of –1. String positions start at 0 and go to one less than the length. The code then uses the substr method to take just enough of an intermediate string to produce the desired result. Here is the code to do the formatting. You need to insert it right before the return false; statement. The code takes what has been placed in f.totalf.value and modifies it to show properly formed currency.
JavaScript
Explanation
Declare variables used for intermediate values. totals = f.totalf.value + "00"; Take the original value and concatenate it (+ means concatenate when operating on strings) "00" at the end. dp = totals.indexOf("."); Use the indexOf string function to find the position of the decimal point. if (dp function toss() { if (Math.random()>=.5) { window.document.coin.src="head.gif";} else { window.document.coin.src="tail.gif";}; return false; }
To test this program, you need to draw or obtain in some other way image files representing a head of a coin, the tail of a coin, and a blank image to start the application. Copy the code in TextPad or its equivalent, and load it into a browser. The next step is to keep track of the counts of heads and tails and to display these counts. The decision was made to use internal, global variables for this purpose. The variables are declared and initialized, each to 0. Within the appropriate clauses of the if statement, the right variable is incremented using the shorthand operator ++. The results are displayed each time using the alert function. Notice that the parameter for this function consists of a string constructed by concatenation of constants and variables. The JavaScript process knows to turn the numbers into strings based on the context. In some strongly typed languages, you would need to use a function to produce the string form of a number. Here is the complete code for this next version of the coin toss. Notice that much of it is the same as the previous version. coin toss
Coin Tossing Games <script> var heads = 0; var tails = 0; function toss() { if (Math.random()>=.5) { window.document.coin.src="head.gif"; heads++; } else { window.document.coin.src="tail.gif"; tails++; }; alert("Count: "+heads+" heads and "+tails+" tails."); return false; }
The next application allows the player to produce a biased or weighted coin. This is done using a new function, called setbias, invoked upon submission of input from a new form. The form has the name "b" and an element with the name "sbias". This function resets the heads and tails variables back to 0. This is done using the statement heads = tails = 0;
This compressed format works because an assignment statement is actually an expression with the value of whatever was assigned. So the variable heads also is assigned 0. Note You do not need to strive for brevity by using tricks such as combining assignment statements or using shorthand operators such as ++. It is generally the case that programmers spend more time looking at their code than writing it, so use what is meaningful to you.
109
110
Chapter 5
n
Variables and Datatypes
The code begins coin toss <script> var heads = 0; var tails = 0; var bias = .5; function setbias() { heads = tails = 0;
The next task is to take the value that the player entered and assign it to the variable. However, it is necessary to convert the text entered by the player into a number—specifically, a floating-point number. This is done using the function parseFloat. bias = parseFloat(document.b.sbias.value);
This value is assigned back to the visible element, turning it back into a string. Notice this will mean that if the player enters .25, it will be displayed as 0.25. document.b.sbias.value = bias;
The player may have entered a number that was out of the acceptable range. The following if statement checks this and also checks if the original input was something other than a number by using a built-in function isNaN (standing for ‘‘is not a number’’). In the case of any bad input, the bias is reset to .5 and an alert message is issued. if (bias>=1 || bias =bias) { window.document.coin.src="head.gif"; heads++; } else { window.document.coin.src="tail.gif"; tails++; }; alert(heads+" heads out of "+(heads+tails)+" tosses." ); return false; }
The body element has a second form element, with one element for the player to enter data and another for the Submit button. JavaScript
Explanation
Open the body tag. Set up the img tag named "coin". Open the tag for the TOSS button. When it is clicked, the toss function will be called. Set up the button with the label TOSS. Close the form. Start for a second form. When its Submit button is clicked, the setbias function will be called. Set up the field for the player to enter a value. The initial value is .5. Set up a button with the label "Set bias".
Close the form. Close the body.
The final example outputs the results a different way, using yet another form element, which has an input element named results. The setbias function erases any previous contents in the element named results by assigning the empty string, "", to document.r.results.value.
111
112
Chapter 5
n
Variables and Datatypes
JavaScript
Explanation
Open the tags. Set up the title of the Web page. <script> Open the <script> element. var heads = 0; Initialize the count of heads. var tails = 0; Initialize the count of tails. var bias = .5; Initialize the bias. function setbias() { Start the definition of the setbias function. heads = tails = 0; Reinitialize the counts. bias = parseFloat(document.b.sbias.value); Set the bias to the value entered by the player, forcing it to be a floating-point number. If it was not a number, it would be set to 0. document.b.sbias.value = bias; Redisplay the value so player notices if the entered value was incorrect. document.r.results.value = ""; Reset the results to empty string. if (bias>=1 || bias =bias) { window.document.coin.src="head.gif"; heads++; } else { window.document.coin.src="tail.gif"; tails++; };
Coin Tossing Games
JavaScript
Explanation
document.r.results.value = tails/ (heads+tails)+" ratio of tails out of" +(heads+tails)+" tosses.";
Compute and display the tails ratio.
return false;
Return false to prevent a reload of the page. Close the function. Close the script tag. Close the head tag.
}
The body now has three form elements. It is possible to combine the form named ‘‘r’’ with one of the previous forms because it does not require its own Submit button. I give the code without additional explanation.
What Can Go Wrong One thing that easily can go wrong in these types of applications is neglecting to do the conversions from strings to numbers. The weakly typed languages have advantages in ease of use in not requiring typing and making many conversions automatically. However, sometimes the runtime system cannot figure out that the programmer wants a conversion (also called a cast), and then it needs to be programmed explicitly. This was done by the parseFloat command in the application. The browser can cause another type of problem. When you use the Web, you can click the Reload button. This opens the browser and interprets the HTML document just as it did when you typed in the address or used a window to find and open the file. The problem is that the form data may not be changed. This can cause the anomaly in this example that the internal variable named bias is
113
114
Chapter 5
n
Variables and Datatypes
reset to .5 but another value appears on display. To fix this, the code could include document.b.sbias.value = bias;
right under the statement var bias = .5;
Chapter Summary This chapter focused on the critical programming concept of variables and how data is represented in computers. The applications built were a set of coin-tossing games.
What You Have Learned The representation of data is the critical part of computer applications, so this chapter included nitty-gritty discussion of bits and bytes, different types of numbers such as integer versus floating point, the binary system, Booleans, and character strings. Arrays, which are sets of values, were introduced. Comparisons were made between strongly typed and weakly typed languages. In this chapter, you n
Learned about variables and how they are used in programs.
n
Learned what is meant by datatype.
n
Came to know the difference between bit and byte.
n
Discovered how bits represent numbers using the binary system and characters using character codes.
n
Added to your experience using arrays and instances of classes.
n
Gained some understanding of the difference between weakly typed and strongly typed languages. JavaScript and ActionScript are both weakly typed.
n
Acquired experience using built-in objects in HTML and JavaScript.
You may ask why the counts of heads and tails could not be displayed directly on the Web page and updated in place, so to speak, instead of using
Chapter Summary
internal variables. To perform this addition, it would be necessary to use code such as document.c.headscount.value = 1+parseInt(document.c.headscount.value);
assuming that c was the name of the form and headscount was the name of the element within the form. This certainly could be done. However, the approach shown here allowed you to compose the display in another way. In any case, many applications are best done with internal variables not on view by the user. An important lesson from the sample applications in this chapter is the progression from the simplest case to more elaborate cases. Most programming is done in an iterative fashion.
In the Real World Simulations of events involving pseudo-random, also called stochastic, calculations are common in industry and in research. There are even actions corresponding to changing weightings. For example, banks need to test whether their networks can handle variable traffic at ATMs located throughout the city. Simulations are used to determine optimum places to locate stations such as ATMs. Market research firms use simulations to gather data on products, ads, and promotions. Some industrial applications use the equivalent of alert windows—that is, messages that need to be closed; others use messages on the screen that do not require explicit attention. You need to consider each case and decide what is required. Alert windows, and their equivalents in other languages (trace is the function for Flash), are useful during debugging. The complicated rules governing access and persistence of variables may strike you as misguided. You may say, ‘‘If my code uses the variable tid both inside a function and inside the body as part of event handling, I intended this to be the same variable.’’ The problem is that both you and your colleague down the hall or around the world may be working on parts of the same application. If you use the same variable name for different values, your program will not work correctly. It is best if variables and other entities are assumed local and, therefore, distinct unless explicitly set up to be shared.
115
116
Chapter 5
n
Variables and Datatypes
What’s Next All the rest of the examples will include use of variables. Chapter 6, ‘‘Functions and Parameters,’’ continues games of chance by an implementation of Rock, Paper, Scissors. Chapter 7 focuses on the Craps dice game.
Review Questions 1. How do you set up a button using an HTML form? 2. How do you set up a field for a user to enter data for an application? 3. What does onSubmit do in the tag? 4. What does parseFloat achieve? 5. If the variable X held the value 5, what would be its value after the statement X++ was executed?
On Your Own 1. Change the alert statements to put messages in new tags that you have set up in one of the forms. 2. Enhance the initial coin toss game (the one with a fair coin) to include betting on the outcome. You will need to set up an field to call the flip. You will need to keep score of how many times the player called what actually happened. The details are up to you.
chapter 6
Functions and Parameters This chapter will continue the study of programmer-defined functions started in previous chapters, with focus on defining a function with parameters. The chapter also addresses the topic of how to encode features of the application such as the rules of a game. After studying this chapter, you will n
Understand the role of function parameters
n
Learn how different programming languages provide the function parameter feature and some of the different terminology used
n
Appreciate how aspects of a representation or encoding can be arbitrary
n
Acquire experience using function parameters, arrays, and global and local variables in JavaScript
Motivating Example The example for this chapter is a computer version of the playground game, Rock, Paper, Scissors. On the playground, two people face each other, and on the count of three, they make a hand gesture, called a throw, indicating rock, paper, or scissors. The rules are that rock breaks scissors, paper covers rock, and scissors cuts paper. If the two opponents throw the same thing, it is a tie. In the computer game, the player plays against a virtual opponent, who I call the computer. An opening screen for the game is shown in Figure 6.1. 117
118
Chapter 6
n
Functions and Parameters
Figure 6.1 Opening screen shot for Rock, Paper, Scissors.
The three pictures on the screen are actually buttons. When the player clicks on one, say paper, the program makes a choice for the computer, and the rules of the game are applied. In Figure 6.2, the program indicates a tie because both player and computer have chosen paper. In Figure 6.3, the screen displays that the player has won, since the player clicked on paper and the computer selected rock. This design does depend on the player remembering his choice and having the faith that the program is fair. In this instance, ‘‘fair’’ means that the computer’s choice is based on a random calculation and not knowledge of the player’s move. You can make this game fancier by including a graphic for each result. For example, Figure 6.4 shows a paper covering a rock as a result of the player throwing paper and the computer throwing rock. In Figure 6.5, the player has thrown rock and the computer has thrown scissors, resulting in another player win. In Figure 6.6, the computer wins by throwing scissors when the player threw paper.
Motivating Example
Figure 6.2 Screen shot showing a tie.
Figure 6.3 Screen shot indicating player win.
The critical features required by this application include n
A mechanism for the player to indicate his move
n
Pseudo-random facilities to produce the computer move
119
120
Chapter 6
n
Functions and Parameters
Figure 6.4 Result is paper covering rock. n
Ways for the program to display the results
n
Incorporating the rules of the game into the program
Introduction to Concepts As was described in previous chapters, all programming languages provide programmers a way to extend the language by defining their own functions or procedures, pieces of code that can be invoked by name. One reason to do this is to avoid writing the same code multiple times. When a function is defined, it can be called (invoked) from multiple places. Programming languages have built-in functions and provide a way for programmers to define their own functions. Caution I repeat the caution on terminology. In some languages, a function is a procedure that returns a value so that the function call can occur within an expression or wherever an expression can occur, such as on the right side of an assignment statement. If the procedure does not return a value, it is not called a function. For example, in VB .NET, subroutines are procedures that do not return values. The strongly typed languages require definition of the datatype of the returned value in the definition of the procedure. You do not have to be concerned with this when using JavaScript.
Introduction to Concepts
Figure 6.5 Result is rock breaking scissors.
Some languages support what are termed classes. A class defines code (the methods) and data (called properties or attributes that the methods act on). Class methods are procedures defined as part of the definition of a class. You already have seen the Math class in action. I use the methods random and floor, which belong to the Math class, to generate the computer move in Rock, Paper, Scissors. Strings are implemented in JavaScript as instances of a String class. If a variable is assigned a string literal, as in title = "Logic";
then you can write code using String properties title.length
and String methods title.substring(a,b)
121
122
Chapter 6
n
Functions and Parameters
Figure 6.6 Result is scissors cutting paper.
There are many other String methods. JavaScript and most other scripting and programming languages give people the facility to define their own functions. Functions can be called with extra information, a folksy way of describing what you have seen between the parentheses after the function name as part of the call. Here again, terminology differs. Some languages refer to the values in the call as arguments and the values in the procedure definition as parameters, and some languages use either term for both situations. I will use the same function to accept the player’s throw, determine the computer’s throw, and carry out the rules of the game. Games and other applications often require aspects of the application to be encoded in some way in the program. I used 0 for rock, 1 for paper, and 2 for scissors. This encoding can take different forms, and you will read about strategies in this and other chapters. One subtle point is that often the encodings are arbitrary—that is, they’re totally up to you, the programmer. Many different
Introduction to Concepts
ways would work. This arbitrariness can be unsettling. Did I force something special into the game by choosing 0 for rock? The answer is no. Every application has its own distinct set of representation issues, but I hope the Rock, Paper, Scissors example and the others in this text will contribute to your programming education. The examples will feature calling one function with different parameters. The parameter will indicate the player move. The rules of the game will be encoded in a sequence of if statements.
Procedure Definition Header Line A programmer-defined procedure is defined in different programming languages by a header or prototype line with a mixture of keywords—sometimes called modifiers—that specify attributes of the procedure; the programmer-given name of the procedure; names; and, with some languages, datatype information for the parameters. If the procedure returns a value, the strongly typed languages require datatype information on the returned value. In JavaScript, the header line takes the following format: function functionname (parametername1, parametername2...)
The keyword function is required and must be spelled correctly. What is indicated here as functionname is up to the programmer. Generally, names need to start with a letter and cannot have blanks. Tip Make function names, variable names, and parameter names meaningful even if that means making them longer. Don’t economize on typing. You will spend more time examining your code than typing it.
If there are no parameters, the function name is followed by opening and closing parentheses. The parentheses are still needed. Without the parentheses, the function name will not invoke the function but just refer to it as an entity. I will show uses of function names by themselves in Chapter 9, ‘‘Objects.’’ If there are parameters, then when the function is invoked, the values specified in the call are given the parameter names for use inside the function. Using the Rock, Paper, Scissors example, the function used to generate the computer move starts with the header statement function computerturn (player)
123
124
Chapter 6
n
Functions and Parameters
and the function is called with the statement computerturn("rock");
The technical jargon is that "rock" is passed as the parameter. In the function computerturn, whenever code refers to player, as in if (computer==player)
will have the value "rock" unless player has been assigned a different value within the function. The parameter player is treated as a local variable, with the value set by the call. When computerturn completes, the variable named player is no longer accessible. player
Note In the implementation of most programming languages, space for the local variables is assigned in the memory circuitry of the computer when a function is invoked. When the function completes, the association between the locations in memory and the variable names goes away, and the memory is available for other purposes. Python Example As an example of a procedure definition in another scripting language, here is a function definition in Python: def perimeter (len, wid): return 2*len + 2* wid
The header line uses the keyword def and ends with a colon. Each line within the function must be indented.
Call by Value Versus Call by Reference The discussion so far has focused on use of the parameter values. What if the code changes the parameter value—that is, the variable in the procedure holding the parameter that was passed? When local variables are changed, the change lasts as long as the variable, only until the procedure ends. If a procedure is called with a variable A as one of the parameters, and that parameter is changed in the procedure, will the variable A be changed when the procedure is complete and control returns to the point of the call? The answer: it depends. In JavaScript, the parameters are called by value. This means that the value of the parameter is calculated and passed to the called procedure. The opposite of this is called by reference. In this case, what is passed to the procedure is a reference to the variable, so the variable itself will be changed if it is changed within the called procedure. In some languages, the programmer has a choice and can specify which of the two it is to be for each parameter.
Introduction to Concepts
An exception to the call by value rule in JavaScript concerns arrays. Recall that an array is a sequence of values. In the Rock, Paper, Scissors example, an array will be used to hold the three strings "rock", "paper", and "scissors". (This array is never changed in the Rock, Paper, Scissors applications.) The JavaScript processor passes a copy of header type information about an array when an array variable is named in the function call. This information allows the called program to make some changes to the original array, such as changing one of the elements. The following HTML/JavaScript file demonstrates calling a function with an array as a parameter and changing the array in the function. <script> var origa = [1, 2, 3]; testparms(origa); alert("This is origa after the call: "+origa); function testparms (theparm) { theparm[1] = "Hello"; } nothing
The sequence of operations, also referred to as the flow of control, for this example is the following: load script element execute var statement setting up the variable origa as an array set up definition of the testparms function execute call of testparms, using origa as the parameter execute the statements in testparms, with theparm set to be origa return from testparms execute alert statement load body element
125
126
Chapter 6
n
Functions and Parameters
Figure 6.7 Alert box showing value of array variable after function call.
(The purpose of this exercise is to see what appears in the alert box. After clicking on OK for the alert box, the element is loaded, and the word nothing appears on the screen.) The alert box shown in Figure 6.7 indicates that the element with index 1 in the array has, indeed, been changed. Note Index 1 refers to the second element in the array, since array elements start at 0.
However, if the code changes the variable a to be a string or a number or a different array, these changes will not persist. Try it! This behavior is repeated in some other languages. The alert reader may now ask what happens to strings. Will a string defined outside a function be changed by code inside a function? The exact analog to the array example, changing one character in the string in place, cannot be done. If the code in the function assigns a new string to the parameter value, the original string remains the same. Given the file, <script> var origs = "This is the original string."; testparms(origs); alert("This is origs after the call: "+origs); function testparms (a) { a = "Now this is a new string"; }
Introduction to Concepts nothing
The alert box shown in Figure 6.8 shows that the variable still holds the original string.
Figure 6.8 Alert box showing string variable after function call. Note In what has been discussed, the correspondence between values in the call and values in the procedure was based on the order of the values: the first value in the call is assigned to the first parameter in the definition of the function, the second to the second, and so on. There are languages supporting the technique in which parameters are indicated by name. This is similar to the use of attributes in HTML tags:
is the same as
Representation of Application Features The last general topic is representation of application features. This topic is not easy to discuss in the abstract, so most of the exposition will be in the ‘‘Use of Concepts in Implementation’’ and ‘‘Chapter Summary’’ sections. In games and other applications, it may be necessary to represent different choices. In Rock, Paper, Scissors, the player indicates a choice by clicking on one of three buttons. To be fair, my program calculates the computer move using the pseudo-random features. The tactic chosen here is to code a calculation that returns the values 0, 1, or 2. These values, in turn, are used as index values for an array that has been set up to hold the strings "rock", "paper", and "scissors". This uses the order of choices as they appear in the name of the game, but it is really arbitrary. The player is not aware that the Math.random method returns a value
127
128
Chapter 6
n
Functions and Parameters
that was then mapped to a number and used as an index. This type of representation is common in programming.
Rock, Paper, Scissors This section reviews the use of functions in previous chapters and then goes on to describe construction of two versions of Rock, Paper, Scissors using JavaScript.
Review of Previous Examples The previous uses of programmer-defined functions generally took no parameters and did not return values. With regard to returning values, to use terminology for some programming languages other than JavaScript, they were procedures or subroutines, not functions. Note A procedure that does something other than calculate or generate a value is said to have side effects.
The money function, described in Chapter 3, ‘‘Extending the Basic Language,’’ as an alternative approach for the example in Chapter 2, ‘‘Basics,’’ was a true function. It returned a value, a string. The money function had one parameter: a number representing a cost. The function produced a string that represented the number in proper dollars-and-cents formatting. The call to the money function was on the right side of an assignment statement. The target, indicated on the left side of the assignment statement, was the value of the element in the HTML page. The coding for this function, because it was in JavaScript, did not have datatype declarations. However, the programmer needed to be aware of the datatype. The parameter value was used in a concatenation operation with a string formatteds = orig + "00";
to produce a string that was, in turn, manipulated to produce the result. In contrast to the programmer-defined functions, there have been many uses of built-in functions. For example, the Math.random method was used without parameters to produce values used in the coin flip examples. The parseFloat function was used to take a string input by the player and produce a floatingpoint number (a number with a fraction): bias = parseFloat(document.b.sbias.value);
Rock, Paper, Scissors
The coin tossing games in Chapter 5, ‘‘Variables and Datatypes,’’ used Math.random to obtain a random value between 0 and 1. For Rock, Paper, Scissors, I want a random choice of three possibilities. I’ll still use Math.random, but I’ll include it in a more complex calculation.
Plan of Attack for Rock, Paper, Scissors The general plan of attack for Rock, Paper, Scissors is to build a text-only game and then enhance it with graphics. The body of the HTML document contains buttons, implemented as elements, for the player to make his move. The action in the elements is three different calls to a function, computerturn. This function generates the computer move and then applies the rules of the game. The results are displayed for the player. You can see that the computer makes its moves after the player, but because computers are fast, the player experiences the moves as being simultaneous. The outline for the HTML document is html
element
head
element
title
element
script
element
options array holding the choices definition of computerturn function body
element
heading directions form
element
input
element for computer throw
input
element for winner
hyperlink/button for rock hyperlink/button for paper hyperlink/button for scissors (for the graphics version) img element to show results
129
130
Chapter 6
n
Functions and Parameters
Use of Concepts in Implementation In explaining the application, I will proceed as I actually built the implementation, starting first with a simple text version of the game and then enhancing it to the graphics version shown in the figures at the start of this chapter. Text Game
The text-only version of the game does not use pictures. Tip Working incrementally is the best and the fastest way to program. I first made a text-only version of the code so I could get started quickly and focus on the logic. It then was easy to add the graphics.
The contents of the elements are text: Rock, Paper, and Scissors (see Figure 6.9). There is no picture indicating the results. This will change for the graphics version of the game.
Figure 6.9 Opening screen for text version of Rock, Paper, Scissors.
This application uses functions and parameters, which are the focus of this chapter. Now I, as an author, have a problem. Should I show the function definition first or the calls first? There is no right answer. So I will show the way I think about things when I am creating scripts. I will show and explain the part of the HTML document first and then show the rest of the document, with the <script> element containing the functions. My plan is to create a function that generates the computer move and applies the rules of the game based on that move and the player’s move. I use the player’s move as a parameter for the function. The of the HTML document looks like this; you can see the calls to the computerturn function in the tags:
Rock, Paper, Scissors Rock, Paper, Scissors Click on your choice! Computer played Winner Rock Paper Scissors
The forces a space and makes the screen look better. The use of single and double quotation marks is important. The double quotation marks surround the values of the href attribute. Inside, I needed to indicate strings. If I wrote Rock
JavaScript would have ended the attribute value at the second double quotation mark: 50:
is allowable. After each case is executed, flow of execution jumps out of the structure. The days-of-the-month example is SELECT CASE (month) CASE "Sep", "Apr", "Jun", "Nov": print "This month has 30 days." CASE "Feb": print "This month has 28 or 29 days." CASE ELSE: print "This month has 31 days." END SELECT
Dice Game
The VB format uses line breaks for bracketing. Only the code following each case definition is executed, so there is no need for a break statement. The language for transforming eXtended Markup Language (XML) documents, eXtended Stylesheet Language (XSL) has a form of switch statement available using <xsl:choose>, <xsl:when>, and <xsl:otherwise> elements. The intent in telling you about these different languages is to impress the point that the construct is widely available, but there are significant features you must understand to use the facility in the particular language. The logic of the Craps game in both versions will be programmed using a combination of if and switch statements.
Arrays The HTML with JavaScript example will display images of the faces of dice by setting up an array of HTML image objects as elements of the array. A subtle point here is that it is up to the builder of the application to make sure that the file names assigned to the src attributes of the images hold pictures corresponding to the appropriate value. The image file for the die face with two dots must show a die face with two dots! For the HTML with JavaScript implementation, the nth element of the array of images needs to refer to an image file that shows a die face with n þ 1 dots. Note that I could ignore the 0th element and start with 1, but I chose not to do this. The pseudo-random calculation will produce a whole number from 0 to 5, and this will be used as an index to reference an element of the array. The element of the array will be an image that has an image file with one to six dots.
Dice Game This section reviews the use of global variables and arrays in previous chapters and then goes on to present two versions of the dice game Craps.
Review of Previous Examples The Rock, Paper, Scissors example in Chapter 6 used global variables and arrays in the options variable. var options=new Array(); options[0] = "rock";
149
150
Chapter 7
Application State
n
options[1] = "paper"; options[2] = "scissors";
It is a subtle point that this is not state data but rather information required for the implementation. The values in this array variable do not change. In contrast, the coin toss example in Chapter 5, ‘‘Variables and Datatypes,’’ that kept track of the counts of heads and tails used global variables, the values changed, and thus they could be construed as state of the game information. In Chapter 4, ‘‘Events and Event Handling and the Graphical User Interface,’’ the version of the Find Daniel game that enforced a time limit used a variable, tid, to turn off the timing event when the player clicked on the correct area of the photograph. As indicated in that chapter, this needed to be a global variable so that it could be accessed in code in different places.
Plan of Attack for the Dice Game The outline of the HTML with JavaScript implementation is html
element
head
element
script faces
element
array holding image files
global variable firstturn global variable pointvalue function definition for dthrow, including if and switch statements for logic. body
element
img a
elements for each die
element to invoke dthrow
form
element to hold input elements for display
Use of Concepts in Implementation Now it is time to go into detail on the implementations of the Craps game. For the HTML with JavaScript implementation, it is assumed that, by this time, you know the basic organization of an HTML document. At some point, you will need to create image files showing die faces: six images, showing one dot, two dots, and so on.
Dice Game
Following the outline given in the previous section, the first critical step is to create the faces array. This could be an array of strings. However, a slightly more effective approach is to create HTML image objects of a specified width and height and then set the src attributes to be the appropriate string value. The tactic here is make the 0th element correspond to the die face with 1 dot, the 1st element correspond to 2 dots, and so on. The following coding sets up the array. var faces = new Array; faces[0] = new Image(50,50); faces[0].src = "dice1.gif"; faces[1] = new Image(50,50); faces[1].src = "dice2.gif"; faces[2] = new Image(50,50); faces[2].src = "dice3.gif"; faces[3] = new Image(50,50); faces[3].src = "dice4.gif"; faces[4] = new Image(50,50); faces[4].src = "dice5.gif"; faces[5] = new Image(50,50); faces[5].src = "dice6.gif";
Note It turns out that the approach of using image objects forces the browser to load the images at the start, preventing delays later on.
The next step is to set up the two variables holding the state information. The one indicating firstturn status requires a var statement with initialization. The variable that will hold the point value just needs a var statement. var firstturn = true; var pointvalue;
The definition of the function that does all the work follows with a line-by-line explanation. Certain lines require you to know or have faith in the coding that will appear in the element. You need to decide on the names of the images and the form elements. JavaScript
Explanation
function dthrow() {
Start function header.
var choice;
Hold random choice 0 to 5. Hold one die value. Hold one die value.
var die1v; var die2v;
151
152
Chapter 7
n
Application State
JavaScript
Explanation
var sum;
Hold the sum. Acquire random value 0 to 5. Increment to get the die value to use in sum. Use choice to set one visible die image. Acquire (another) random value 0 to 5. Increment to get the die value to use in sum. Use choice to set the other visible die image. Calculate to get value of throw. Check if this is a first turn. Wipe out any point value information from a prior game. Start switch based on sum. Check if sum is 7. Check if sum is 11. Indicate a win. Break out of switch. Check if sum is 2. Check if sum is 3. Check if sum is 12. Indicate a loss. Break out of switch. Set up default case. Change application state. Save sum to be the point value. Display the point value. Display message to throw again.
choice=Math.floor(Math.random()*6); die1v = choice+1; document.dieimagea.src=faces[choice].src; choice=Math.floor(Math.random()*6); die2v = choice+1; document.dieimageb.src=faces[choice].src; sum = die1v + die2v; if (firstturn) { document.f.point.value = ""; switch (sum) { case 7: case 11: document.f.status.value = "You win!"; break; case 2: case 3: case 12: document.f.status.value = "You lose."; break; default: firstturn = false; pointvalue = sum; document.f.point.value = pointvalue; document.f.status.value ="Throw again for your point."; } } else { switch (sum) { case 7: document.f.status.value = "You lose."; firstturn = true; break; case pointvalue: document.f.status.value = "You win."; firstturn = true; } } }
End switch. End if-true. Start else, which signifies the follow-up application state. Start switch based on sum. Check if sum is 7. Indicate a loss. Reset firstturn back to true. Break out of switch. Check if sum equals the pointvalue. Indicate a win. Reset firstturn back to true. End switch. End else clause. End dthrow function.
Dice Game
Notice that if a follow-up throw was something other than 7 or the point value, nothing needs to be done. Following the outline given previously, the element contains two elements that each will have the src attribute modified to display the appropriate image.
The actual call to the dthrow function is accomplished by setting the onClick handler in an a tag. Click to throw dice.
Lastly, elements in a element are used for display, or output. Status Point value
If you build this or any other application, you need to test it thoroughly. This means testing for each of the winning and the losing situations and testing that the game can start again after a win or a loss.
What Can Go Wrong The HTML with JavaScript implementation of the dice game does require that the image files representing the die faces be prepared in the image format referenced in the code, named to correspond with the names used in the code, and stored in the same folder as the HTML file. Alternatively, the image files can be in another folder and the appropriate reference used. For example,
A way to confirm this is to change the initial src value of the two img tags systematically to check for each of the six files. This application involves nested bracketing—that is, { and } symbols—to define the clauses of if statements and switch statements, which can be tricky. The JavaScript console in the Mozilla or Netscape browsers will be helpful sometimes,
153
154
Chapter 7
n
Application State
but for the most part, you are on your own in HTML and JavaScript. A good practice is to type the opening bracket, skip a line and type a closing bracket, and then go back and fill in what goes in between. A deeper issue is to make sure you really understand the rules of the game of Craps. Then be patient when testing. You need to test for many possibilities, not just play the game until you win! Your application may be working perfectly, and it can still take many turns before winning or losing.
Chapter Summary This chapter described ways to maintain information on the state of an application. The application state is critical in carrying out the rules of any game. The programming features included global variables and objects. The if and switch features were used to perform the logic.
What You Have Learned This chapter demonstrated the use of global variables to hold application state information, random processing, and conditional statements. The display for the player included graphics and text. You learned n
What is meant by the state of an application
n
How and why to use global variables for state information in a scripting language
n
How to use a switch statement for application (game) logic
n
How to display image files based on a computation involving random processing
n
How to communicate with the player using text and graphics images
The variables in the JavaScript example were accessible everywhere. The implementation of the game was restricted to the single function computerturn so there could be some degree of information hiding. The issue was not keeping secrets but making it unnecessary to review all the code for all changes.
Chapter Summary
In the Real World In industrial applications involving events that do not happen according to a fixed schedule or pattern, testing is a challenge. There are many such applications. In addition to games, consider networks of ATM machines; control of the steering, braking and gear shifting in cars; and operating banks of elevators. The first stages of testing may consist of specifying occurrences and only later use facilities such as random number generators to simulate what would happen in the real world. Building the testing system is itself a considerable undertaking.
What’s Next Chapter 8, ‘‘Automating a Physical Application,’’ demonstrates further use of arrays, including another example of parallel structures and for loops. The featured example is a JavaScript version of the game of Memory, also known as Concentration. Chapter 9, ‘‘Objects,’’ describes the use of programmer-defined objects in ActionScript. The featured example is a picture quiz.
Review Questions 1. Describe what is meant by the state of the Craps game. 2. Describe what is meant by the state of the game in a game of your choosing, such as Texas Hold-Em or another variant of poker. 3. What is the difference between global variables and local variables? 4. What are the state variables in the Craps game? 5. Describe the workings of a switch statement.
On Your Own 1. Write the logic using if statements in place of the switch statements to perform the logic of the game of Craps. 2. Write the code to change the image displayed using the HTML to car.gif? What is the code for changing
HTML to "ALL"?
the text displayed using the
155
This page intentionally left blank
chapter 8
Automating a Physical Application This chapter will continue the study of arrays. Arrays are an important way of structuring information and are provided in most programming languages. The application featured in this chapter brings several general issues of program development into discussion: automating a real-world application, testing, and scaling up. In this chapter, you will n
Learn about arrays and collections
n
Gain experience using loops to manipulate array elements
n
Acquire an appreciation of what may be required for a computer implementation of an application, specifically when it is necessary to program a pause
n
Learn favorable ways to test an application
n
Practice using JavaScript arrays, the image collection of the Document Object Model for HTML documents, JavaScript for loops, and functions setting up timed events
Motivating Example The game Memory, also called Concentration, typically is played with a set of cards consisting of some number of pairs of matching cards. Figure 8.1 shows the opening screen for a computer Memory game using just six cards. The hyperlink to shuffle the cards may be removed for the final version of the game. 157
158
Chapter 8
n
Automating a Physical Application
Figure 8.1 Opening screen for Memory game. Note The motivating example for this chapter, as with the others, is a game. You may question calling this a ‘‘real-world application,’’ but it is. It is played in the physical world. Your potential audience of users has ideas about how this application works in real life, away from computers. When you attempt to produce a computer version of such an application, you need to be aware of these aspects of the application. Similarly, you need to be aware of people’s experiences with other computer applications. You must consider all these factors when designing and building applications. For example, when people fill out forms online, they bring their experience in filling out physical forms and computer forms. They do expect that errors will be caught and they will be helped. They do not want time pressure.
The player chooses two of the cards. Something like Figure 8.2 may appear. The display in Figure 8.2 will remain on the screen only for a short time before the original screen reappears. This simulates the cards being flipped back. Of course, there are no actual cards—just image files assigned to specified positions.
Motivating Example
Figure 8.2 Screen shot after player moves.
If the player clicks on two cards assigned to the same image—that is, a matched pair—these images remain visible, as shown in Figure 8.3. You will read about how to implement this game and then how to take steps to implement a larger, improved version. The critical features required for this application include n
A way to represent the game board—namely, the cards as images that can change back and forth between an image representing the blank card back and images representing the card face.
n
A way for clicking on the card to invoke a function.
n
Variables representing the state of the game so that the function can distinguish first turn and second turn and, upon the second turn, compare the two card faces.
159
160
Chapter 8
n
Automating a Physical Application
Figure 8.3 Player finds a match. n
A way to simulate shuffling of the cards.
n
A way to insert a pause so that the player has time to study the card faces.
n
A way to determine when the game is over. There is no way in the basic game for the player to lose, but it is necessary to determine when the player has won by matching all the pairs of cards.
n
A way to prevent a player from clicking on more than two cards. Because there will be a pause after clicking on the second card, a fast player could keep clicking to reveal more card faces.
Introduction to Concepts An array is an aggregation of data. Most programming languages provide arrays, although, as always, the details differ. If you need to represent a set of things, such as a sequence of cards, a set of choices in a menu, income from a set of stores,
Introduction to Concepts
grades of students in a class, and so on, you can use arrays. The code to reference a member of the set uses an index value or a key value. A challenge is not to confuse the index or key value with the contents of the array member for that index or key value. Repeating a sequence of statements, looping, is a common requirement for programming. You may know the number of times you need a sequence of statements to be repeated, or it may depend on the value of a variable. Looping is especially useful when manipulating arrays. The computer implementation of a manual task can require extra or different steps to work at all or to work in an efficient way. This will be discussed in a general way and then illustrated with the game of Memory. Testing a program, making sure the application works as required, can take as long as the initial coding. There are ways to make testing easier.
Arrays and Collections You have seen JavaScript arrays in previous examples. These were the simplest types of arrays: sequences of values—all of the same datatype—with the individual members accessible by index values, numbers going from 0 to 1 less than the number of elements in the array. Assuming the example from Chapter 6, var options = [ "rock", "paper", "scissors" ];
then the assignment statement played = options[1];
would assign "paper" to the variable played. More typically, the index value in an expression involving an array would not be a constant, but a variable. played = options[answer];
would be interpreted as follows by the language processor: Locate the variable options, confirm that it is an array, and determine the length to know what the allowable index values (the array bounds).
161
162
Chapter 8
n
Automating a Physical Application
Figure 8.4 Schematic for array and index variable.
Figure 8.5 Schematic showing variable pointing to array element.
Locate the variable answer and extract its value. Confirm whether the value is an integer within the array bounds. Assuming everything is confirmed okay, extract the indicated element of the array. Figure 8.4 shows two variables, answer and options, with actual contents for the elements of options and n indicating that answer holds something, but exactly what is not known. You can think of the variable answer as a pointer into the array. Figure 8.5 shows this. Languages differ in what happens when a value is used as an array index that is not within bounds of the array. This could be a number that is too small (less than zero), too big, or a value that is not a number at all. Note Cþþ is a programming language that does not do runtime checking on array bounds. This means that if the value of answer was greater than 2, something would be assigned to played, but not what was intended. Similarly, if the assignment statement was options[answer] = played;
Introduction to Concepts and answer held an incorrect value, then the value of played would be plopped down in an incorrect location. One of the advantages many see in Java over Cþþ is that there is runtime checking on array bounds. You do need to realize that this feature comes with a cost: the runtime check takes time.
The behavior of JavaScript is complex with respect to assignments to a position in an array using an index value that is out of bounds. If answer held an integer value, say 4; played held the string "dirt"; and the assignment statement options[answer] = played;
was executed, then the value held by the options array would be "rock", "paper", "scissors", , "dirt"
meaning that the item at the 3rd position was undefined, but the 4th position was the string "dirt". JavaScript creates and sets the new element. An assignment statement played = options[answer];
would not trigger an error, but later use of the variable played might cause an error because it has the value undefined. As you would expect, strongly typed languages require array variables to be declared. Some languages fix the size of the array at declaration time, and others allow the array to grow or shrink. Some languages allow flexibility for the ranges of index values; they do not have to be 0 to 1 less than the number of items in the array. For example, in certain languages, the index values could be set to be 2000 to 2005 for a problem involving data stored by year. Note Arrays can be more complex. Some programming languages support arrays in which the elements are not all the same datatype. And some programming languages support multidimensional arrays directly. Others provide this feature by allowing one-dimensional arrays in which the elements are themselves arrays.
An associative array holds elements accessible by keys. A key can be any value type. A standard example is a set of values, each associated with a day of the week. The keys are strings spelling out the days. If the associative array is classes, then classes[’Monday’]
would show information about Monday classes. If the variable currentday held a string indicating one of the days of the week, then classes[currentday]
163
164
Chapter 8
n
Automating a Physical Application
would show information for that day. Now, you may be saying that this is nice, but it would not be that much trouble to encode the days of the week as numbers. This is, in fact, what the Date class does. Associative arrays provide an alternative approach. Note Associative arrays also can be used when the keys are not known ahead of time. To demonstrate this, here is a typical example from PHP, a language for server-side programming, often used for online stores. In PHP, variable names start with a dollar sign. Assume that $cart is to hold information on what someone has ordered, $product holds the code for the product being ordered, and $quantity holds the quantity. In that case, $cart[$product] = $quantity would be used to add the order of $qty of $product. The key/value pair, $product/ $quantity, has been added to the associative array $cart.
The Document Object Model (DOM) that defines how to write code relating to an HTML document specifies several collections, sets of elements with the same name and a similar structure. The images collection can be used like an array to reference and set the attributes of tags. Note You can read the full specification of the DOM at http://www.w3.org/DOM.
A common technique in programming is to use parallel structures to represent aspects of an application. The first element in one structure corresponds to the first element in the other, the second element in one structure corresponds to the second element in the other, and the last corresponds to the last and everything in between. In the Memory game featured in the chapter, an array named faces holds the file names of images that are to be displayed in the corresponding member of the document.images collection.
Looping Looping was an early addition to programming languages. Abstractly, a loop specifies a starting value for the loop or index variable, a condition that determines if the body of the loop is to be executed and determines a changing operation for the loop variable. This last operation can be called the incrementing step, but it need not be restricted to adding to the loop variable. The loop variable can be used inside the body of the loop or elsewhere. In JavaScript, the for loop follows the concise syntax of Cþþ and Java. Any variable can be used, but
Introduction to Concepts
following a convention established with Fortran many years ago, the name you will see most frequently is i. Assuming that start and last are numbers, the code for (i=start; i $qty) {. The body of the loop would be repeated for each key/value pair in the array. In the body, the code would reference the key as $pid and the value as $qty.
The Memory application uses looping to shuffle the cards.
Array Operations: push, pop, and slice There are multiple ways to assign values to an array variable. In JavaScript, the statement var models = new Array();
defines models to be an array variable, but it does not assign a value to the variable. You can assign the whole array or assign values to elements of the array, as was shown previously in the options example.
165
166
Chapter 8
n
Automating a Physical Application
An array variable can be set up with values in the declaration statement. var models = [ "heart", "crane", "frogface" ]
Tip The multiple lines used in the declaration of models makes it easy to add new elements. However, you still need to be careful to put commas after each entry except the last one.
Another technique for adding elements to an array is to use the push method. Assuming that models is still the array with three elements, as declared and initialized in the previous code, the statement models.push("box");
will add an element to the end of the variable. Imagine a stack of dishes in a cafeteria, and you are pushing an item at the top of the stack. The models array is now ["heart", "crane", "frogface", "box"]
The pop method performs two tasks. It removes the last element from the array and returns that value. So after the statement last = models.pop();
is executed, the variable last has the value "box", and models is back to being ["heart", "crane", "frogface"]
Tip The push and pop operations are called last in/first out processing, also known as stack processing.
The splice method combines removing and adding elements to an array. The name is intended to invoke the action of cutting something out and grafting something in its place. The method has two or more parameters. The first parameter indicates the position where the splicing is to start; the second parameter is the number of elements to be removed. The splice method can have one or more optional parameters after these first two. These parameters are values to be added, or spliced, into the array.
Introduction to Concepts
Assuming the models array is ["heart", "crane", "frogface", "box"]
the models.splice(1,2) will change the array to be ["heart", "box"] Following this with models(0,1,"bird","fox","purse");
will make the variable be ["bird", "fox", "purse", "box"].
Computer Versus Physical Version of an Application When automating a task or application that exists in a manual/physical/real-world version, one strategy is to take the manual way as a model and implement each step. This may or may not work and, if it does work, it may not produce the best results. When a player plays the physical Memory game that is the featured example of this chapter, he turns over one card and then another to reveal the faces. If the cards match, he takes them off the board. If the cards do not match, he flips them both over so the cards are face down again. One implementation of the computer Memory game would require the player to use the mouse to choose the cards and then touch the cards again to restore them to the face-down position. Most people would suggest letting the computer handle the flipping over or taking away as appropriate. This computer version differs from the original game because the tasks of the player have changed. The tasks are similar to other computer games. However, there is one additional issue for the game builder to address. The computer implementation needs to include a step that the real-world game did not have: the program must enforce a pause to make sure the player sees the unmatched cards. If a pause is not inserted into the program, the player will not see the second card. Putting in a pause will require setting up a timed event. Making the design of a computer program resemble the way a person would do the task manually may be committing an anthropomorphic error. An especially vivid example relates to washing clothes. Think about how people once brought their clothes to a river and pounded the clothes with rocks. You can imagine building an apparatus resembling this scene. This is not the design of a washing machine! Remind yourself of this example when designing programs. How do you know when to follow the manual approach or do something different? There is no strategy that applies all the time. What is true is that as you
167
168
Chapter 8
n
Automating a Physical Application
gain experience in computing, you will have examples of programs to use as models.
Testing and Scaling Up It is a mark of professionalism to test your application to see if it meets the requirements of the job. Previous chapters discussed the challenge of doing adequate testing when aspects of the application are random events. You must test for all situations. A related issue is that of scale. The final application may involve a large number of items. However, you often can test most of the logic using a small set. The sample application for this chapter is the Memory game, which can involve a large number of virtual cards. You should test your logic with a small set of cards in a known order. Then incorporate shuffling. Finally, once you confirm that the basic logic works, scale up the project to the number of cards that would make the game interesting. The trick here is to make the initial system incorporate all or most of the features of the final game. Tip A strategy for building games is to avoid the necessity of playing the game while you are building it. This may lead back to the issue of how to handle randomness. One tactic is to take randomness out of the initial implementation. Another tactic is to include randomness but make aspects of the application visible so that you, as developer/tester, know the state of the game.
Application: Memory The Memory application actually reuses several programming constructs that have been introduced.
Review of Previous Examples In Chapter 4, ‘‘Events and Event Handling and the Graphical Human Interface,’’ the timed version of the Find Daniel game used timed events. The timed event was started when the player began the game. If the timed event occurred, the specified event handler displayed a screen saying that time was up. The timed event was stopped if the player did locate Daniel correctly. Unlike the more subtle requirement that occurs in the Memory game, the timed version of Find Daniel called explicitly for a pause.
Application: Memory
The Rock, Paper, Scissors game in Chapter 6, ‘‘Functions and Parameters,’’ used an array, options, to hold the strings "rock", "paper", and "scissors". The elements in this array were never changed. Similarly, the Craps game featured in Chapter 7, ‘‘Application State,’’ used an unmodified array of images called faces for the die faces. The game of Craps in Chapter 7 required the program to maintain the game state: specifically, is this a first turn or a follow-up turn? In Memory, the player clicks to turn over one card and then another. The program must distinguish between first turn and second turn.
Plan of Attack for Memory The plan is to build and debug the application using a small number of cards. What is an appropriate number? Three pairs, for a total of six cards, is appropriate to test the application adequately. Two pairs is too small. Shuffling the cards will be done explicitly by using an tag with the call to shuffle. This provides a way not to shuffle for the initial testing and then check that shuffling works. This will be changed in the final version of the application. Most of the HTML and JavaScript features necessary for this application have been covered before. The game board is laid out using tags in the body element of the html document. The src attribute of each image is changed to switch between the card back and the card face. The document.images collection is used to access individual cards. The faces of each card are stored in an array named faces. The program uses the information in the faces array when displaying the card faces. The parallel structures of tags and the faces array are what implements the virtual cards. Each is the contents of an a element. The href attribute of the tag is assigned the value of a call to a function, choose, with the parameter for the call indicating which image. The cards are shuffled by manipulating the elements of the faces arrays. There are many ways of shuffling. The method used here is intended to simulate how children mix up cards when playing the physical Memory game. The pause is coded into the program by code in the choose function that invokes the setTimeout command to call a function check after a fixed amount of time.
169
170
Chapter 8
Automating a Physical Application
n
The check function does the checking and, as appropriate, restores the card back image to the images. A variable named cntr keeps track of the number of matches. When all matches have been made, the game is over. The necessity to prevent a player from cheating by clicking on more than two cards was not immediately obvious to the author. This is why you recruit other people to test your programs. A solution is to use a variable, turns, to keep count of the number of cards revealed. The choose function simply returns without doing anything if the value of turns is 2. The outline for the HTML document is html
element
head
element
script
element
global variables choose check
function
function
shuffle
function
body
heading and instructions table holding a elements holding img elements hyperlink calling shuffle function An appropriate method of documentation for applications is a table indicating function calls. This application has three functions, as shown in the table. Function
Invoked By
Invokes
choose
JavaScript code in tags in table. Contents are images. setTimeout action. JavaScript code in tag with contents Shuffle cards.
setTimeout
check shuffle
-------
Application: Memory
Use of Concepts in Implementation The application uses the faces array and six other global variables. The location of the image file names in the faces array determines which face will appear for each card. It is up to the programmer to ensure that the array elements correspond to pairs of file names. Here is an appropriate declaration: var faces = new Array( ’bird.gif’, ’heart.gif’, ’frog.gif’, ’frog.gif’, ’bird.gif’, ’heart.gif’ );
The numOfMatches variable is used with the variable cntr to determine if the game is over. To ease scaling up the application to hold more cards, numOfMatches is defined in terms of the length of the faces array. The cntr variable is initialized to 0. var numOfMatches = .5*faces.length; var cntr = 0;
Tip You want to minimize the places in the code that you need to change when you scale up the application for a large number of cards. Using the length attribute is one way to do this.
The turns variable, as indicated in the previous section, prevents cheating. It must be initialized to 0. var turns =0;
The choose function stores the index values indicating what card the player has selected. These values are stored in the global variables firstchoice and secondchoice. They do not need to be initialized. var firstchoice; var secondchoice;
The virtual flipping back of cards to show the card back and not the face means that it is necessary to ‘‘remember’’ the image file name. This is done using a variable: var backcard ="blank.gif";
171
172
Chapter 8
n
Automating a Physical Application
The explanation of how the functions work is better done after describing what is in the body of the document. HTML
Explanation
Start . Set up the name of the game onscreen as a heading. Display the instructions.
Memory game Choose two cards, trying to make a match. Matched cards will remain visible. Click on Shuffle Cards for a new arrangement.
Start the
element. Start the row. Set up the table datum holding an element, with contents an . Note that the href value is a call to the function choose with parameter 0. Set up the same thing with parameter 1.
Close this row and start a new one. Set up the same thing with parameter 2.
Set up the same thing with parameter 3.
End this row and start a new one. Set up the same thing with parameter 4.
Set up the same thing with parameter 5.
Close the row. Close the table. Insert a line break. Set up for a call to the shuffle function. Close .
Shuffle cards
The choose function is invoked, as indicated, with a parameter holding the index value of the image. Its job is to reveal the card faces, save information for later
Application: Memory
checking, and start the timed event using setTimeout. This operation both inserts the pause and sets up the call to the check function. JavaScript
Explanation
Start function definition. if (turns==2) { return ;} Return immediately if turns is 2. if (turns==0) { Check if it is a first turn. firstchoice=card; Save card value. document.images[card].src = faces[card]; Show face of this card using the images collection and the faces array. turns = 1; Set turns to 1. } End clause. else Start the else clause (only possibility is turns = 1). { turns = 2; Set turns to 2. secondchoice = card; Save card value. document.images[card].src =faces[card]; Show face of this card. setTimeout("check()",1000); Start timed event to invoke check after 1 second. } Close else clause. } Close function. function choose(card) {
The check function will be invoked only after the pause, set for 1000 milliseconds, which equals 1 second. It performs several tasks: determining if there was a match and, if so, adding to the count of matches. Determine if the game is complete. If there wasn’t a match, the images are returned to blank squares. JavaScript
Explanation
Define the function header. Use the stored index values to access the elements in faces to determine whether they are the same. cntr++; Increment the counter of matches. if (cntr == numOfMatches) { Check whether the game is over. alert("You won. Reload/refresh to replay"); Signal the win to the player. } End the clause. turns = 0; Reset the turns to 0. return ; Return. } End the clause. else { Start the else clause. document.images[firstchoice].src = backcard; Flip over the first card. Make this image show the backcard image.
Flip over the second card. Reset the turns to 0. Return. End the clause. End the function.
Shuffling is the subject of many research articles. The approach here is to mimic somewhat the way many children mix up cards: by grabbing a card with each hand and moving it to a new place on the floor. My code simulates grabbing two cards and swapping positions. This is done in code by randomly selecting two integers to be the index values for two elements in the faces array. Suppose that these values are i and j. The elements at these positions in the array are swapped. The code is holder = faces[i]; faces[i] = faces[j]; faces[j] = holder;
Notice that swapping requires an extra variable—in this case, the variable holder. The number of swaps is set at twice the size of faces. A for loop is used to perform the swaps. JavaScript
Explanation
function shuffle() {
Start the definition of the function. Set up the variable used for swapping. Set the number of swaps. Set up variables used in the loop.
var holder; var swapcount = 2* faces.length; var swaps; var i; var j; for (swaps=0; swaps<swapcount; swaps++) { i = Math.floor(Math.random()*faces.length); j = Math.floor(Math.random()*faces.length); holder = faces[i];
faces[i] = faces[j]; faces[j]=holder; } }
Start for loop for the actual shuffling; swapcount swaps will be made. Use a random expression to get one index. Use a random expression to get the second index. Perform the swap, which takes three assignment statements. Save the value that was at the position pointed to by variable i. Set this element to the value at the position pointed to by variable j. Use the saved value to set the position pointed to by variable j. Close the for loop. Close the function.
Application: Memory
You may ask whether there is a problem if the value of i and j are the same. The answer is no. The code would not accomplish anything for that cycle of the for loop, but there would be no harm, and it would be more trouble to prevent it than to allow it to happen. You should get this version of the application working. You will need four image files: three representing faces and one representing a card back. Notice that if you do not click on Shuffle Cards, you will know what face is associated with each card. This means that you do not have to play the game when debugging it. To add cards, you make a bigger faces array and add elements to the table. You probably need to change the value of the width attribute in the tags. Because of the definition of numOfMatches and swaplimit, the rest of the code will work. To make the game exciting, even for you, the game builder, you need to make shuffling part of the action and not under the control of the player. Remove the element Shuffle cards . Put a call to shuffle in the <script> section, right after the definition for the shuffle function. This means the cards will be shuffled whenever the HTML document is loaded. After a game is won, put code after the alert statement to restore all the images to show the card back image and call shuffle. Code to restore all the card backs is for (i=0; i<document.images.length; i++) { document.images[i].src = backcard; }
The ‘‘On Your Own’’ section includes ideas for enhancing the game. Prepare this application using TextPad or the equivalent. You need to create or acquire the image files for your card faces and save them in the same folder as the HTML file. Open the HTML document in a browser to test the program.
What Can Go Wrong The for loops provide opportunities for syntactic mistakes such as mismatched brackets. The nested if statements in the check function also require care. You need to ensure that the image files are correctly named and located in the same folder as the HTML document.
175
176
Chapter 8
n
Automating a Physical Application
You may decide that you want to improve the look of the game by adding images for decoration. The coding here assumes that all the images in the document.images collection represent cards. You will need to adjust the coding if this is not the case. For example, if you included one image before the table of cards, then calls to the choose function would start with 1, instead of 0.
Similarly, the for loop code to reset the images to be the card backs would start with i=1 in place of i=0. If you add decorative images at the end, you need to change the stopping condition in the for loop.
Chapter Summary This chapter used the familiar game of Memory/Concentration to demonstrate the use of arrays as well as including for loops to manipulate the contents of arrays. The Document Object Model definition of the images collection was used to access the elements. A programmer-defined array, faces, held the names of image files. The text also described a difference between computer games and manual games: when building a computer application, you need to give users adequate time to respond.
What You Have Learned In this chapter, you learned n
How to set up an array and access individual members of the array
n
How to use for loops with arrays
n
How the Document Object Model (DOM) provides ways to access and manipulate parts of an HTML document—specifically, the set of images
n
How the automation of a manual game may require additional steps, such as forcing a pause
n
How to test an application using a small set, and then how to scale up to a reasonable size
Automating a manual application can require modification of the steps, as demonstrated by the Memory game. Accommodating human time versus computer
Chapter Summary
time is just one example. You need to pay close attention to the layout of the screen for displaying information to the users and the mechanisms for obtaining information from the users. The pause amount indicated in the code is 1000 milliseconds, which is equal to 1 second. One second is actually a long time in computer games. You may consider changing it for the production version of this application. The ‘‘On Your Own’’ section suggests a more elaborate enhancement. When playing the regular game, no one thinks there are pauses. That is because the game is played at human speed, which is slow enough to study the cards. Because computer speeds are much faster than human speeds, programmers need to pay attention to their target user population and how they best operate. Problems can arise if the human/computer interface is too fast, too slow, inconsistent, or fails to meet expectations in any way.
In the Real World Testing a small version of an application and then scaling up to full size is a typical task in developing industrial applications. I hand-coded all the HTML for this application, including the details of the table holding the card images. In fact, the layout of the table tags can be done using the document.write function. In the script element in the head element, define a function: function createboard(ncols, nrows) { var c; var r; var imw = 500/ncols; document.write("
"); for (r = 0; r createboard();
The Memory game, with only six cards, three pairs, is not particularly difficult to play. However, a bigger version of the game or a more complex game application would be a challenge to debug while playing the game. Making the call to the shuffle function under (temporary) external control means that it is easier to debug. These are the types of tactics you need to devise to test applications. Memory can be the basis of an educational game in which the matches consist of related, but not identical images. You can set up a look-up table to determine matches. However, another way to implement this is to make the names of the matching image files partially agree. For example, for a game in which the player is to match images showing the shape of states with images holding the name, you would create images with file names such as nyname.gif and nymap.gif.
To check for a match, you would determine how many letters at the start of the game need to be checked. In this case, the answer is two, because the standard two-letter abbreviations for states are used. The substr String method extracts from a piece of a string starting at the position indicated by the first parameter and for the length indicated by a second parameter. If fn is the string "nyname.gif", then fn.substr(0,2) produces the string "ny". The following code would perform the check for matching images—that is, images that correspond to each other. if (faces[firstchoice].substr(0,2)==face[secondchoice].substr(0,2)) . . .
The underlying strategy is that you need to make the names of the files correspond to some pattern and use the appropriate calculation. Changing the names of the files to follow a simple pattern would be more efficient than using a look-up table, but a table may be necessary if you do not have control over the names.
Chapter Summary
What’s Next There will be other examples of arrays in the rest of this book. The next chapter will feature a picture quiz using an array of objects in which each object is a question, with properties and methods.
Review Questions 1. What was the role of the functions choose, check, and shuffle in the program? 2. Compare and contrast the way that the shuffle function is invoked in the initial version of the game and in the final version. 3. What needs to be done to make the Memory game faster—that is, to make the pause shorter? 4. Consider an array: var days = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]
Suppose the following assignment statement was executed: today = "4";
What is the value of days[today]? 5. Consider the days array variable and the today variable described in question 4, after the statement today++;
What is the value of days[today]?
On Your Own 1. Increase the number of cards for Memory to 12 and then to 20. You will need to set up the HTML
and insert the calls to the choose function. After you successfully do this, construct a game in which the player chooses the size and the difficulty of the game. You can make the game more difficult by decreasing the duration of the pause and enforcing a time limit to complete the game. 2. In this chapter’s version of Memory, a pair of cards matched if the image files were identical. The ‘‘In the Real World’’ section described how to make a game with pictures that are similar, but not identical. You can do this by making the first parts of the names of the file correspond: say bird1.gif and bird2.gif, frog1.gif and frog2.gif, and hat1.gif and hat2.gif.
179
This page intentionally left blank
chapter 9
Objects
This chapter will continue the study of objects, a subject touched on briefly in previous chapters. When studying this chapter, you will n
Gain experience using programmer-defined object classes, constructors, and methods
n
Use inheritance to enhance a basic application
n
Learn how to produce a prompt Window using JavaScript
Motivating Example The game featured in this chapter is a quiz in which the player is asked to identify pictures. The game is built incrementally. A timed version moves on to the next image after a set period. The last version supports questions that have follow-up questions. If the player gets the first question correct, he must answer another question, presented in a pop-up window, to get a point. Like the Memory game discussed in Chapter 8, ‘‘Automating a Physical Application,’’ the implementation I describe has a small set of questions. It should be relatively easy to add more questions and scale up the application for real use. Objects will be helpful for doing this. The opening screen of the game is shown in Figure 9.1.
181
182
Chapter 9
n
Objects
Figure 9.1 Opening screen shot of Picture Quiz.
Figure 9.2 shows the quiz after a question that included a follow-up question. The implementation of two types of questions is done using the inheritance feature of object-oriented programming. Figure 9.3 shows the final screen. Notice the score. The quiz show requires the following features: n
A way to represent the game board—namely, the picture that constitutes the question and a set of radio buttons holding the options
n
A way to hold the information for a simple question and a complex question
n
A way to have a time limit
n
A way to keep score
n
A way to display a window that prompts the player with a question and accepts input from the player to be examined by the program
Introduction to Concepts
Figure 9.2 Follow-up question.
Introduction to Concepts Object-oriented programming (OOP) puts code and data together in a way that can make the internal computer programming resemble the real-world objects and situations they are intended to represent. Object-oriented programming has its own vocabulary and often is viewed as an advanced topic with a special mystique. However, objects are anything but abstract, so do not be intimidated by anything you may have read or heard about OOP being difficult. The built-in objects of JavaScript—for example, Date objects—are good examples. The exposition in this chapter will focus on programmer-defined objects. Certain purists would take the position that JavaScript is not object-oriented because applications are not constrained to use only objects. Specifically, global variables and functions are allowed, and it would be difficult or, at the least, awkward to avoid their use. There also is an issue that the objects are defined without formal class definitions. This book takes a relaxed view. It is possible to define
183
184
Chapter 9
n
Objects
Figure 9.3 Screen showing ‘‘ALL DONE.’’
objects, encapsulated properties, and methods using JavaScript. The Document Object Model (DOM) specifies the parts of an HTML document as objects. A form of inheritance is available and can be used to facilitate development.
Classes, Objects, Methods, and Constructors To recap from previous chapters, a class defines the workings of a set of objects. A programmer uses the facilities of the specific language to define the members of the class: the data, termed variables, attributes, or properties, and code, termed methods. Actual objects or object instances of the defined class are created, generally using the same format as declaring variables for the built-in types such as integer.
Introduction to Concepts
Each member variable or method can be designated as a class variable or class method or as an object variable or object method. Each instance has its own set of the object member variables, and the object methods can access and change the values of the member variables. In contrast, there is only one copy of each class variable. You have seen Math.random used in previous chapters. It is a class method that is available for use independently of any object instance. An example of a class variable is Math.PI, which has the additional characteristic of being a constant variable; you cannot change it. One common use of a class variable is to track the number of objects created. This class variable will change in value, but it is essential that it be a single variable. Class methods are procedures that are invoked independently of any object of the class. It is not necessary for there to be any objects declared for the class. Object methods generally refer to object variables. Assuming that a class is not defined as containing only class variables and class methods, using objects involves at least two distinct steps: defining the class and creating objects of that class. In JavaScript, an object is created when the new operator is invoked as part of a declaration (var statement). For the Picture Quiz application, the declaration statements for each question will begin var q1 = new question( The question function is the constructor. Consider the following example for setting up characters in a computer game. I have made up a type of pseudo-code here to emphasize what is happening in terms of objects. In the game, each character has a position, a strength factor, a value if captured, and a bag of treasures, which is initially empty. There are object methods for ascertaining the value, weakening and strengthening the character, and adding to its treasures. There is a method for obtaining the count of characters created. There would be more methods, but this is a start. Note The pseudo-code for the game example sets up game characters that have a bag of treasure. Typically, a bag is an unordered set of things. Languages could use arrays or strings for sets, although the developer must ensure that imposing an order on the set of things does not matter. The language SETL supports sets as part of the language.
The constructor method shown sets the strength and the value at a default value.
185
186
Chapter 9
n
Objects
class character class variable: integer count_of_characters = 0; object variable: position [integer, integer]; object variable: strength integer; object variable: value integer; object variable: treasure_bag set; object method: constructor: strength = 100; value = 10; treasure_bag = empty_set; position[0] = 0; position[1] = 1; count_characters = count_of_ charactersþ1;
class method: how_many(): return (count_of_characters);
Instead of using pseudo-code, here is the JavaScript statement that would both declare the variable my_character to be of type character and create an object of the character class and assign it to my_character: var my_character = new Character();
Generally, the methods and variables of an object are referenced using dot notation, so my_character.weaken(penalty);
invokes the weaken method indicated and causes the strength variable for my_character to decrease by an amount equal to penalty. I have shown many applications of dot notation for referencing and changing parts of an HTML document, such as f.sum.value = f.one.value + f.two.value+f.three.value;
where "sum", "one", "two", and "three" are names of elements in a named "f" as used in Chapter 2, ‘‘Basics,’’ and window.document.coin.src="head.gif";
where "coin" is the name of an element. In any language that supports objects, if there is no constructer method defined, the default constructor simply allocates space for any object variables. It also is possible to have more than one constructer. This is supported using overloading of methods or operators. Note Recall that the þ operator in many languages, including JavaScript, has one meaning when it is used with numbers and another when it is used with strings. This is an example of overloading.
The language processor examines the datatypes of the operands and uses the information, the signature, to determine which operator to invoke. Similarly, methods can be defined with parameters that have different numbers and datatypes. The language processor examines the calling expression to determine which method to invoke. The game character example may have the constructor
187
188
Chapter 9
n
Objects
shown earlier be the default and another constructor for setting specific amounts for the strength and value variables: object method: constructor(s,v): strength = s; value = v; treasure_bag = empty_set; count_characters = count_of_ charactersþ1;
The Picture Quiz application uses programmer-defined objects to represent questions, which facilitates adding new questions.
Inheritance and Overriding Classes can be defined as extensions of other classes. When one class is defined as an extension of the other, the original class is called the superclass and the class defined as an extension is called the subclass. The subclass inherits properties and methods from the superclass; that is, objects of the subclass have all the properties and methods of the superclass. The important thing is that you, the programmer, can have it both ways: you can reuse some of the coding defined for the superclass for the subclass, saving writing and debugging time, and you can add new versions of some methods, replacing the definitions in the superclass. This replacement is termed overriding. Suppose that the game described here had characters that had defenses against being weakened and that moved along at a quicker pace. This characteristic could be represented by Special being defined as a subclass of Character. The definition, using the abstract pseudo-code introduced previously, would be class Special inherits Character object variable: defense float; object method: constructor(d): Character(); defense = d;
The code indicates that a Special character is like a regular character, but it has one extra property—the defense factor—and one extra method. Variables of type float are numbers represented in floating-point notation, also called mathematical notation. These can be numbers with decimal parts, such as 1.5 0.333333333 –104.30279 A Special character is constructed using the signature to pick the appropriate constructor method. Each of these methods calls a constructor defined for Character and then executes one more statement. The weaken method for Special objects is different from the weaken method for regular Character objects. For Character objects, a call of weaken means a simple decrease in strength; for Special objects, the decrease is based on the current value of defense, a property that Character objects that are not special do not possess. Many languages enforce single inheritance, in which a new class can be the subclass of at most one superclass. This restriction still allows for fairly elaborate inheritance structures. Figure 9.4 shows an inheritance tree for a game involving different types of characters. The subclasses of any one superclass do not have to differ from the superclass in the same way. The Flying class may have an added object variable relating to movement and a different move_along method that uses the object variable. Objects in the class may use the weaken method of Character. A characteristic of object-oriented programming is that there will be statements such as piece.weaken(penalty);
in the code instead of (writing again in pseudo-code)
189
190
Chapter 9
n
Objects
Figure 9.4 Inheritance tree example.
if (piece corresponds to a Special) do it this way else do it the other way The logical test to determine what type of piece is built into the object-oriented language facilities of the language. Picture Quiz will use programmer-defined objects for simple questions (see Figure 9.1) and for questions with a follow-up (see Figure 9.2). I first built the application using simple questions, whereby each picture came with a question, a set of options, and the designation of which option was correct. I then decided that some questions would have an additional feature—specifically, another, related question. This follow-up question was fill in the blank, not multiple choice. The object style of coding meant that I could build on what I had done for the simple questions. Formally speaking, specialquestion inherited from question.
Information Hiding Information hiding refers to the feature in object-oriented languages that the exact implementation of objects is contained in the class definition. This includes the structure of the variables and the statements in the code of the methods. Some object-oriented languages have terms, called modifiers, such as private or public, that establish the specific access to each variable and method. For example, it may be forbidden for code outside the class definition to use my_character.value
Picture Quiz
If code outside the class definition needs this information, a method called worth would display it. The implication here is not that matters are kept secret from certain members of the development team but that a discipline is established to use the methods and variables in a prescribed way. This will make it easy to change the specific implementation if the situation demands that this be done. Note The best illustration of the value of this feature is what was called the Y2K problem. Much software was written to use only two digits for the year part of a date. The software remained in operation far longer than the original programmers predicted and needed to be fixed before 2000. The ‘‘problem’’ in the Y2K problem was not that people did not know how to adapt the code. It was that coding involving dates was spread throughout many, many programs, and it was necessary to examine code, some of which was only in executable form, not source form, to find the places to change. If object orientation had been used to confine the handling of dates to one place in each application, changing the date would not have cost large amounts of money. Everyone would have been confident that all computers had been changed.
The benefit of information hiding is ensuring that the details of a part of an implementation are in just one place so that if and when it is necessary to change something, the people doing the task do not have to look everywhere.
Is-a Versus Has-a A class definition can be built on another class, as indicated previously, and a class definition can include variables that are objects. The phrase is-a refers to the first situation, and the phrase has-a refers to the second. The featured example in this chapter involves two types of questions. Using English, not coding, a special question is a question. A special question has a property that is its follow-up question. Each question, special or not, has a property that is a picture. Often, especially in more complex applications, it is beneficial to think through all the is-a and has-a relationships.
Picture Quiz This section reviews the use of objects in prior chapters before tackling the implementation of Picture Quiz.
191
192
Chapter 9
n
Objects
Review of Previous Examples Object orientation is a fundamental topic, so it was expedient to include some uses before this chapter. You have seen uses of class methods of the Math class. Math.floor()
for example, is a class method, independent of any object, that produces the greatest integer not larger than the parameter to the call. In contrast, indexOf is a method applicable to individual strings. In the definition of the money function in Chapter 3, ‘‘Extending the Basic Language,’’ dp = totals.indexOf(".");
is used to determine the location in the particular string totals where the decimal point occurs. The Document Object Model for HTML is what defines the components of an HTML document for JavaScript. For example, if there is a named f containing an tag with the name attribute set to "sum", then document.f.sum.value = . . .
is the way to set the value attribute of this particular . In Chapter 7, ‘‘Application State,’’ you read about a simplified implementation in Java of the Craps dice game. This application had a class called Game and a testing class called Crapstest that created a Game object and invoked methods to play out a game until it was won or lost.
Plan of Attack for Picture Quiz The first step in planning Picture Quiz was to decide on what information represented a question. I decided that a question would consist of an image, a question about the image, possible options, and a designation for the correct option. This meant that I did not want it to be just, ‘‘What is this picture?’’ or ‘‘Identify this picture,’’ but something customized to the image. I also chose multiple choice instead of fill in the blank. As you will see, my decision to add special questions was a decision to have multiple choice followed by fill-in-theblank questions. Each question would be shown to the player when his turn came. There would need to be a way to accept and check answers. My script would keep score and display the score to the player.
Picture Quiz
I developed this application incrementally in four stages, each one building on the last. 1. In what I call the base game, the questions are presented in turn and, after the last one, if the player clicks on Check, the first question is shown again. 2. I changed the application to go through the questions just one time. At the conclusion, the phrase ‘‘ALL DONE’’ appears. The player cannot restart by clicking on Check. 3. I then added timing to the game. Each question is allotted a set amount of time. If the player does not answer, the next question is shown. The game also ends with ‘‘ALL DONE.’’ 4. Last, I added the feature of special questions. A special question has a followup question asked by means of a prompt window. I changed the code to remove the time pressure for special questions. What I have just laid out constitutes the logical design of the application. In the next section, I describe the implementation, or the physical design.
Use of Concepts in Implementation In Picture Quiz, each question is constructed as an object. The object contains (encapsulates) as properties the name of the image file, the text of the question, the text of four options, and the designation of the correct answer. The object also contains the name of a function that checks the answer and the name of a function that displays the question. The definition of the question function that acts as the constructor for each object is function question (pic,ques,opta, optb, optc, optd, right) { this.questext = ques; this.picture = pic; this.aa = opta; this.ab = optb; this.ac = optc; this.ad = optd; this.rightans = right; this.checkit = check; this.loadq = loadquestion; }
193
194
Chapter 9
n
Objects
The term this is used to set the properties to the values indicated—namely, the ones given as parameters of the function. All question objects will have checkit set to check and loadq set to loadquestion. These two functions, check and loadquestion, are defined elsewhere in the document. A use of this function to build a question is var q1 = new question ( "three.jpg", "What are we celebrating?", "a birthday", "Daniel’s thesis defense", "primary", "Olympics", "b" );
The new keyword signals that JavaScript should use the question function as a constructor for a new object. With this structure in place, I use an array to hold the questions. I decided that three questions were enough to test the application. (All the code will be shown in the next section, ‘‘Basic Quiz.’’) The statement to set the array is var questions = [q1, q2, q3];
A variable named quesnumber is used for indexing this array, and the statement curq= questions[quesnumber];
is used to hold the current question. Displaying the next question and checking the player’s answer required two functions. In each case, one regular function calls the question method. For displaying the next question, I wrote function loadnext() { quesnumber++; if (quesnumber==questions.length) { return false; } else { curq= questions[quesnumber]; curq.loadq(); } }
Picture Quiz
The curq.loadq(); statement invokes the loading method for this question. Similarly, for checking the answer function checkanswer() { var i; for (i=0;i<document.q.qp.length;i++) { if (document.q.qp[i].checked) { player = document.q.qp[i].value; } } if (curq.checkit(player)) { document.q.score.value = 1+parseInt(document.q.score.value);} loadnext(); return false; }
The condition (curq.checkit(player)) calls the checkit method associated with this question. The special questions will have a different checkit method. Here is the outline for the quiz games: html
element
head
element
title script
element
variables, including one for each question object and an array to hold all the questions function
definitions, including
the question constructor: question functions for checking answers functions for displaying the next question body
element
img
tag to hold the picture
form
195
196
Chapter 9
n
input
Objects
element for question text
text plus input element of type radio for each option input
element of type submit labeled CHECK
input
element of type text to hold the score
Now I will describe each of the four versions. Basic Quiz
The code for the basic quiz is given in the table. JavaScript
Explanation
Quiz show: array of question objects
Start the HTML document.
<script>
Start the <script> element. Declare the variable to hold the player response. Declare and initialize the variable holding the number of the question. Define the question as a constructor.
function loadquestion() { Define the function for displaying a question. document.pic.src = this.picture; document.q.qtext.value = this.questext; document.q.ansa.value = this.aa; document.q.ansb.value = this.ab; document.q.ansc.value = this.ac; document.q.ansd.value = this.ad; }
Picture Quiz
JavaScript
Explanation
var q1 = new question ( "three.jpg", "What are we celebrating?", "a birthday", "Daniel’s thesis defense", "primary", "Olympics", "b" );
Define a question.
var q2 = new question ( "emcoreydog.jpg", "Who are these people?", "Esther, Corey, and dog", "Leanne’s family", "Jeanine’s neighbors", "Aviva’s friends", "a" );
Define a question.
var q3 = new question ( "kiheisunset.jpg", "What state is this?", "New York", "California", "Florida", "Hawaii", "d" );
Define a question.
var questions = [q1,q2,q3];
Define the array holding all the questions. Start the checkanswer function. Run through the radio button options and determine which one the player clicked on. The variable player will hold the ‘‘a,’’ ‘‘b,’’ ‘‘c,’’ or ‘‘d.’’
function checkanswer() { var i; for (i=0;i<document.q. qp.length;i++) { if (document.q.qp[i].checked) { player = document.q .qp[i].value; } } if (curq.checkit(player)) {
Use player as the parameter in a call to the checkit method of the current question. This is the condition in an if statement. If the condition was true (the player guessed correctly), increment the score. (Continued )
197
198
Chapter 9
n
Objects
JavaScript
Explanation
loadnext(); return false; }
Load the next question. Return false to prevent a refresh. Close the function. Start the loadnext function. Increment the variable used to index the questions array. If it is at the end, end the function by returning false.
function loadnext() { quesnumber++; if (quesnumber==questions .length) { return false; } else { curq= questions[quesnumber]; curq.loadq(); } }
If there still are more questions, set curq and then call its loadq method to load the next question. Close the else clause. Close the function.
Close the elements. Open the element. Set up loadnext() to be called when the document is loaded or refreshed. Define the element.
Define and name a form element. Set up the event handler for the Submit button. Set up the place to hold the question text, with no border.
Set up the radio buttons.
Set up the Submit button, with a label of "CHECK".
Picture Quiz
JavaScript
Explanation
Set up the place to hold the score.
Close the html elements.
Open TextPad or an equivalent program and copy the code in column 1. Replace my questions and answers with your own. Each question will need an image file, which must be in the same folder as the HTML file. Use your own digital images or download images from the Web. Test it by opening in a browser. Ending the Quiz
Cycling through the questions did not appeal to me, so I decided I wanted a way to end the game. I added a variable to be true if the game was still going on and false if it had ended. So, in the <script> element, outside of any function, I added var gameon = true;
Then I modified the loadnext() function by putting the whole body of the function within an if-true clause based on the gameon and adding two lines to the if-true clause that checks on the question number. function loadnext() { if (gameon) { quesnumber++; if (quesnumber==questions.length) { document.q.qtext.value = "ALL DONE"; gameon = false; return false; } else { curq= questions[quesnumber]; curq.loadq(); return false; } } }
199
200
Chapter 9
n
Objects
I did something similar for checkanswer. The additions are in bold. function checkanswer() { if (gameon) { var i; for (i=0;i<document.q.qp.length;i++) { if (document.q.qp[i].checked) { player = document.q.qp[i].value; } } if (curq.checkit(player)) { document.q.score.value = 1+parseInt(document.q.score.value); } loadnext(); } return false; }
At this point, I decided that my dividing the work between the loadnext function and the loadquestion function that was designated as the loadq method was the correct thing to do. The method has the question-dependent part and is kept hidden, or at least separate, from the logic concerning going from question to question or ending the game. The same applies to the division of work for checkanswer and either of the methods designated as checkit. Before making this change, ensure that the basic game is saved under its own name, say quizbase.html. Then save the file under a new name and make the change. This ensures that you can go back to the previous version. Adding Timing
The next step was to make the game more challenging by adding time constraints. Timing was added in Chapter 4, ‘‘Events and Event Handling and the Graphical User Interface,’’ for the Find Daniel game. The same JavaScript built-in functions, setInterval and clearInterval, are used for this game. A variable to hold the identifier returned is declared. var tid;
Picture Quiz
The loadnext() function was modified again: function loadnext() { if (gameon) { clearInterval(tid); quesnumber++; if (quesnumber==questions.length) { document.q.qtext.value = "ALL DONE"; gameon = false; return false; } else { curq= questions[quesnumber]; curq.loadq(); tid = setInterval("loadnext()",5000); return false; } } }
The added statements are shown in bold. The effect is to invoke loadnext(), the function that moves on to the next question, after 5 seconds. If the player answers a question before the time elapses, the checkanswer function invokes loadnext(), which calls first on clearInterval, and then setInterval again. This is analogous to waking up before the alarm rings and resetting it to allow another hour of sleep. As before, make sure the prior working version is saved, and make these changes. Test the program. You may want to change the parameter 5000 in the call of setInterval. Remember that the unit is milliseconds, so 5000 is the equivalent of 5 seconds. Adding Facility for Special Questions
The last step is to add special questions by building on the work I have done for standard questions. My thinking was to add a follow-up question to be checked against a follow-up answer. The question would be displayed using the JavaScript prompt function. I would use a JavaScript facility for inheritance so I could reuse what I had already scripted for standard questions. I would need to define
201
202
Chapter 9
n
Objects
additional properties and override the standard checkit method because checking for the special question would be different. Note There is more than one way to implement inheritance in JavaScript. I chose to use the functional method. Another method uses a feature of JavaScript called prototype. Neither approach sets up something like the class in Java, so purists may argue that this is not object oriented. I won’t disagree. This is an introduction to the concepts.
The following code defines a function called specialquestion that can be used to set up questions using the code already written and with the additional properties and the changed method. function specialquestion (pic,ques,opta, optb, optc, optd, right, followupq, followupa) { this.base = question; this.base(pic,ques,opta,optb,optc,optd,right); this.fq = followupq; this.fa = followupa; this.checkit = checkwfollowup; }
Note again the use of the keyword this. The first two statements in the function invoke question to construct a standard question. The next two lines set up the added properties. These are the contents of the follow-up question and the answer to the follow-up question. The last statement sets the value of checkit. Checking a special question is different from checking a standard question, so the checkit method must be overridden to point to checkwfollowup instead of check. Here is the definition of checkwfollowup: function checkwfollowup (player) { var ea; if (this.rightans==player) { clearInterval(tid); //remove time pressure ea = prompt(this.fq); if (ea==this.fa){ return true; } } return false; }
Picture Quiz
is invoked in the same way that check is invoked for standard questions. That is, the function checkanswer has the code curq.checkit(player). If the question was created using question as the constructor, then check is called. If the question was created using specialquestion, then checkwfollowup is called.
checkwfollowup
I added clearInterval(tid); because I could not manage to answer the original question and then type in the answer to the prompted question quickly enough. This convinced me that the right approach would be to remove all time pressure. Please note that an extraneous call to clearInterval, which would occur in the next loadnext function, is not a problem. A special question is set up by invoking specialquestion in a var statement following the term new. An example is var q3 = new specialquestion ( "kiheisunset.jpg", "What state is this?", "New York", "California", "Florida", "Hawaii", "d", "What town?", "Kihei" );
Operationally, I added to the sunset question. See Figure 9.2 for a screen shot of how the follow-up question is displayed. I could have added a completely different question. In fact, I did add another standard question to be sure that the application would handle standard questions before and after special questions. This version of my game had the line var questions = [q1,q2,q3, q4];
Make sure the previous version is saved. Invent and then code special questions, and test your application. There is one more enhancement for Picture Quiz. You can extract the code for defining the questions along with the definition of the questions array and put it into an external JavaScript file. In my example, I saved the following code (after cutting it from the rest of the document) with the name quizquestions.js.
203
204
Chapter 9
n
Objects
var q1 = new question ( "three.jpgthree. jpg", "emcoreydog.jpg", "Who are these people?", "Esther, Corey, and dog", "Leanne’s family", "Jeanine’s neighbors", "Aviva’s friends", "a" ); var q2 = new question ( "What are we celebrating?", "a birthday", "Daniel’s thesis defense", "primary", "Olympics", "b" );
var q3 = new specialquestion ( "kiheisunset.jpg", "What state is this?", "New York", "California", "Florida", "Hawaii", "d", "What town?", "Kihei" ); var q4 = new question ( "aviva.jpg", "Who is this?", "Esther", "Jeanine", "Aviva", "Sally", "c" ); var questions = [q1,q2,q3, q4];
Chapter Summary
In the now smaller HTML document, I add the following after the tag: <script src="quizquestions.js" language="javascript" type="text/javascript">
Save this program with a new name, perhaps quizplusX.html, and then test it. It should work as the other one did. If you use the browser view source option, you will not see the questions, which means that you cannot see the answers! However, a sneaky player can read the name of the external JavaScript file and go to it directly. To keep the answers secret, you need to learn about server-side programming using a language such as PHP. I still recommend using an external file; it makes the program much more robust, because you can change or add to the quizquestions.js file as you create more questions.
What Can Go Wrong Another way to build an application such as this one is to use parallel structures. The questions array would be an array of arrays, with each inner array holding the information in a set order. This means the programmer needs to remember that questions[cq][0] holds the image file name, questions[cq][1] holds the question text, and so on. The object approach avoids these problems. The coding used here does have if statements within for statements and other potential nesting problems. The timing issue alluded to in the previous section could be called something that went wrong. It, along with the refinements from the base game to the game that ends to the timed game to the game with special and standard questions, is natural in any development effort.
Chapter Summary This chapter showed different versions of a guessing game involving pictures. The implementation was done using objects. The game used several of the concepts introduced in the text.
What You Have Learned In this chapter, you n
Gained experience setting up using constructors and using programmerdefined objects
205
206
Chapter 9
n
Objects
n
Observed an application of inheritance
n
Gained experience working incrementally to build up an application
n
Added to your experience using various features of JavaScript, including images, radio buttons, and timing
n
Learned about a new feature of JavaScript: the prompt function
n
Used an external JavaScript file to make your application more robust
Having simple questions and special questions was a natural use of objects and inheritance. Deciding on what classes need to be defined for a particular application can be a challenge. In this case, question and special question seemed pretty obvious choices. I encapsulated all the data involved with a question as the properties and the two actions to take on questions—loading and checking—as methods. A special question was similar to a regular question, but it required more data and a more complex checking method.
In the Real World Preparing projects for a course or while learning a subject on your own with a book generally means that you start ‘‘from scratch,’’ concentrating on the logic. You may need to identify and use built-in facilities of the language, which may be its own challenge, but for the most part, you are on your own. When working in the industry, most of the work involves modifying or building on existing programs. You have the burden and the luxury of not doing everything by yourself. The burden comes about because you need to learn what already exists. Objectoriented programming is promoted as a way to support the efficient use of software. If a new requirement occurs, the theory is that object orientation makes it easy or easier to change only what needs to be changed and easy to build on working programs. The claims for object orientation may not always be justified, but it is the current standard. A real quiz may involve many questions and perhaps even different sets of questions. One issue is how those questions are to be stored. Databases or eXtended Markup Language (XML) are possible technologies to use. Those topics are beyond the scope of this text, but keep them in mind.
Chapter Summary
What’s Next The next chapter introduces the topic of computed animation: moving objects around on the screen in a way to suggest motion. It will be followed by a chapter on ballistics simulation and then one on discrete simulation. These are important applications of programming that build on the topics covered so far.
Review Questions 1. What were the methods of the question object? 2. What method did specialquestion inherit from question? Which was overridden? 3. What is the significance of this in the statement in the question function this.picture = pic;
4. Trick question: Why does the check function not have open and closing parentheses in the statement in the question function this.checkit = check;
5. True or false: The + operator is overloaded in JavaScript. Explain.
On Your Own 1. Build your own quiz show. Then devise a new scoring system that does not set a fixed time limit but does keep track of time, displaying the elapsed time in seconds on the screen. 2. Modify the quiz show to assign a different point value to each question. You will need to add another property and add a statement such as this.value = qv to the question constructor function.
207
This page intentionally left blank
chapter 10
Computed Animation
This chapter will introduce the topics of simulation and animation, which are common computer programming applications. After studying this chapter, you will n
Understand what is meant by discrete simulation
n
Appreciate the differences between discrete simulation and continuous real-life
n
Have practiced building a virtual world for a 2-D simulation of a bouncing ball enclosed in a box
n
Know how to use calculations and the HTML styles construct to position objects on the screen
n
Have practiced using timed events and repositioning to produce animation
n
Have learned how to use an object constructor function to check for the existence of a method and used this to handle differences among browsers
Motivating Example The application featured in this chapter is not really a game, although you can build on it to create one. The opening screen shot is shown in Figure 10.1.
209
210
Chapter 10
n
Computed Animation
Figure 10.1 Opening screen for Bouncing Ball with walls.
If the player clicks on Start, the ball will begin to move. When the ball hits a wall (or, more correctly, when it appears to hit a wall), it bounces. When the player clicks on Stop, the ball will stop, and when it resumes, it will go in the opposite direction. I implemented this application in stages. The first stage did not have walls. It is shown in Figure 10.2. It is important to realize that no collisions actually take place; everything is based on calculations. The critical features required by this application include n
A way to position graphical elements at different places on the screen
Introduction to Concepts
Figure 10.2 Opening screen for Bouncing Ball with no visible walls. n
A facility to do something—namely, reposition graphical elements—at short intervals of time
n
Determining if a virtual collision has taken place
n
Calculating 2-D movement
Introduction to Concepts Real life is continuous, meaning connected, uninterrupted, and without a break in time or space. In contrast, most simulations portray what is being simulated at discrete intervals, meaning not connected, distinct, or separate. That is, the simulation is a representation of what is being simulated at one point in time and then at another point in time a little later and then another, for a time a little after that, and so on. This can be adequate or not, depending on the situation.
211
212
Chapter 10
n
Computed Animation
If you have examined a movie reel, you know that a movie consists of a sequence of still pictures that are projected at a fast enough pace that the human eye does not see the individual pictures but, instead, perceives movement. Animation is produced in the same way. In cel or frame animation, a sequence of still pictures is created as part of the production process. At runtime, the pictures are displayed to the viewer. It may be that the individual pictures are produced using computer programming, so this could be called computer animation. However, the animation featured in this chapter and the next is different. The program changes what appears on the screen as the program runs. The scene is created dynamically by positioning and repositioning the objects using calculations of what the positions would be based on conditions. The Bouncing Ball application will show a ball bouncing against the walls in a 2-D box. It works by repositioning the ball by adjusting its horizontal and vertical properties. The application includes calculations to check whether the ball has hit any of the four walls, that is, if the position of the ball and the position of the walls overlap.
3-D Modeling The many games that feature 3-D require complex programming, outlined here briefly. The entities (characters, buildings, and so on) are represented by 3-D models: generally collections of polyhedra, flat-sided objects approximating more complex shapes. Surfaces may be represented by mathematical equations, sometimes involving pseudo-random calculations to simulate nature. Often 2-D patterns and images are wrapped around 3-D surfaces. Action in the game means movement of the models. A simple act of a character walking corresponds to a complex repositioning of the geometric shapes making up the character, along with calculations such as collision detection. The program must generate the display on the flat screen over and over again to trick the human eye into seeing live action. The tasks included for producing the display include these: n
Determining the projection plane based on a position for the eye or camera and a focal point. First-person-shooter games use the eye position of the character representing the player.
n
Clipping the projection based on the dimensions of the screen.
Introduction to Concepts
Figure 10.3 Wire-frame versus hidden line.
n
Solving the hidden linesurface problem—material is covered up (occluded) by other material. (Figure 10.3 shows what is called a wire-frame version of an object and the same object with the portions of the edges that would be invisible if the object was solid. If the surfaces were defined to hold textures and the display was rendered with parts of surfaces hidden and the rest shown appropriately in terms of lighting, this is called the hidden surface problem.)
n
Calculating the effects of lighting based on position and types of light sources along with models specifying the reflectivity of all the surfaces.
Software exists to support these tasks, but it is still an area of active research for games, movies, and scientific visualization.
2-D Movement The application featured in this chapter is a ball that is bouncing within a box made up of four walls. The virtual world is 2-D. The movement of the ball is simulated by repositioning the computer object representing the ball periodically, that is, at set time intervals. The positioning is done in terms of horizontal and vertical coordinates. The position is based on the equation of motion from the study of physics: new_position = old_position þ velocity*time The time in this equation refers to the time interval or time elapsed. The term velocity conveys speed and direction. The equation is a vector equation, meaning that new_position, old_position, and velocity are vectors.
213
214
Chapter 10
n
Computed Animation
Note Before getting into the vector calculations, consider the following examples from everyday life in which I calculate the distance from home. If at 10 a.m., you are 20 miles from home, traveling at 50 miles/hour, then at 11 a.m., you will be 70 miles from home. At 11:30 a.m., you will have traveled 25 miles farther, to be 95 miles from home. Note that the phrase ‘‘from home’’ sets this up as a 1-D problem. A 2-D problem would involve how far east or west and how far north and south you are from your home.
Vectors are added by putting them together head to tail, as illustrated in Figure 10.4. When you are programming, you generally add vectors using the component parts. For example, in the 2-D situation, each new position is establishing using two equations: Positionx = Oldx þ Velocityx * Time Positiony = Oldy þ Velocityy * Time The velocityx is the x component of the velocity. Figure 10.5 shows the velocity vector as the sum of the x and y components. Resolution is the operation of calculating the components, done using the trigonometric functions.
Figure 10.4 Vector addition.
Figure 10.5 Resolution of vector.
Introduction to Concepts
Some applications start with the velocity and require calculation of the x and y components, and others start with the components directly. The cannonball application featured in the next chapter assumes a velocity given as the velocity out of the cannon. The program computes the components. In the Bouncing Ball application, the horizontal and vertical components are assumed to be values set in the program. See the ‘‘On Your Own’’ section for a challenge. Note Coordinates for computer displays typically have the horizontal coordinate increasing from left to right and the vertical coordinate increasing moving down the screen. As has been indicated previously, this can be disconcerting if you remember studying analytical geometry in school. For computer screens, moving up corresponds to the vertical coordinate decreasing in value.
Information Hiding for Browser-Specific Coding What I have discussed so far in this section concerns the calculation of position of the ball. However, how does my code actually move images in an HTML document? The answer is not obvious and requires certain trickery. Although the specifics here apply just to HTML and JavaScript, there are general principles that are language independent. It turns out that the <style> element in HTML can be used to define the position of elements of HTML documents in terms of left and top properties, and these properties can be modified. The type of element used in this way is a . The problem is that this feature is not implemented identically by the different browsers (Mozilla, Internet Explorer, Safari, and so on). The first general technique is to restrict the browser-specific part to just one place—in this case, one function—in my application. This is the information hiding feature of object-oriented programming. The coding relating to what can be done in different browsers is in a function used to construct one object. The second general technique is that the code in this function uses a feature that provides a way to test whether something is available, without actually invoking it or in any way causing an error. The details will be explained and demonstrated in the ‘‘Plan of Attack for Bouncing Ball’’ and the ‘‘Use of Concepts in Implementation’’ sections.
Event Handling The event that is important in this application is the passage of a set amount of time. The use of timed events has been discussed in previous chapters. What is required here is an event that recurs at regular time intervals so that the position of the ball can be calculated. The calculation is the application of the horizontal
215
216
Chapter 10
n
Computed Animation
and vertical equations. Experimentation with the length of the duration will make the ball appear to move continuously and smoothly.
Collisions The simulation of the ball in a box may seem straightforward: keep moving the ball until it hits one of the walls and, if and when it does, reverse direction. Of course, the ball does not hit anything. Instead, the code makes a calculation based on the position of the ball and the position of the walls. There still is a problem. Here is where it becomes significant that this is a discrete simulation of a continuous process. The position of the ball is checked at discrete intervals. Consider the situation illustrated in Figure 10.6. The ball is inside the box, in front of the right wall at the time equals T1 and then beyond the right wall at time equals T2. You can lessen these effects by continually decreasing the time duration and making the walls thicker, but the problem never goes away entirely. Think of it as checking up on the ball’s whereabouts by making an instantaneous check every so often. You miss what happens between checks. When the ball hits a wall, the direction of movement will change depending on which wall was hit. If the ball is heading downward and to the right, hitting the wall on the right will change the travel to moving downward but now to the left (see Figure 10.7). This turns out to be easy to program. You will simply change the sign of the appropriate variable. So if hitting the left or right wall, a variable xa that holds the change in horizontal movement will be modified: xa = -xa;
Figure 10.6 Ball in front of and beyond wall.
Introduction to Concepts
Figure 10.7 Direction of travel after hitting wall.
When hitting the top or bottom wall, the vertical variable, a variable ya that holds the change in vertical movement, will be modified: ya = -ya;
It may take a moment to realize that if a variable xa holds a positive value, say 10, then –xa becomes –10. If the variable held a negative value, say –10, then –xa would be 10. This means that the code for hitting the left wall and the code for hitting the right wall is the same. Note In nature, balls hitting surfaces lose energy and, therefore, velocity. If you drop a ball, it will not bounce up as high as the position from which you dropped it. The coefficient of restitution, dependent on the materials of the ball and the wall, indicates how much the velocity changes. Rubber balls bounce higher than bowling balls! Tennis players have a keen sense of bouncing on different surfaces.
The Bouncing Ball application featured here assumes an ideal situation in which the ball rebounds completely. The checks done in this application for hitting a wall are the mathematical equivalent of asking, ‘‘Has the ball gone past a particular point?’’ If the wall is the right wall at 400 pixels from the left, and currentx holds the horizontal position, the condition to be tested is (currentx>400). If the wall is the left wall, the
217
218
Chapter 10
n
Computed Animation
condition is (currentx section to be described in the next section and a <script> section. The outline is html
element
head
element
style
element
style for the ball div script
element
variables: tid, xa, ya, currentx, currenty, ballobj functions: start, stop, move, getobj body
element
div
containing img
a
element containing the word ‘‘Start’’
a
element containing the word ‘‘Stop’’
The final version of Bouncing Ball includes four walls. In the implementation, I added entries in the <style> element for the walls and elements in the body. I made no other changes.
Use of Concepts in Implementation I now need to explain in detail how to make things move in HTML. A <style> element in the section of an document may contain many different ways of specifying position and formatting information for any of the built-in elements in HTML. What I use for this application are styles for specifying position on the screen for elements. The element is a way for anyone to specify parts of an HTML document. The coding is <style type="text/css"> #ball {position: absolute; top: 100px; left: 200px; } <script>
219
220
Chapter 10
n
Computed Animation
The #ball refers to whatever in the has been given an id attribute of "ball". For this application, it is a defined as follows:
The style specification, the information between the brackets following #ball, indicates that the position information will be given in absolute terms—that is, in terms of the screen, not any containing element. The specifics are that it must be 100 pixels from the top of the screen and 200 pixels from the left. Note Styles for HTML documents constitute a substantial subject. The primary use for styles is to separate formatting from content and not for the dynamic positioning of graphics demonstrated here. You can consult sources online and in books and articles to find out how to use styles.
The application has six variables. JavaScript
Explanation
var ballobj;
Set up the variable to hold the object representing the ball. Set up the variable to hold the timing identifier. Set up and initialize the amount of horizontal change. Set up and initialize the amount of vertical change. Set up and initialize the current horizontal position. It must match the left attribute in the style. Set up and initialize the current vertical position. It must match the top attribute in the style.
var tid; var xa = 20; var ya = 30; var currentx = 100; var currenty = 200
It is necessary to keep track of the current position because I can set the style top and left properties, but I cannot extract those values. The next challenge is to change the top and the left of the ball object during the application. This, in turn, requires the code to get access to the element that corresponds to . This is accomplished by defining a function to serve as a constructor. I call the function getobj. It contains three if statements. Each if statement essentially asks the following: is a particular method available in this browser? If so, the code invokes the method. Asking if the method is available is done by naming it in a condition.
Bouncing Ball
JavaScript
Explanation
function getObj(name) {
Start function. The parameter will be name. The call will be
if (document.getElementById) {
var ballobj = new getObj("ball");
Check whether code can use document.getElementById. Use document.getElementById to set up the obj property and the style property.
Check whether code can use document.all. Use document.all to set up the obj property and the style property.
Check whether the code can use document.layers. Use document.layers to set up the obj property and the style property.
Close the function.
There are three functions to explain. The start function arranges for the ball to move by setting up the ballobj and calling setInterval. The code mentioned in the setInterval call is a call to the move function. The start function does not move the ball. Instead, it arranges for the movement to happen every interval of time. function start() { ballobj = new getObj("ball"); tid = setInterval("move(xa,ya);",100); }
The stop function is simpler; it stops the timed action. Also, just because I decided to do it this way, the change variables, xa and ya, are reversed.
221
222
Chapter 10
n
Computed Animation
function stop() { clearInterval(tid); xa = -xa; ya = -ya; }
The move function updates the current position and then assigns the values to the style attributes of the ballobj. Then the code tests whether the ball has hit the walls by comparing the numbers set up to demark each virtual wall. The code is function move(dx, dy) { currentx += dx; currenty += dy; ballobj.style.top = currenty; ballobj.style.left = currentx; if (currentx >= 400) { xa = -xa; } if (currentx =400) { ya = -ya; } if (currenty element and elements inside elements in the . Here is the complete application, with the addition for visible walls shown in bold. Bouncing ball <style type="text/css"> #ball {position: absolute; top: 100px; left: 200px; } #leftwall {position: absolute; top: 10px; left: 0px;} #rightwall {position: absolute; top: 10px; left: 440px;} #topwall {position: absolute; top: 0px; left: 0px;} #botwall {position: absolute; top: 450px; left: 0px;} <script> function getObj(name) { if (document.getElementById) { this.obj = document.getElementById(name); this.style = document.getElementById(name).style; } else if (document.all) { this.obj = document.all[name]; this.style = document.all[name].style; } else if (document.layers) { this.obj = document.layers[name]; this.style = document.layers[name]; } } var ballobj; var tid; var xa = 20; var ya = 30; var currentx = 100; var currenty = 200; function start() { ballobj = new getObj("ball");
223
224
Chapter 10
n
Computed Animation
tid = setInterval("move(xa,ya);",100); } function stop() { clearInterval(tid); xa = -xa; ya = -ya; } function move(dx, dy) { currentx += dx; currenty += dy; ballobj.style.top = currenty; ballobj.style.left = currentx; if (currentx >= 400) { xa = -xa; } if (currentx =400) { ya = -ya; } if (currenty element. You can copy this code and test it. You will need to create three images—ball, horizontal wall, and vertical wall—and make sure that the HTML file, the ball image file, the image file for the vertical wall, and the image file for the horizontal wall are in the same folder on your computer.
What Can Go Wrong The usual coding problems can occur: unmatched brackets, quotation marks, and HTML tags. You may mix up the vertical and the horizontal walls. You can experiment with the variables for the movement (xa and ya) and the duration of the timing interval (100) to change the appearance of motion.
Chapter Summary This chapter focused on computed animation, adding the features necessary to display a 2-D ball moving in an enclosed box. A graphical object, the ball, was moved incrementally across the screen, fooling our eyes into perceiving motion. The implementation was done using computed animation, not cel animation (a sequence of preconstructed pictures). The tests for colliding with the walls are accomplished using simple comparisons of the current horizontal and vertical coordinates of the ball object with the known positions of the walls.
What You Have Learned In this chapter, you learned n
How to reposition parts of an HTML document with elements and <style> elements
n
How to produce animation by repositioning images as a result of a function invoked by the setInterval function
225
226
Chapter 10
n
Computed Animation
n
How to simulate collisions—that is, calculate when objects will collide and take actions
n
How to produce an application that will work with different browsers by defining an object
In the Real World This is a basic simulation/animation application. Simulations help in understanding and testing systems. Industrial organizations simulate systems before deploying them. Animations can be considered simulations rendered in graphical form. Of course, animations also are entertaining and often are the basis for games.
What’s Next Chapter 11, ‘‘Ballistics Simulation,’’ uses the same programming techniques in HTML and JavaScript to simulate the firing of a cannonball out of a cannon that either hits a target or falls to the ground. The collision calculation for hitting a target will be more complex. Chapter 12, ‘‘Discrete State Simulation,’’ describes discrete simulation of a different kind, finite-state simulation. The behavior of a dog is what’s being simulated.
Review Questions 1. Consider the workings of a digital clock and an old-fashioned face clock with hands, and compare this to discrete versus continuous simulation. 2. Why does ‘‘hitting a wall’’ change only one of the two direction variables? 3. Moving the ball object horizontally toward the right involves changing what attribute? 4. Moving the ball higher up on the screen involves changing what attribute? 5. You read a book at the rate of 2 pages/minute. How many pages can you read in 30 minutes?
Chapter Summary
On Your Own 1. Enhance the Bouncing Ball application by giving the user a chance to specify the horizontal and vertical speed of the ball. You will need to set up a with two elements. You will define a function named setvelocities and set the onSubmit attribute in to be "return setvelocities();". Last, in the function setvelocities, you will use the values in the elements to set xa and ya. 2. Enhance the Bouncing Ball application by making the ball change appearance after hitting a wall. You can have the src attribute cycle between two or more names of image files.
227
This page intentionally left blank
chapter 11
Ballistics Simulation
This chapter builds on the previous one to describe ballistics simulation— namely, the simulation of the firing of a projectile into the air. When studying this chapter, you will n
Learn the basic mathematics and physics of projectile motion, including simulation of the effects of gravity
n
Practice building an application involving collision checking
n
Discover the benefits of dividing a project into steps
Motivating Example The Cannonball application featured in this chapter can serve as a basis for a shooting game. The initial screen is shown in Figure 11.1. The player clicks on the Fire Cannon link. The cannonball travels in an arc and either hits the ground or the target. The player can change the angle of the cannon by entering a new amount in the field next to the label Angle, initially set at 45, or can change the speed out of the mouth of the cannon by changing the label Velocity Out of Cannon, initially set to 20. If the ball hits the target, the image changes. Figure 11.2 shows the screen after a successful firing of the cannon.
229
230
Chapter 11
n
Ballistics Simulation
Figure 11.1 Opening screen of Cannonball.
Figure 11.2 Screen after the cannonball hits the target and is damaged.
Introduction to Concepts
The critical features required by this application include n
Repositioning objects on the screen and producing animation by repositioning at certain intervals
n
Calculating vertical and horizontal components of velocity
n
Calculating the effects of simulated gravity to produce the characteristic arc of projectile motion
n
Determining collisions
Tip This application requires some basic mathematics, but don’t be frightened. All the equations are supplied, and you will not need to consult any tables or perform any calculations. What you need to do is understand the use of built-in Math methods. Seeing the mathematical functions in use should help your understanding.
Introduction to Concepts When someone throws a ball, shoots an arrow, or fires a missile, the projectile travels in an arc in the shape of a parabola. This is because the force of gravity acts on the object. Ballistics is the study of projectile motion. The previous chapter noted that the requirements of most computer systems made it necessary to separate the horizontal and vertical components of velocity. Simulation of projectile motion provides another reason for this separation. Gravity acts to change the vertical component, not the horizontal one. The horizontal component can be changed by forces such as the drag from the air, but I assume a more idealized situation. The horizontal velocity remains constant, and the vertical velocity changes. The simulation is to move (animate) the cannonball through the air using calculations based on the initial velocity out of the cannon, the resolution of that vector into horizontal and vertical components, and the effects of gravity to change the vertical vector. In simulations involving virtual worlds, the program often must check whether the position of one object overlays the position of another. A generic term for these checks is collision detection. The checks determine if the virtual objects collide. Checks are made to see if the cannonball hits the ground or hits a target. These checks are set up to be done throughout the flight using different programming techniques.
231
232
Chapter 11
n
Ballistics Simulation
The simulation is enhanced by allowing the player to change the angle of the cannon and the velocity out of the cannon. For dramatic effect, the simulation changes the picture of the target when a hit is detected. The simulation involves various coding techniques, some of which are specific to HTML and JavaScript, and others that are applicable to other programming languages. One strategy for scripting and programming projects is to divide the implementation into steps. This will be demonstrated by dividing the implementation of the Cannonball application into multiple steps. This is an important principle to keep in mind for all projects.
Simulation of Projectile Motion In the Bouncing Ball simulation, the ball is repositioned horizontally and vertically over and over again to produce the look of animation. For the Cannonball simulation, it is necessary to determine the horizontal and vertical components of the velocity. The initial information is the speed of the cannonball out of the cannon and the angle of the cannon. Figure 11.3 shows how the vector v representing the cannonball departing the cannon oriented at angle a can be decomposed (resolved) into horizontal and vertical vectors, vx and vy. The magnitude of the two vectors turns out to be easy to calculate using the built-in trigonometric functions. Look at the triangle shown in Figure 11.3. It is a right triangle, meaning that two of the sides are perpendicular. The side opposite the right angle is the hypotenuse. The angle at the left is of size a. Triangles that have the same angles are said to be similar and can be thought of as having the same shape. The ratio of the side labeled horizontal component vx to the hypotenuse will be the same for any triangle with this shape. The cosine of a is defined to be this ratio. Similarly, the ratio of the side opposite, vy, to the hypotenuse, v, is the sine of the angle a. These ratios are definitions of the trigonometric functions sine and cosine.
Figure 11.3 Initial speed as the sum of the component parts.
Introduction to Concepts
Using pseudo-code and the common abbreviations of the functions, vx = v * cos(a) vy = v * sin(a) Most programming languages have built-in functions or methods for producing the trigonometric functions. This is also the case with JavaScript: vx = v * Math.cos(a); vy = v * Math.sin(a);
and Math.sin are class methods similar to Math.random and Math.floor. The parameter a is the angle. Stating this in practical terms, once you know the value v, the velocity of the cannonball out of the cannon, and the angle a, the rotation of the cannon, you can write the code to calculate the horizontal and vertical velocities for moving the cannonball.
Math.cos
Tip What are the units for the angle? This question may not have occurred to you because you assume that degrees----360 indicating a full circle----are the only way of measuring angles. I am sure you are familiar with degrees----90 degrees to a right angle; making a u-turn is ‘‘doing a 180’’----but this measurement is arbitrary, and it is not the only possibility. Many computer programming languages use radians in place of degrees. Imagine taking the radius of a circle and using it as the ruler to measure the arcs around the circle. There are 2 * pi radians to go all the way around. One radian is a little less than 60 degrees. This unit may seem strange, but calculations are easier. Consequently, a radian is the standard unit for many programming languages. You need to determine what units the built-in trigonometric functions expect and adjust accordingly.
The Cannonball application expects the player to input the angle in the familiar degrees. The built-in functions expect angles to be expressed in radians. The program, therefore, must make the conversion. Fortunately, JavaScript provides a Math class variable Math.PI. The code for the conversion is angle_radians = angle_degrees * Math.PI/180
Now that it’s clear how to determine the initial values to use to animate the cannonball, it is time to describe how to include the effects of gravity. The vertical velocity must change. Exploring this requires a return to the equations of motion. Velocity changes position and causes displacement. The displacement is calculated using the formula new_position = old_position þ velocity * time
233
234
Chapter 11
n
Ballistics Simulation
Gravity is a force that brings about acceleration. Acceleration changes velocity. The technical term acceleration means any change in velocity, not just getting faster by pushing on the car gas pedal. Acceleration can mean going faster or slower, and it can refer to changes in direction. The relevant formula is new_velocity = old_velocity þ acceleration * time Assuming constant acceleration, the velocity at the end of the time interval chosen for the simulation is the velocity at the start of the interval plus the value of the acceleration. Note that the sign (positive or negative) of the acceleration does not matter for these equations to be valid. What is the velocity to be used for repositioning the object? To find the answer, take the average of the starting and ending values: average_velocity = (old_velocity þ new_velocity) / 2 Combine the last two equations: average_velocity = (old_velocity þ (old_velocity þ acceleration * time)) / 2 Put this value into the displacement equation: new_position = old_position þ ((old_velocity þ old_velocity þ acceleration * time) / 2) * time Simplify this: new_position = old_position þ old_velocity * time þ .5 *acceleration * time2 The simplification shows that the value assigned for the new position is a quadratic expression in terms of the time variable. This is why the path is a parabolic arc. The horizontal component of the velocity remains constant, so the object keeps moving horizontally as it started. The horizontal movement is proportional to the time elapsed. The vertical component undergoes the changes corresponding to the quadratic expression. For the ballistics simulation, assuming that the cannon is pointing up and to the right, the vertical velocity begins moving the projectile upward, changes to moving upward more and more slowly, and then changes to moving downward, then moving downward faster and faster. Figure 11.4 conveys this. When you get to the coding, you will learn about the signs of the relevant variables and how this produces the desired effect, but this mathematics and physics lesson is over. If you work on action games or simulations of many
Introduction to Concepts
Figure 11.4 Arc (may not be perfect parabola!).
phenomena of nature, you will need to explore more equations such as these involving forces and vectors.
Collision Detection The ballistics simulation featured in this chapter requires two calculations involving collisions: the ball hitting the ground and the ball hitting the target. It is important to understand that you, the programmer, need to check explicitly for the conditions that represent a collision. There are no cannonballs, targets, and ground inside the computer. Graphical objects are characterized by their positions on the screen or in the virtual world and numbers or formulas defining their shapes. The position technically is the location of the registration point or nominal origin of the object. It is critical to know what the registration point is because the computations are in terms of this point. The origin of all images in HTML is their upper-left corner. Figure 11.5 shows three of the images used in the Cannonball application, with the origin shown as a small dot. Notice that in the case of the ball and the wrecked target, the origin is not actually on the visible part of the object. For the block representing the original target, the origin is its upper-left corner. Figure 11.6 shows the ground. The origin is slightly above the upper-left corner. Tip The registration point or origin may or may not be in your control. In Flash, for example, you can define the registration point to be anywhere you want, including in the center of the graphical material.
235
236
Chapter 11
n
Ballistics Simulation
Figure 11.5 The ball, target, and wrecked target.
Figure 11.6 The ground.
If you know the registration point and the shape of an object, you can write code to determine if a point is within the boundaries of an object. Consider the following situation involving a rectangle. If a rectangle’s origin is the upper-left corner and origin = rx, ry width = rwidth height = rheight then the determination that the point (mx, my) is within the rectangle is calculated using the following if test: if ((mx>=rx) && (my >= ry) && (mx element. I will use elements and elements in a , as has been done in previous applications. The general outline is html
element
head
element
style
element containing styles for
ball ground block cannon script
element containing variables and functions
getObj, fire, travel, move, setposition, setinfo, stopflight body
element
div a
elements for ball, ground, target, and cannon
elements for Fire Cannon and for Stop Flight
form
element to hold input elements for velocity and angle and
for the Submit button to change this information This outline is for all three versions of Cannonball. The differences are in the details: a few more variables and changes to the travel function.
Use of Concepts in Implementation Implementing a program in steps is an example of the adage ‘‘make haste slowly.’’ Working on one thing at a time makes the work go faster.
Cannonball
Step 1: Making the Ball Go in a Parabolic Arc, No Stopping
The first step of implementation is to position the cannonball at the mouth of the cannon and move the cannonball according to the equations of motion. Because this step does not stop the flight, you need to close the window showing the movie. This may feel silly, but once this much of the program works, you have the most difficult part completed. As you did in the Bouncing Ball application, you achieve animation by using the setInterval function. This function sets up the call to a function I wrote called travel. The travel function figures out how to move the ball, the horizontal and vertical changes, and then calls a function called move. I did not have to do it this way, but I decided to separate the calculations arising from the physics of the problem from the pure geometric task of repositioning the ball. The <style> element contains the following lines. I determined the values by trial and error. #ball {position: absolute; top: 460px; left: 0px; } #ground {position: absolute; top: 500px; left: 0px; } #block {position: absolute; top: 220px; left: 800px} #cannon {position: absolute; top: 420px; left: 100px;}
The <script> element contains declarations for var var var var var var var var var
Please note that I determined the value 2 for the variable representing gravity by trial and error to look good on the screen. The getObj function is the same as in the previous chapter. The other functions are defined as shown in the table.
241
242
Chapter 11
n
Ballistics Simulation
JavaScript
Explanation
Start the definition of the move function. Change the variable holding the current horizontal coordinate. currenty += deltay; Change the variable holding the current vertical coordinate. ballobj.style.top = currenty; Set the top value in the ballobj. ballobj.style.left = currentx; Set the left value in the ballobj. } Close the function. function setposition(obj, Start the definition of the setposition function. function move(deltax, deltay) { currentx += deltax;
posx, posy) { obj.style.top = posy; obj.style.left = posx; return false; } function fire() { ballobj = new getObj("ball"); currentx = 100+250; currenty = 400+10; angleR = degrees*Math.PI/180; setposition(ballobj, currentx, currenty); yv = -Math.sin(angleR)*speed; xv = Math.cos(angleR)*speed; tid = setInterval ("travel();", 200); } function travel() { var averageyv; var oldyv = yv; yv = yv+g; averageyv = .5*(oldyv+yv); move(xv, averageyv); } function stopflight() { clearInterval(tid); } function setinfo(f) { speed = 1*f.speedf.value;
Set the top attribute in the indicated object. This positions the object vertically. Set the left attribute in the indicated object. This positions the object horizontally. Return false. End the function. Start the definition of the fire function. Create an object for the ball. Set the initial horizontal position using numbers derived by experiment. Set the initial vertical position using numbers derived by experiment. Convert from degrees to radians. Set the ball at the current (starting) position. Set yv to be the initial vertical velocity. Set xv to be the horizontal velocity. Set up the timed event: call the travel function every 200 milliseconds. Close the function. Start the definition of the travel function. Declare the local variable. Declare and initialize oldyv to the current yv value. Add g to yv. Calculate the average vertical velocity. Call move to reposition the ball by xv and averageyv. Close the function. Start the definition of the stopflight function. Stop the timed interval event. Close the function. Start the definition of the setinfo function, which uses information in fields in the form f. Set the speed to the value entered by the player, converting it to a number by multiplying it by 1.
Explanation Set the speed to the value entered by the player, converting it to a number by multiplying it by 1. Return false. Close the function.
The element contains the following elements for the ground, cannon, ball, and target (called block).
Because I want the cannonball, the cannon, and both the block.gif representing the original target and the wreck.gif representing the hit target to lie on top of the ground, I need to put the coding for the ground before the others. The rest of the HTML for the document produces the text, the input fields, and the button.
HTML with JavaScript
Explanation
Fire cannon
Set up the hyperlink to fire the cannon.
Stop flight
Set up the hyperlink to stop the flight.
Start the form. Set up the text and the input field for the player to change the speed out of the cannon. Set up the text and the input field for the player to change the angle. Set up the button.
Velocity out of cannon Angle
Close the form.
243
244
Chapter 11
n
Ballistics Simulation
Create the four image files and then put all this together into an HTML document, including the getObj function. Test it in a browser. When it works, the ball goes in a parabolic arc. The application will keep going, so you need to click on the X in the upper-right corner to close the browser window. Step 2: Checking for Ground and Target, Issuing Alerts
The next step is to put in code to stop the flight, either when the cannonball hits the target or hits the ground. You could do this the same way for ground and for target, but I do one type of calculation for the ground and another for the target as suggested earlier in the chapter. Figure 11.10 shows the screen shot of the simulation when the ball hits the ground. I add three variables for this version of the application when the cannonball has hit the ground. var groundlevel = 500; var bx = 800; var by = 200;
Figure 11.10 Alert window following ball hitting the ground.
Cannonball
The first one is to indicate the vertical position beyond which the code ‘‘says’’ the ball has hit the ground. The bx and by are the dimensions of the block that is the target. It is a small thing, but I do the calculations concerning the ball in terms of currentx + 25 and currenty+25. The currentx and currenty hold the origin of the ball image. It is the upper-left corner. Using offsets of 25 in each dimension
makes the computation in terms of the center. I show the enhanced travel function in full. The changes are the two if statements indicated in bold. function travel() { var averageyv; oldyv = yv; yv = yv+g; averageyv = .5*(oldyv+yv); if (hitblock(currentx+25, currenty+25)) { stopflight(); alert("you hit the block"); document.blockname.src = "wreck.gif"; } if (hitground(currentx+25, currenty+25)) { stopflight(); alert("you hit the ground"); } move(xv, averageyv); }
Step 3: Changing the Target, Removing Alerts
This next enhancement to the project is to remove the alerts, which certainly can be considered clunky. I can change the look of the target by changing the src attribute of the corresponding element as has been done in several previous examples. I do need to create one more image file, which I named wreck.gif. The tag needs a name. I show the surrounding code defining the element so you can see that it does not change:
I changed the travel function by removing the alerts and swapping in the other image file. I decided to enhance the look slightly by adjusting the position of the
245
246
Chapter 11
n
Ballistics Simulation
ball to ensure that it would lie on the ground. Placing the origin of the image displaying the ball at 25 pixels above ground level makes the bottom of the ball appear to lie on the ground. The additions are indicated in bold. function travel() { var averageyv; oldyv = yv; yv = yv+g; averageyv = .5*(oldyv+yv); if (hitblock(currentx+25, currenty+25)) { stopflight(); document.blockname.src = "wreck.gif"; } else if (hitground(currentx+25, currenty+25)) { stopflight(); setposition(ballobj,currentx,groundlevel-25); } else { move(xv, averageyv);} }
The application so far relies on the player acting properly. I added a check on the angle being within the range 0 to 85. If the player puts in something different, it is not accepted. Note that if the player includes letters in place of numbers, the text is treated as 0. More checking certainly is required for a real application. Prepare the wreck.gif image, put the coding together, and test.
What Can Go Wrong This application is meant to inspire you to build an improved version. However, the recommendations already mentioned deserve repetition: start with simple graphics, and work in steps. One common error is failing to test what happens if the cannonball does not hit the target. You, the developer, are not the player. Your job is not over when the ball hits the target. The application ‘‘works’’ if it shows the correct results for all settings.
Chapter Summary This chapter covered the programming features necessary to simulate projectile motion. The basics for the computed animation were addressed in the previous chapter. This chapter focused on the mathematical operations necessary to
Chapter Summary
represent (resolve) a vector into vertical and horizontal components and calculate the changing vertical velocity. These are similar in any programming language. The application also required implementation of accepting player input and collision detection.
What You Have Learned In this chapter, you n
Learned how to implement simulation of the physics of projectile motion using expressions involving mathematical functions
n
Learned how to detect simulated collisions
n
Practiced getting input from the player through text boxes
Cannonball, along with Bouncing Ball of the previous chapter, shows the power of computed animation. The program, based on inputs and actions by the player/ user, produces a complex display. It makes you appreciate the fact that a computer program can produce results that you did not specifically predict but are still under your control. The radians versus degrees issue brings up an important point for interface design: build an interface for the user, not for the programming language. People use degrees. It is the developer’s job to code any conversions to satisfy the internal system requirements. The application shows event-driven, interactive programming. The events include the passage of time, the player entering information into text fields, and the player clicking a button.
In the Real World Ballistics simulation was one of the earliest applications of computers. Simulation and control of missiles and rockets still are important applications. A question to ask is how much of the material in this chapter applies to programming languages other than HTML and JavaScript. The answer: most of it. The laws of physics are the same. The equations of motion are the same. Setting up events and event handlers varies, but the general design considerations apply to any programming system.
247
248
Chapter 11
n
Ballistics Simulation
Of course, if you were working on an application to simulate, track, or control real phenomena, you would need to pay closer attention to values and units. For the Cannonball application, the value for gravity, 2, was chosen because it produces a nice-looking arc on the screen. Programs created to help scientists, engineers, and planners better visualize and understand situations may require that the simulation run at variable rates, slower or faster than the real thing. The general lessons of this chapter on dividing implementation into steps and testing all situations apply even more to work in industry than to projects found in books. Organizations may even have groups of professionals whose main assignments are to plan the steps of work or perform system testing.
What’s Next The next and last chapter presents a different kind of simulation: the virtual dog. It represents the class of simulations for phenomena that have a fixed number of different states, and with behavior involving probabilistic and deterministic calculations.
Review Questions 1. If you wanted the ball to rise higher before falling to the ground, what would you change? 2. Which function calls the move function? 3. What calls the travel function? 4. Why is the variable holding the vertical velocity being increased each interval? 5. What is the style for placing a with id="ball" at a location in the middle of a window 600 pixels wide and 400 pixels high?
On Your Own 1. Create pictures of a cannon rotated to 10, 20, 30, and so on up to 80 degrees. Determine which one is closest to the angle input by the player, and substitute that in the element. This produces a much nicer look for the game. 2. Add a second target to the Cannonball application, and modify the coding to check for each target separately.
chapter 12
Discrete State Simulation
This chapter focuses on building a discrete state simulation with stochastic processes. Discrete state refers to the fact that the application makes reports at timed intervals and the phenomenon represented has a finite number of distinct states. Stochastic processes are controlled by pseudo-random calculations. The featured application is a virtual pet: a computer representation of a pet dog in which the owner actions of feeding and petting the dog have effects according to a model of dog behavior. While studying this chapter, you will n
Learn about discrete state simulation as a way to model different phenomena
n
Understand how to integrate deterministic and probabilistic factors in a computer model
n
Practice using images, including animated GIFs, in an HTML document
n
Gain experience using HTML and JavaScript features for timed events, display of changing information, Math.random, if statements, hyperlinks for JavaScript code, and expressions
Motivating Example The game featured in this chapter is a virtual pet. More or less elaborate virtual pets exist online and in the form of physical dolls. The goal can be to see how long you can keep the virtual pet alive or simply to be amused by 249
250
Chapter 12
n
Discrete State Simulation
Figure 12.1 Initial screen for Virtual Dog.
the changing display. The implementation featured here allows the player, who can be called the dog owner, to feed or pet the dog. The opening screen is shown in Figure 12.1. The four hyperlinks at the bottom of the screen invoke the actions of starting and stopping the simulation and feeding or petting the dog. The text boxes tell the state of the dog and the weight. The weight starts off at 100. The picture also indicates the state of the dog. The simulation is based on a timed cycle. The dog loses weight as time passes and gains weight after it eats (see Figure 12.2). If substantial time passes without the dog being fed, the dog dies (see Figure 12.3). After the dog dies, the game needs to be restarted. Figure 12.4 shows a situation in which the owner has fed the dog. Notice that its weight is 103. Just as it is possible to starve the virtual pet, it is possible to overfeed it (see Figure 12.5). Overfeeding can lead to the death of the virtual pet, as shown in Figure 12.6.
Motivating Example
Figure 12.2 Thin dog.
Figure 12.3 Thin, dead dog.
251
252
Chapter 12
Figure 12.4 Dog fed.
Figure 12.5 Fat dog.
n
Discrete State Simulation
Motivating Example
Figure 12.6 Dead, fat dog.
Figure 12.7 One snapshot from animated GIF of wagging dog.
The action of petting the dog can lead to a happy dog wagging its tail or a dog that snarls. The tail-wagging dog is implemented using an animated GIF file. The screen shot shown in Figure 12.7 is one frame from wag.gif.
253
254
Chapter 12
n
Discrete State Simulation
Figure 12.8 Snarling (mean) dog.
The snarling dog is portrayed using a static graphics file (mean.gif), as shown in Figure 12.8. The choice of wagging dog or snarling dog is based on a calculation with deterministic and stochastic features. There always is a chance of either event happening. However, it is more probable that the dog will be happy and wagging its tail if it has been recently fed. The critical features required by this application include n
A mechanism for keeping track of time so that when an interval passes, a certain procedure is invoked
n
A way to change the image displayed
n
Persistent data to keep track of the state of the dog, including its weight and when it was last fed
n
Programming logic for checking conditions to take certain actions
n
Techniques to manage the state, the image displayed for the state, and the label for the state
Introduction to Concepts
Introduction to Concepts The applications in the previous two chapters simulated situations involving movement: a ball bounced against walls and a cannonball was fired from a cannon hitting a target or the ground. The critical element that changed was position. The simulation was the animation. Other simulations involve phenomena in which single or multiple conditions change. The entities being simulated can assume or be in a small number of well-defined states. These simulations resemble the animations in that calculations take place at set intervals. The calculations determine if the state is to remain the same or change. The states and other state variables, such as the dog’s weight, are examples of persistent data, as described in the applications in previous chapters. The presentation of state involves an image and a label appearing under the image on the screen. This information is organized using associative arrays, or arrays in which the index is a string. In the real world, the change of state does not have to be either completely determined by conditions or purely by chance. The programming constructs of pseudo-random functions, expressions, and if statements provide the tools to combine deterministic and stochastic factors in calculations. The HTML and JavaScript applications described so far include pictures produced by the display of image files. One special type of image file is the animated GIF. It is treated as a single image by HTML, but the browser and other programs display it as a short animation.
Discrete State Simulation Some phenomena can be modeled by defining or identifying a finite number of discrete states and a finite number of conditions or inputs. The model changes state according to a known set of rules that consider the current state and the inputs. The model is never between states. Just as a digital clock changes the display abruptly between settings, state transitions are instantaneous. Of course, the underlying phenomenon may be more complicated, but the model, the abstraction, follows the rules. A computer simulation can be built based on these ideas. A global variable holds the state. When it is appropriate to check whether there should be a change of state, a conditional test—for example, some combination of if or switch statements—is
255
256
Chapter 12
n
Discrete State Simulation
executed based on the state and other variables. There may be a way to change the variables based on inputs from someone running the simulation. The conditional clauses may or may not change the state. Some simulations keep going, some run for a specified number of cycles, and some run until one of a designated set of final states is reached. Some simulations use any change in the variables to trigger the function that calculates whether there needs to be a change in state. An alternative is to perform the test periodically based on time. The animations described in Chapters 10, ‘‘Computed Animation,’’ and 11, ‘‘Ballistics Simulation,’’ used the frame structure of Flash to perform the calculation that changed the position of the ball. In applications programmed using HTML and JavaScript, the setInterval command sets up execution of the indicated JavaScript code at the specified time interval. The call tid = setInterval("change();", 1000);
sets up a timed event to happen every second. (1000 milliseconds equals one second.) The handler for the event is the function change. The tid variable holds a value that can stop the timed event. The states of Virtual Dog are represented by the images: the normal dog, the fat dog, the hungry dog, the dead (starved) dog, and so on. At each time interval, logic is invoked to check whether there needs to be a change of state. Tip The Virtual Dog application is not a pure discrete state simulation because a global variable named weight holds the dog’s weight, and a variable named feedtime holds the time it was last fed. The states of the simulation are implemented using parallel structures: an array holding the names of the image files and an array holding text indicating the status of the dog. The presence of the persistent data for weight and feedtime, in addition to the state information, puts this application in a more powerful class in terms of computability theory.
Associative Arrays Recall from Chapter 8, ‘‘Automating a Physical Application,’’ that an associative array is an array in which the index is not a number but something else, such as a string. This is an excellent way to hold the information on the name of the image file corresponding to a state and the label corresponding to a state. You can always use regular arrays by encoding the information, making the 0th element correspond to ‘‘normal,’’ the 1st correspond to ‘‘thin,’’ and so on. If it were
Introduction to Concepts
necessary to keep two sets of information, you would refer to the arrays as parallel structures. However, if the programming language supports associative arrays, the coding is easier to produce, to read, and to modify. For this situation, a character string representing the state would be the index value. The initialization of the data would include statements like the following for each state: statepictures[’normal’] = "normal.gif"; statelabels[’normal’] = "Dog is normal.";
Then if the variable curstate held a string indicating the state, the following statements would insert the appropriate image and the appropriate label: document.f.label.value=statelabels[curstate]; document.pic1.src=statepictures[curstate];
Combining Stochastic and Deterministic Factors A decision might depend on a mixture of factors, some stochastic (also known as probabilistic) and some determined by a fixed formula. The term deterministic refers to factors that are not random. The coin flip examples in Chapter 5, ‘‘Variables and Datatypes,’’ demonstrated a way to integrate pseudo-randomness into an application. If the bias on the coin is set to be strongly favorable toward heads, then it still is possible for the result to be tails, but it is less likely. The function Math.random, or its equivalent in other languages, returns a number from 0 to 1. This number is compared to the bias point. The Virtual Dog application has a feature combining stochastic and deterministic factors. What corresponds to the bias setting for the weighted coin toss, the point at which the decision is made to present a wagging dog or a snarling dog, depends on the elapsed time since the dog was fed. This point has an upper and a lower bound. The code is written to ensure that it always is less than 1 and greater than 0. This means that the wagging dog and the snarling dog are both always possible, although the wagging dog becomes less likely as the time since feeding grows. Note The notion that something is neither totally up to chance nor absolutely determined actually is fairly common, so it is fortunate that programming provides a way to represent such situations.
257
258
Chapter 12
n
Discrete State Simulation
Animated GIFs Previous chapters demonstrated ways to produce animation. One particular format for images, GIF, provides a way to construct an entire animation within one file. Several software tools exist for generating these animated GIFs. For example, Animation Shop, part of the Corel Paint Shop Pro product, has an Animation Wizard tool to identify a sequence of image files, specify the time duration for each image, and define the looping for the sequence. The software also provides ways to vary the transitions from image to image. In terms of the treatment by the JavaScript program, the image is just another image file. Any of the images for the Virtual Dog application could be animated GIFs. The wagging dog seemed appropriate as a representation of a dog happy to be pet by its owner.
Virtual Dog This section reviews how time and timing were handled in previous chapters and then goes on to describe the implementation of the Virtual Dog application.
Review of Previous Examples Chapters 4, ‘‘Events and Event Handling and the Graphical User Interface,’’ and 8 used the setTimeout function in JavaScript to set up a timed event to occur after a specified amount of time. In Chapter 4, the setInterval function set up a timed event to keep happening until it was stopped using clearInterval. Chapters 10, ‘‘Computed Animation,’’ and 11, ‘‘Ballistics Simulation,’’ each used setInterval to invoke a function that repositioned a ball, producing the appearance of movement. The application in this chapter will use setInterval to set up calls to a function that monitors the state of Virtual Dog. Many of the previous applications, starting from the coin flip, involved changing the picture displayed on the screen by changing the value of the src attribute of an tag. The Virtual Dog program will use this technique.
Plan of Attack for Virtual Dog The organization of the applications is html
element
head
element
Virtual Dog title
element
script
element
global variables weight tid
for timing event
wagtime,
used to stop display of wagging
elapsed
to hold time since feeding
interval
used as a constant 1000
statepictures statelabels
array of picture file names corresponding to states
array holding text describing states
function definitions: change, start, stop, petdog, feeddog body
element
img
tag to hold appropriate dog image
form
elements: input boxes to show status and weight
hyperlinks to start game, stop game, feed dog, pet dog The change function uses a switch statement to go through the logic for the different states. After you determine the new state, the displayed picture and information are reset. The following table indicates the calling and calls structure of the functions. Function
Called/Invoked By
start
Action Action Action Action Action
stop change feeddog petdog
of of of of of
Calls
hyperlink hyperlink, change
clearInterval
setInterval setting up call to change; feeddog
setInterval
stop
hyperlink hyperlink
-------
Use of Concepts in Implementation The discrete states of the Virtual Dog application are represented by two arrays— statepictures and statelabels —and a variable curstate used as an index to each of the arrays. These are declared and initialized at the start of the <script> element.
259
260
Chapter 12
n
Discrete State Simulation
var curstate=’normal’; var statepictures=new Array(); var statelabels=new Array(); statepictures[’normal’]=’dog.gif’; statelabels[’normal’]=’Dog is normal.’; statepictures[’fat’]=’fatdog.gif’; statelabels[’fat’]=’Dog is fat.’; statepictures[’fatdead’]=’fatdeaddog.gif’; statelabels[’fatdead’]=’Dog is dead.’; statepictures[’thin’]=’thindog.gif ’; statelabels[’thin’]=’Dog is thin.’; statepictures[’thindead’]=’thindeaddog.gif’; statelabels[’thindead’]=’Dog is dead.’; statepictures[’wagging’]=’wag.gif’; statelabels[’wagging’]=’Dog is wagging its tail.’; statepictures[’mean’]=’mean.gif’; statelabels[’mean’]=’Dog is angry. ’;
Other global variables are the following: var var var var var
The main workhorse of this application is the change function. It is the event handler set up by the start function in its call to setInterval. Again, the transition logic for the states is performed in a switch statement.
JavaScript
Explanation
function change(){
Start the function definition. Add to the time since feeding. Decrease weight. Start the setup of the switch statement based on the current state. Set up the normal case. Check if weight is high. Change to fat. Close if. Check if weight is low. Change to thin. Close if.
elapsed=elapsed+interval; weight=weight-1; switch (curstate) { case ’normal’: if (weight>120) { curstate=’fat’; } if (80>weight) { curstate=’thin’; }
Virtual Dog
JavaScript
Explanation
break;
Break out of the switch statement. Set up the fat case. Check if weight has dropped. Change to normal. Close if. Check if weight is really high. Change to dead from fat state. Close if. Break out of the switch statement. Start the fat and dead case. Break out of the switch statement. Start the thin case. Check if weight is back up into normal range. Change to normal. Close if. Check if weight is really low. Change to dead from the thin state. Close if. Break out of the switch statement. Start the thindead case. Break out of the switch statement. Start the wagging case. Check if enough time has been passed in the wagging case. Change to normal. Close if. Break out of the switch statement. Start the mean case. Check if enough time has passed. [Use the same value (5).] Change to normal. Close if. Break out of the switch statement. Close switch statement. Display the label corresponding to the state.
case ’fat’: if (120>weight) { curstate=’normal’; } if (weight>150) { curstate=’fatdead’; } break; case ’fatdead’: break; case ’thin’: if (weight>80) { curstate=’normal’; } if (60>weight) { curstate=’thindead’; } break; case ’thindead’: break; case ’wagging’: if ((wagtime++)>5) { curstate=’normal’; } break; case ’mean’: if ((wagtime++)>5) { curstate=’normal’; } break; } document.f.label.value =statelabels[curstate]; document.pic1.src =statepictures[curstate];
Display the picture corresponding to the state.
document.f.weightx.value =weight;
Display weight.
if (curstate==’fatdead’){
Check if dead. Stop the timed event.
window.clearInterval(tid);
261
262
Chapter 12
n
Discrete State Simulation
JavaScript
Explanation
}
Close if. Check if (other) dead state. Stop the timed event. Close if. Close the function.
if (curstate==’thindead’){ window.clearInterval(tid); } }
The start function is called by the player clicking on a hyperlink in the body. JavaScript
Explanation
function start() {
Start the function definition. Set up the timed event: change is called every interval milliseconds. The variable tid holds the identifying number for this timed event. Close the function.
tid=setInterval("change()", interval); }
The stop function is called by the player clicking on a hyperlink in the body. See the ‘‘What Can Go Wrong’’ section for a warning. JavaScript
Explanation
function stop() {
Start the function definition. Stop the timed event using the tid variable. Close the function.
window.clearInterval(tid); }
The feeddog function also is invoked by the player clicking on a hyperlink in the body.
JavaScript
Explanation
function feeddog() {
Start the function definition. Add to the weight. Assign 0 to the variable elapsed to set the time passed since feeding to 0. Close the function.
weight=weight+10; elapsed=0; }
Virtual Dog
The petdog function is invoked by the player clicking on a hyperlink button in the body. The condition in the if statement is complicated and explained next. JavaScript
Explanation
function petdog() {
Start the function definition. Initialize the time for wagging to 0. Check if the results of Math.random() are in the calculated happy range. Set to wagging. Close if-true clause. Start not-true clause. Set to mean state. Close the clause. Close the function.
The condition determining wagging or snarling involves the following steps: 1. Determine the number of seconds since the dog has been fed by dividing elapsed by interval. 2. Take whatever is smaller: the number of seconds since feeding or 19. This means this value will never be more than 19. It does grow to 19 if the dog is not fed. 3. Divide this number by 20. This value ranges from 0 to 19/20. Because elapsed is incremented by interval at each call of change, it will rarely be 0. This will be the deciding factor. 4. Invoke Math.random() to produce a number between 0 and 1. 5. Compare the random value to the deciding factor. If the random value is more, the condition is met. This concludes the explanation for the variables and the functions defined in the <script> element in the element. The body of the HTML document contains the element holding the picture of the dog in its current state, the form data displaying status and weight,
263
264
Chapter 12
n
Discrete State Simulation
and the four hyperlinks. Note that the elements actually output information to the player. HTML
Explanation
Start the body element. Set up the place for pictures of the dog. Start the form element. Set up to hold the state information; the initial value is that the dog is normal. Set up to hold the weight; the initial value is set at 100. Close the form. Display the horizontal rule: a line across the window. Set up the hyperlink to invoke the function to feed the dog. Set up the hyperlink to invoke the function to pet the dog. Set up the hyperlink to invoke the function to start the simulation. Set up the hyperlink to invoke the function to stop the simulation. Close body.
State Weight Feed dog Pet dog Start play Stop play
A feature of this project is that it is easy to test the application systematically. How does the screen look when the HTML document is loaded initially? If this is okay, click on the Start Play hyperlink and let the program run. The status line should change to indicate that the dog is hungry, and the weight should go down. Soon you will see the picture of the thin dog. Assuming all this works, reload the project (see ‘‘What Can Go Wrong’’ for a possible problem), click on Start, and then try clicking on the Feed Dog button. Next, try letting the dog go hungry and then feeding it. The next thing to test is petting the dog. Lastly, mix up the order of clicking on the hyperlinks.
What Can Go Wrong The syntax in the change function can be tricky, but be careful to match up starting and stopping curly brackets. Remember to put in the break; statements at the end of the code for each case. The first version of this application, not shared with you, was an unsystematic set of if and if/else statements. Defining states with associated images and text for
Chapter Summary
status, using a switch statement, and then resetting the visible picture, status, and weight information each time made the application much easier to understand and to code. Browsers may not reinitialize form input text fields when an application is reloaded. You may notice this when testing your application. The internal values are reinitialized: curstate to "normal" and weight to 100; the src for the pic1 tag will be set, but momentarily you may see the prior values.
Chapter Summary This chapter focused on the programming features necessary to produce a simulation of a situation represented by distinct states. The states change based on deterministic and probabilistic factors and the programming needed to implement the required calculations. Animated GIF image files livened up the look of the application. My students tell me that it is clear that I do not like dogs, but they still enjoy the project. Feel free to make the project your own. A reason for including it in this text is to show the power of programming to produce reasonable, but not totally predictable effects. It is possible to describe this project without mentioning the theoretical ideas of discrete state simulation and finite state automata. However, these concepts did help the author in improving the design of the application, so they are deemed worth sharing with readers. The dog wagging its tail part of this application was achieved by integrating the use of animated GIFs, produced by a separate program, with HTML and JavaScript. Combining different software tools and the products of different software tools is an effective way to build applications.
What You Have Learned In this chapter, you learned n
How to mix deterministic and probabilistic (stochastic) factors
n
How to define and set up states represented by text and images
n
How to incorporate animated GIFs into an application
n
How to encode checking of conditions involving states and variables
265
266
Chapter 12
n
Discrete State Simulation
In the Real World The Virtual Dog application is a model, like a paper airplane is a model. This one features dog behavior. It may or may not fit your idea of what dogs do. Computer models are used to investigate and control a variety of natural and man-made phenomena. Commercial and scientific organizations devote considerable resources to building and running simulations. For example, the programs to predict the weather are examples of simulations. The weather programs divide the atmosphere into a finite, but large, number of regions. Initial conditions exist in each region concerning temperature, pressure, precipitation, and so on. Mathematical equations define how the conditions can change based on the conditions in each region and in each bordering region. Although the simulations are not perfect and require substantial computer resources, they are getting better at predicting the weather. Similarly, programs to study traffic and epidemics involve simulations with states and transition rules.
What’s Next This was the last chapter. I hope you enjoyed reading it and making the projects your own with your pictures and ideas. You will find the Answers to the Review Questions and a Glossary next.
Review Questions 1. How are the player/dog owner’s actions implemented? 2. Describe the statepictures and statelabels arrays. Why is the term ‘‘parallel structures’’ used to describe situations with two (or more) such arrays? 3. What is required to add a new state? 4. What is the code that determines the reaction to petting the dog? 5. Why is the coding shown for this application described as combining stochastic and deterministic calculations?
Chapter Summary
On Your Own 1. Write the code for setting up a call to a function called hello() every 5 seconds. 2. Write the code that makes clicking on a link with the text Start Laughing start the process of calling a function named laugh() every 10 seconds and clicking on a link with the text Be quiet stop it.
267
This page intentionally left blank
appendix a
Answers to End-ofChapter Questions Chapter 1 Questions 1. Explain what is meant by development time versus runtime. 2. Explain the relationship of the HTML elements html, head, body, p, img, and a. Which elements go inside which elements? 3. What is the HTML for producing a hyperlink that will take the user to a site with the address http://www.irs.gov if the user clicks the words TAX INFORMATION? 4. What is the HTML for displaying the image file snow.jpg? 5. In HTML,