Beginning C++ Game Programming


Чтобы посмотреть этот PDF файл с форматированием и разметкой, скачайте его и откройте на своем компьютере.
Acknowledgments
SVP,Thomson Course
Technology PTR:
Andy Shafran
Publisher:
©2004 by Thomson Course Technology PTR.All rights reserved.No
part ofthis book may be reproduced or transmitted in any form or by
any means,electronic or mechanical,including photocopying,record-
ing,or by any information storage or retrieval system without written
permission from Thomson Course Technology PTR,except for the
inclusion ofbriefquotations in a review.
The Premier Press and Thomson Course Technology PTR logo and
related trade dress are trademarks ofThomson Course Technology PTR
and may not be used without written permission.
All trademarks are the property oftheir respective owners.
Important:
Thomson Course Technology PTR cannot provide software
support.Please contact the appropriate software manufacturers techni-
cal support line or Web site for assistance.
Thomson Course Technology PTR and the author have attempted
Course Technology PTR from sources believed to be reliable.However,
because ofthe possibility ofhuman or mechanical error by our sources,
Thomson Course Technology PTR,or others,the Publisher does not
from use ofsuch information.Readers should be particularly aware of
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Questions and Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Discussion Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Chapter 5Functions: Mad Lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .129
Creating Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Using the switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Using while Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Using do Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Using break and continue Statements . . . . . . . . . . . . . . . . . . . . . . . . 50
Using Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Generating Random Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Understanding the Game Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Introducing Guess My Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Questions and Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Discussion Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Chapter 3For Loops, Strings, and Arrays: Word Jumble . . . . . . . . . . .71
Using for Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Understanding Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Using string Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Using Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Understanding C-Style Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Using Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Introducing Word Jumble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Questions and Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Discussion Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Chapter 4The Standard Template Library: Hangman . . . . . . . . . . . . .99
Introducing the Standard Template Library . . . . . . . . . . . . . . . . . . . . 99
Using Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Using Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Understanding Vector Performance . . . . . . . . . . . . . . . . . . . . . . . . . 116
Examining Other STL Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Planning Your Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Introducing Hangman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Chapter 1Types, Variables, and Standard I/O: Lost Fortune . . . . . . . . .1
Introducing C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Writing Your First C++ Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Working with the std Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Contents
AWSON
has worked as both a programmer and a computer game designer and
producer.In addition to real-world game industry experience,Mike earned his bachelors
degree in Computer Science from the University ofSouthern California.Mike currently
teaches game programming and design to students ofall ages through UCLA Extension
courses and private lessons.Visit his website at http://www.programgames.com to learn
About the Author
This book is for anyone who wants to program games.Its aimed at the total beginner and
assumes no previous programming experience.Ifyoure comfortable using your com-
puter,then you can start your game programming odyssey right here.But just because this
book is written for the beginner,that doesnt mean learning C++ and game programming
will be easy.Youll have to read,work,and experiment.By the end ofthis book,youll have
a solid foundation in the game programming language ofthe professionals.
I start at the very beginning ofC++ and game programming,assuming no experience
in either.As the chapters progress,I cover more advanced topics,building on previous
material.
In each chapter,I cover one or several related topics.I move through concepts one step at
a time by writing bite-sized,game-related programs to demonstrate each idea.At the end
ofeach chapter,I combine some ofthe most important concepts in a single game.The last
chapter ofthe book ends with the most ambitious project„one that harnesses all ofthe
major concepts presented throughout the book.
In addition to learning about C++ and game programming,youll also learn how to orga-
nize your work,break down problems into manageable chunks,and refine your code.
Youll be challenged at times,but never overwhelmed.Most ofall,youll have fun while
learning.In the process,youll create some cool computer games and gain insight into the
craft ofgame programming.
Chapter 1:Types,Variables,and Standard I/O:Lost Fortune.
Youll be introduced to the
fundamentals ofC++,the standard language ofthe game industry.Youll learn to display
utting-edge computer games rival the best that Hollywood has to offer in visual
effects,musical score,and pure adrenaline rush.But games are a form ofenter-
tainment unlike any other;they can keep players glued to their monitors for hours
Introduction
Chapter 10Inheritance and Polymorphism: Blackjack . . . . . . . . . . . . .279
Introducing Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Controlling Access under Inheritance . . . . . . . . . . . . . . . . . . . . . . . 284
Calling and Overriding Base Class Member Functions . . . . . . . . . . . 286
Derived Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Introducing Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Using Abstract Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Organizing Your Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Introducing the Blackjack Game . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
Questions and Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
Discussion Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
Chapter 7Pointers: Tic-Tac-Toe 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . .191
Understanding Pointer Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Understanding Pointers and Constants . . . . . . . . . . . . . . . . . . . . . . 198
Passing Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Types, Variables, and
Standard I/O: Lost
Fortune
Chapter 1
ame programming is demanding.It pushes both programmer and hardware to
their limits.But it can also be extremely satisfying.In this chapter,youll be intro-
duced to the fundamentals ofC++,the standard game industry language.
Specifically,youll learn to:
Display output in a console window
These point out areas where its easy to make a mistake.
These suggest techniques and shortcuts that will make your life as a game programmer easier.
in the real world
These are facts about the real world of game programming.
The CD-ROM that comes with this book includes the following:
All ofthe source code for the programs and games presented in the book
The Bloodshed Dev-C++ IDE,which uses the MinGW port ofGCC as its
compiler
A walkthrough ofhow to use the Dev-C++ IDE to create your first program
SGIs Standard Template Library Programmers Guide
Useful links for C++,game programming,and industry news and information
A Word about Compilers
I hate to pick on any particular compiler or software company,but I have to say that I cannot rec-
ommend Microsoft Visual C++ 6.0.Its compiler fails to correctly implement C++ in some impor-
tant ways.As a result,a few of the programs in this book will not compile under Visual C++ 6.0.I
do my best to point out the issues when they arise in the programs in the book.If you want to go
C++ standard quite faithfully.
Chapter 4:The Standard Template Library:Hangman.
Youll be introduced to a power-
ful library„a toolbox that game programmers (and even non-game programmers) rely
on to hold collections ofthings,such as items in a players inventory.Youll also learn
about techniques that can help you plan larger game programs.
Chapter 5:Functions:Mad-Lib.
Youll learn to break up your game programs into
smaller,more manageable chunks ofcode.Youll accomplish this by discovering func-
tions,the fundamental units oflogic in your game programs.
Chapter 6:References:Tic-Tac-Toe.
Youll learn how to share information with different
parts ofyour programs in an efficient and clear manner.Youll also see a briefexample of
artificial intelligence
) and youll learn how to give a computer opponent a little bit of
personality.
Chapter 7:Pointers:Tic-Tac-Toe 2.0.
Youll begin to discover some ofthe most low-level
and powerful features ofC++,such as how to directly address and manipulate your com-
puters memory.
ever played a game where a character walked on air (that is,a character who
shouldnt be able to walk on air),then youve seen a logical error in action.
in the real world
Like other software creators,game companies work hard to produce bug-free products.Their last
line of defense is the quality assurance personnel (the game testers).Game testers play games for
a living,but their jobs are not as fun as you might think.Testers must play the same parts of a game
The ISO standard is often called the
.These different names
involve the acronyms of the various committees that have reviewed and established the standard.The
most common way to refer to C++ code that conforms to the ISO standard is simply
Writing Your First C++ Program
Types, Variables, and Standard I/O: Lost Fortune
1.First,the programmer uses an
to write the C++ source code,a file that usu-
ally has the extension .cpp.The editor is like a word processor for programs;it
allows a programmer to create,edit,and save source code.
2.After the programmer saves a source file,he invokes a C++
tion that reads source code and translates it into an
.Object files usually
have the extension .obj.
3.Next,a linker links the object file to any external files as necessary,and then creates
the executable file,which generally ends with the extension .exe.At this point,a
user (or gamer) can run the program by launching the executable file.
The process Ive described is the simple case.Creating a complex application in C++ often involves
To help automate this process,its common for a programmer to use an all-in-one tool for
development,called an IDE (
Integrated Development Environment
).An IDE typically
combines an editor,a compiler,and a linker,along with other tools.Popular commercial
logical error
,can make the program simply behave in unintended ways.Ifyouve
Its fast.
Well-written C++ programs can be blazingly fast.One ofC++s design
goals is performance.And ifyou need to squeeze out even more performance from
your programs,C++ allows you to use
assembly language
„the lowest-level
human-readable programming language„to communicate directly with the com-
puters hardware.
Its flexible.
C++ is a multi-paradigm language that supports different styles of
programming,including
object-oriented programming
.Unlike some other modern
languages,though,C++ doesnt force one particular style on a programmer.
Its well supported.
Because it is the dominant game programming language,
Types, Variables, and Standard I/O: Lost Fortune
Figure 1.1
The creation of an executable file from C++ source code
function
is a group ofprogramming code that can do some work and return a value.In
indicates that the function will return an integer value.All function headers
have a pair ofparentheses after the function name.
All C++ programs must have a function called
,which is the starting point ofthe
program.The real action begins here.
The next line marks the beginning ofthe function.
And the very last line ofthe program marks the end ofthe function.
Writing Your First C++ Program
You can also use what are called
,which can span multiple lines.All you have to
The next line in the program is technically a blank line.The compiler ignores blank lines.
In fact,compilers ignore just about all
whitespace
„spaces,tabs,and newlines.Like com-
ments,whitespace is just for us humans.
Judicious use ofwhitespace helps make programs clearer.For example,you can use blank
Types, Variables, and Standard I/O: Lost Fortune
You can type the code in yourself,but Ive also provided the source code for all ofthe pro-
grams on the CD-ROM that came with this book.The code for this program is in the
Chapter 1 folder on the CD-ROM;the file name is game_over.cpp.
For step-by-step instructions on how to create,save,compile,and run the Game Over program
using Dev-C++,check out Appendix A,Creating Your First C++ Program,Žon the CD-ROM that
came with this book.If youre using another compiler or IDE,check its documentation.
The first two lines ofthe program are comments.
Figure 1.2
Your first C++ program displays the two most infamous words in computer
Writing Your First C++ Program
,without any kind ofprefix.This might not seem like a big deal to
you now,but when you have dozens or even hundreds ofreferences to these objects,youll
Introducing the Game Over 3.0 Program
Okay,theres another way to accomplish the same thing,and thats exactly what Im going
to show you in the Game Over 3.0 program,which displays the same text as its predeces-
sors.The code for the program is in the Chapter 1 folder on the CD-ROM that came with
this book;the file name is game_over3.cpp.
Types, Variables, and Standard I/O: Lost Fortune
,and closes the window all in a split second.If you have this problem,just insert the follow-
Working with the std Namespace
Because its so common to use elements from the
namespace,Ill show you two dif-
Working with the std Namespace
I understand this might be a lot to take in,so check out Figure 1.3 for a visual represen-
When you run the Game Over program,you might only see a console window appear and disap-
pear just as quickly.Thats because C++ is so fast that it opens a console window,displays
Types, Variables, and Standard I/O: Lost Fortune
Figure 1.3
Introducing the Game Stats Program
The Game Stats program displays information that you might want to keep track ofin a
space shooter game,such as a players score,the number ofenemies the player has
Types, Variables, and Standard I/O: Lost Fortune
Figure 1.5
Each game stat is stored in a variable.
You might notice that while the result of
) includes a fractional part,it is still
even those of computationally intensive 3D games.
In the next statement,I use an operator you might not be familiar with„the modulus
operator (
).The modulus operator returns the remainder ofinteger division.In this case,
produces the remainder of
,which is
Understanding Order of Operations
The next line ofcode provides an example to help drive this home.Because multiplica-
tion has higher precedence than addition,you calculate the results ofthe multiplication
first.So the expression
is equivalent to
,which evaluates to
Ifyou want an operation with lower precedence to occur first,you can use parentheses,
For a list of C++ operators and their precedence levels,see Appendix B,Operator Precedence,Žon
Declaring and Initializing Variables
variable
Declaring and Initializing Variables
The code for the program is in the Chapter 1 folder on the CD-ROM that came with this
book;the file name is expensive_calculator.cpp.
minus sign,
),and multiplication (an asterisk,
).The results depicted in Figure 1.4 are
just what youd expect.
Types, Variables, and Standard I/O: Lost Fortune
Ifyou hate typing,you can employ the
directive.A decent compromise is to employ
declarations.In this book,Ill employ the
directive most ofthe time for brevi-
tys sake.
in the real world
Ive laid out a few different options for working with namespaces.Ive also tried to explain the
advantages of each so you can decide which way to go in your own programs.Ultimately,though,
grades or paychecks.
Figure 1.4
C++ can add,subtract,multiply,divide,and even calculate a remainder.
Keep the length in check.
Even though
is descriptive,it
can make code hard to read.Plus,long names increase the risk ofa typo.As a
guideline,try to limit your variable names to fewer than 15 characters.Ultimately,
code is written in such a way that its easy to understand what is happening in
the program independent of any comments.Choosing good variable names is an excellent step
toward this kind of code.
Assigning Values to Variables
In the next group ofstatements,I assign values to the six variables I declared.Ill go
through a few assignments and talk a little about each variable type.
Assigning Values to Integer Variables
In the following assignment statement I assign the value of
to
Now
stores
You assign a value to a variable by writing the variable name followed by the assignment
operator (
) followed by an expression.(Yes,technically
is an expression,which evalu-
ates to,well,
Assigning Values to Floating Point Variables
In this statement I assign
is oftype
,I can use it to store a number with a fractional part,
which is just what I do.
Assigning Values to Character Variables
In the following statement I assign
the single-character value
As I did here,you can assign a character to a variable oftype
by surrounding the char-
acter with single quotes.
Variables oftype
can store the 128 ASCII character values (assuming that your sys-
Types, Variables, and Standard I/O: Lost Fortune
I declare three more variables ofyet three more types in the next three lines.
variable oftype
is a variable oftype
.And
is a variable of
type
Games (and all major applications) require many variables.Fortunately,C++ allows you
to declare multiple variables ofthe same type in a single statement.Thats just what I do
next in the following line.
This line establishes two
variables„
Even though Ive defined a bunch ofvariables at the top ofmy
function,you dont
have to declare all ofyour variables in one place.As youll see later in the program,I define
a new variable just before I use it.
Naming Variables
To declare a variable,you must provide a name,known as an
identifier
.There are only a
few rules you have to follow to create a legal identifier.
Declaring and Initializing Variables
Okay,confused with all ofyour type options? Well,dont be.Table 1.1 summarizes com-
monly used types with some modifiers thrown in.The table also provides a range ofval-
ues for each.
The range of values listed in Table 1.1 is based on my compiler.Yours might be different.Check your
compilers documentation.
For brevitys sake,
Declaring Variables
Types, Variables, and Standard I/O: Lost Fortune
Table 1.1
Commonly Used Types
TypeValues
256 character values
booltrue
Declaring and Initializing Variables
score = score + 100;
//combined assignment operator
score += 100;
//increment operators
int lives = 3;
cout lives:  lives endl;
lives = 3;
lives++;
lives = 3;
int bonus = ++lives * 10;
cout lives, bonus =  lives ,  bonus endl;
lives = 3;
bonus = lives++ * 10;
cout lives, bonus =  lives ,  bonus endl;
//integer wrap around
score = 4294967295;
cout \nscore:  score endl;
++score;
Types, Variables, and Standard I/O: Lost Fortune
Finally,ifyou need a floating point number,youre probably best offusing
,which
again is likely to be implemented so that it occupies an amount ofmemory that is most
efficiently handled by the computer.
Figure 1.6
Each variable is altered in a different way.
The escape sequence I used is
,which represents a newline.When sent to
its like pressing the Enter key in the console window.Another useful escape sequence is
,which
acts as a tab.
There are other escape sequences at your disposal.For a list of escape sequences,see Appendix E
Types, Variables, and Standard I/O: Lost Fortune
Code for Information Interchange
Although you can declare a variable without assigning it a value,its best to initialize a new vari-
able with a starting value whenever you can.This makes your code clearer,plus it eliminates the
chance of accessing an uninitialized variable,which may contain any value.
Displaying Variable Values
To display the value ofa variable ofone ofthe fundamental types,just send it to
Thats what I do next in the program.Note that I dont try to display
you dont normally display
In the first statement of this section I use whats called an
),which represents special printable characters.
Declaring and Initializing Variables
The prefix increment operator increments a variable
before
the evaluation ofa larger
expression involving the variable.
is evaluated by first incrementing
,and
then multiplying that result by
.Therefore,the code is equivalent to
,which is
ofcourse.This means that now
Types, Variables, and Standard I/O: Lost Fortune
Figure 1.7
A way to visualize an
unsignedint
variable wrapping aroundŽfrom its maxi-
mum value to its minimum
This statement produces the same results as
.The
operator is called
combined assignment operator
Table 1.2
Combined Assignment Operators
OperatorExampleEquivalent To
+=x += 5;x = x + 5;
-=x -= 5;x = x - 5;
*=x *= 5;x = x * 5;
/=x /= 5;x = x / 5
%=x %= 5;x = x % 5;
Instead ofpresenting all the code at once,Ill go through it one section at a time.The code
for the program is in the Chapter 1 folder on the CD-ROM that came with this book;the
file name is lost_fortune.cpp.
Types, Variables, and Standard I/O: Lost Fortune
Figure 1.9
An
enumeration
The code for the program is in the Chapter 1 folder on the CD-ROM that came with this
book;the file name is game_stats3.cpp.
You cant assign a new value to a constant.If you try,youll generate a compile error.
Types, Variables, and Standard I/O: Lost Fortune
Make sure to pick an integer type that has a large enough range for its intended use.
Working with Constants
is an unchangeable value that you name.Constants are useful ifyou have an
unchanging value that comes up frequently in your program.For example,ifyou were
writing a space shooter in which each alien blasted out ofthe sky is worth 150 points,you
could define a constant named
that is equal to
.Then,any time you need
the value ofan alien,you could use
instead ofthe literal
Constants provide two important benefits.First,they make programs clearer.As soon as
you see
,you know what it means.Ifyou were to look at some code and see
,you might not know what the value represents.Second,constants make changes easy.
For example,suppose you do some playtesting with your game and you decide that each
alien should really be worth 250 points.With constants,all youd have to do is change the
in your program.Without constants,youd have to hunt
down every occurrence of
and change it to
Introducing the Game Stats 3.0 Program
The Game Stats 3.0 program uses constants to represent values.First the program calcu-
lates a players score,and then it calculates the upgrade cost ofa unit in a strategy game.
Figure 1.8 shows the results.
Working with Constants
Figure 1.8
Each calculation involves a constant,making the code behind the scenes clearer.
Q:Why does the
function ofa program return an
A:Because thats what the ISO standard says it should do.Actually,you can return a
to indicate an abnormal program exit,but this is rarely done in
practice.
Q:What are literals?
A:Elements that represent explicit values.
is a string literal,while
are numeric literals.
Q:Why should I always try to initialize a new variable with a value?
A:Because the contents ofan uninitialized variable could be any value„even one
that is legal but doesnt make sense for your program.
Types, Variables, and Standard I/O: Lost Fortune
is an object,defined in the file
,thats used to send data to the stan-
dard output stream (generally the computer screen).
is an object,defined in the file
multiplication,and division„and even the unfamiliar modulus.
C++ defines fundamental types for Boolean,single-character,integer,and floating
The C++ standard library provides a type ofobject (
) for strings.
You can use
to create a new name for an existing type.
A constant is a name for an unchangeable value.
An enumeration is a sequence of
constants.
Q:Why do game companies use C++?
cout leaving just  survivors  in the group.\nŽ;
cout \nThe party was about to give up all hope. ;
cout But while laying the deceased to rest, ;
cout they stumbled upon the buried fortune. ;
cout  pieces to keep things fair of course.\nŽ;
Types, Variables, and Standard I/O: Lost Fortune
This simple use of
this way,but be aware of its limitations.
Telling the Story
Next I use the variables to tell the story.
Okay,its time to put the concepts oftrue and false to work.You can use an
statement
to test an expression for truth and execute some code based on it.Heres a simple form of
statement:
,then
is executed.Otherwise,
program branches to the statement after the
suite.
like in the preceding code example,you can replace it with
Introducing the Score Rater Program
The Score Rater program comments on a players score using an
statement.Figure 2.1
shows the program in action.
Truth, Branching, and the Game Loop: Guess My Number
Table 2.1
OperatorMeaningSample ExpressionEvaluates To
==equal to5 == 5true
5 == 8false
!=not equal to5 != 8true
5 != 5false
�greater than�8 5true
�5 8false
less than5 8true
8 5false
�=greater than or equal to�8 = 5true
�5 = 8false
=less than or equal to5 = 8true
8 = 5false
Truth, Branching, and the
Game Loop: Guess My
Number
Chapter 2
o far,the programs youve seen have been linear„each statement executes in order,
from top to bottom.However,to create interesting games,you need to write pro-
grams that execute (or skip) sections ofcode based on some condition.Thats the
main topic ofthis chapter.Specifically,youll learn to:
Understand truth (as C++ defines it)
Use
statements to branch to sections ofcode
Use
statements to select a section ofcode to execute
Use
loops to repeat sections ofcode
Generate random numbers
Understanding Truth
Truth is black and white,at least as far as C++ is concerned.You can represent true and
false with their corresponding keywords,
.You can store such a Boolean
value with a
variable,as you saw in Chapter 1.Heres a quick refresher:
This code creates two
variables,
Although the keywords
are handy,any expression or value can be inter-
This page intentionally
Exercises
1.Create a list ofsix legal variable names„three good and three bad choices.Explain
why each name falls into the good or bad category.
As a result of this code,
cause a compile error.
An
statement can cause a program to execute a statement or block ofstatements,
statements.When you write one
statement inside another,its called
nesting
.In the following code,the
statement that begins
is nested
statement that begins
is greater than
,the program enters the statement block and displays the
.Then,in the inner
statement,the program compares
to1000.Because
is greater than or equal to
,the program displays the
Then the program continues to the statement after
In general,you should try to limit your nesting to a few levels at most.
You can add an
clause to an
statement to provide code that will only be executed
ifthe tested expression is
.Heres the form ofan
statement that includes an
Truth, Branching, and the Game Loop: Guess My Number
The equal to relational operator is == (two equal signs in a row).Dont confuse it with = (one equal
sign),which is the assignment operator.
While its not illegal to use the assignment operator instead of the equal to relational operator,the
results might not be what you expect.Take a look at this code:
{
cout You scored at least 500.\nŽ;
cout You scored 1000 or more!\nŽ;
}
statement.If you were to do this,youd create an empty statement that would be paired with
statement,essentially rendering the
statement useless.Heres an example:
,I create an empty statement thats associated with the
statement.The preceding code is equivalent to:
All Ive done is play with the whitespace,which doesnt change the meaning of the code.Now the
problem should be clear.The
value and skips the next statement (the
empty statement).Then the program goes on its merry way to the statement after the
which displays the message,
Be on guard for this error.Its an easy one to make and because its not illegal,it wont produce a
compile error.
Truth, Branching, and the Game Loop: Guess My Number
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is score_rater.cpp.
Figure 2.1
statements.
The statement tests
,and
order.If
is equal to a value,then the program executes the corresponding
.When the program hits a
statement,it exits the
structure.If
doesnt match any value,then the statement associated with
is executed.
is optional.Ifyou leave out a
,however,the program will
continue through the remaining statements until it hits a
statement ends.Usually you want one
statement to end each
.And
although a
case isnt required,its usually a good idea to have one as a catchall.
Heres an example to cement the ideas.Suppose
is equal to
.The program
will first test
.Because theyre not equal,the program will continue.
Next,the program will test
.Because they are equal,the program
will execute
.Then the program will hit the
statement and exit the
structure.
You can use the
(or a value that can be treated as an
).A
statement wont work with any other type.
Introducing the Menu Chooser Program
The Menu Chooser program presents the user with a menu that lists three difficulty lev-
els and asks him to make a choice.Ifthe user enters a number that corresponds to a list-
ed choice,then he is shown a message confirming the choice.Ifthe user makes some other
choice,he is told that the choice is invalid.Figure 2.4 shows the program in action.
Truth, Branching, and the Game Loop: Guess My Number
At first glance,you might think that the message,
,will,always
be displayed.But in fact the code displays nothing because the
ed with
;it is associated with
.By adding a little whitespace,you can
see how the code really works.
I havent changed the meaning ofthe code (remember,whitespace is just a convenience
for us humans),but Ive made the meaning clearer.Because the outer
statement never
executes its body,no message is ever displayed.
However,I can solve the problem with a pair ofcurly braces.
As a result,the inner
tions:Mad Lib.ŽRight now,just think of scopes as little self-contained worlds.
You can use a
statement to create multiple branching points in your code.Heres a
generic form ofthe
statement:
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is score_rater2.cpp.
Truth, Branching, and the Game Loop: Guess My Number
is executed.Then the program skips
and exe-
cutes the statement following the
suite.If
is executed.After
Figure 2.2
If the user enters a score thats more than 500,he is congratulated.
Figure 2.3
If the user enters a score thats 500 or less,he is told he does not have bragging rights.
Youll notice that I had to initialize
before the loop because the variable is used in the
loop expression.Because a
loop evaluates its expressions before its
loop body
group ofstatements that repeat),you have to make sure that any variables in the expres-
sion have a value before the loop begins.
Like
Truth, Branching, and the Game Loop: Guess My Number
Figure 2.6
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is play_again.cpp.
Figure 2.5
break;
default:
cout You made an illegal choice.\nŽ;
}
Youll almost always want to end each case with a
Truth, Branching, and the Game Loop: Guess My Number
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is menu_chooser.cpp.
Figure 2.4
Looks like I took the easy way out.
Using the continue Statement to Jump Back to the Top of a Loop
Just before
is displayed,I included the lines:
statement means jump back to the top ofthe loop.ŽAt the top ofthe loop,
condition is tested and the loop is entered again ifits true.So when
to
Truth, Branching, and the Game Loop: Guess My Number
Table 2.2
OperatorDescriptionSample Expression
Logical NOT
{
int count = 0;
count += 1;
//end loop if count is greater than 10
�if (count 10)
break;
//skip the number 5
if (count == 5)
continue;
cout count endl;
}
Although a
as a main loop around the bulk of the code.
Using the break Statement to Exit a Loop
This is the exit condition I put in the loop:
is increased by 1 each time the loop body begins,it will eventually reach 11.
When it does,the
statement (which means break out ofthe loopŽ) is executed and
In this case,the loop is entered because
.But because
never changes,the loop will
never stop.As a result,the user will have to kill the running program to end it.The moral of this
story? Make sure that the expression of a loop can eventually become
Using break and continue Statements
Its possible to alter the behavior youve seen in loops.You can immediately exit a loop with
statement,and you can jump directly to the top ofa loop with a
state-
Truth, Branching, and the Game Loop: Guess My Number
Figure 2.7
The number 5 is skipped with a
statement,and the loop ends with a
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is play_again2.cpp.
in the real world
Ofcourse,the Designers Network program works for other users besides Sid Meier.
Through a series of
statements using the
operator,the program checks three differ-
Truth, Branching, and the Game Loop: Guess My Number
Table 2.3
Possible Login Combinations Using the AND Operator
username == S.MeierŽpassword == civilizationŽusername ==
password ==
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse
{
cout \nWhats up, Shigeru?Ž;
}
if (username == W.WrightŽ && password == thesimsŽ)
{
cout \nHow goes it, Will?Ž;
}
if (username == guestŽ || password == guestŽ)
{
cout \nWelcome, guest.Ž;
security = 1;
}
if (!security)
cout \nYour login failed.Ž;
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
Truth, Branching, and the Game Loop: Guess My Number
Figure 2.10
Looks like one of the elite logged in today.
Figure 2.8
Figure 2.9
contains (among other things) functions that deal with generating ran-
dom numbers.Because Ive included the file,Im free to call the functions it contains,
,which is exactly what I do in
As you learned in Chapter 1,functions are pieces ofcode that can do some work and
return a value.You call or invoke a function by using its name followed by a pair ofparen-
theses.Ifa function returns a value,you can assign that value to a variable.Thats what I
do here with my use ofthe assignment statement.I assign the value returned by
random number) to
The
erate,just send
Functions can also take values to use in their work.You provide these values by placing
Truth, Branching, and the Game Loop: Guess My Number
The code for the program is in the Chapter 2 folder on the CD-ROM that came with this
book;the file name is die_roller.cpp.
Figure 2.11
The die roll is based on a random number generated by the program.
Although you can use parentheses in a larger expression to change the way in which its evaluated,
„parentheses that dont change the value of the expres-
a call you,as the programmer,have to make.
Truth, Branching, and the Game Loop: Guess My Number
The logical NOT operator,
Table 2.4
Possible Login Combinations Using the OR Operator
username == guestŽpassword == guestŽusername == guestŽ
|| password ==
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse
Table 2.5
Possible Login Combinations Using the NOT Operator
security!security
truefalse
falsetrue
Updating the display.
In the majority ofgames,this process is the most taxing on
the computer hardware because it often involves drawing graphics.However,this
process can be as simple as displaying a line oftext.
Figure 2.13
I guessed the computers number in just three tries.
Heres an explanation ofthe parts ofthe game loop:
Truth, Branching, and the Game Loop: Guess My Number
Figure 2.12
The game loop describes a basic flow of events that fits just about any game.
In the preceding code,I used the function call
as an argument when calling
.This is perfectly fine because the value returned by
can be used by
In general,you can use a function call as an argument to another function as long as the
first function returns a value that will always be a valid argument for the second function.
In the function call
,I pass the function
.A call to
returns a number based
on the current time,which I pass to
,which seeds the random number generator.
After generating a random number,
always produce uniform results.Some numbers in the range might be more likely to appear than
others.However,this isnt a problem for simple games.
is a generalized representation ofthe flow ofevents in a game.The core of
the events repeats,which is why its called a loop.Although the implementation might be
quite different from game to game,the fundamental structure is the same for almost all
In this chapter,you should have learned the following concepts:
You can use the truth or falsity ofan expression to branch to (or skip) sections
ofcode.
You can represent truth and falsity with their keywords,
You can evaluate any value or expression for truth or falsity.
Truth, Branching, and the Game Loop: Guess My Number
because I plan to generate a random number.I include
want to seed the random number generator with the current time.
Next,I start the
Truth, Branching, and the Game Loop: Guess My Number
Figure 2.14
The game loop applied to
This page intentionally
Exercises
1.Rewrite the Menu Chooser program from this chapter using an enumeration to
represent difficulty levels.
2.Whats wrong with the following loop?
3.Write a new version ofthe Guess My Number program in which the player and the
computer switch roles.That is,the player picks a number and the computer must
Q:Whats a pseudorandom number?
A:A random number thats usually generated by a formula.As a result,a series of
pseudorandom numbers is not truly random,but good enough for most pur-
Q:Whats seeding a random number generator?
A:Its giving the random number generator a seed,such as an integer,which affects
the way the generator produces random numbers.Ifyou dont seed a random
number generator,it will produce the same series ofnumbers each time its run
from the beginning ofa program.
Q:Dont you always want to seed the random number generator before using it?
A:Not necessarily.You might want a program to produce the exact same sequence of
randomŽnumbers each time it runs for testing purposes,for example.
Q:How can I generate more truly random numbers?
Truth, Branching, and the Game Loop: Guess My Number
Q:Do you have to use the keywords
A:No,but its a good idea.Before the advent ofthe keywords
,pro-
grammers often used 1 to represent true and 0 to represent false.However,now
are available,its best to use them instead ofthe old-fashioned
Q:Can you assign a
,says
is to be incremented each time the loop body finishes.As a result,the loop
iter-
10 times„once for each ofthe values
through
.And during each iteration,the loop
body displays the value of
The next
loop counts from
down to
.The loop begins:
Here,
is initialized to
,and the loop continues as long as
is greater than or equal to
Each time the loop body finishes,
is decremented.As a result,the loop displays the val-
through
The next loop counts from
to
,by fives.The loop begins:
Here,
is initialized to
,and the loop continues as long as
is less than or equal to
.But
notice the action statement,
.This statement increases
by five each time the loop
body finishes.As a result,the loop displays the values
,and so on.The expres-
says to execute the loop body as long as
is less than or equal to
You can initialize a counter variable,create a test condition,and update the counter vari-
able with any values you want.However,the most common thing to do is to start the
counter at
and increment it by
after each loop iteration.
Finally,the caveats regarding infinite loops that you learned about while studying
loops apply equally well to
loops.Make sure you create loops that can end;otherwise,
youll have a very unhappy gamer on your hands.
You can use empty statements in creating your
loop,as I did in the following loop:
I used an empty statement for the initialization and action statements.Thats fine because
I declared and initialized
before the loop and incremented it inside the loop body.
This loop displays the same sequence ofintegers as the very first loop in the program.
Although the loop might look odd,its perfectly legal.
Different game programmers have different traditions.In the last chapter,you saw that you can cre-
Well,some programmers prefer to create these kinds of loops using a
.Because the test expression in this loop is the empty statement,the loop will continue
For Loops, Strings, and Arrays: Word Jumble
for (int i = 0; i = 50; i+=5)
cout i  ;
cout \n\nCounting with null statements:\nŽ;
cout count  ;
}
cout \n\nCounting with nested for loops:\nŽ;
const int ROWS = 5;
const int COLUMNS = 3;
for (int j = 0; j COLUMNS; ++j)
cout i ,Ž j  ;
cout endl;
}
If youre using an older compiler that doesnt fully implement the current C++ standard,when
loops in a scope.I cover the topic of scopes in Chapter 5,Functions:Mad Lib.Ž
loop counts from 0 to 9.The loop begins:
The initialization statement,
,declares
and initializes it to 0.The expression
says that the loop will continue as long as
.Lastly,the action statement,
loop body executes,just as in a
loop.If
,the program moves on to the
statement after the loop.If
,the program executes
.Next,
executed (which often involves incrementing a counter variable).The cycle repeats until
tests
,at which point the loop ends.
Introducing the Counter Program
The Counter program counts forward,backward,and by fives.It even counts out a grid
with rows and columns.It accomplishes all ofthis through the use of
loops.Figure 3.1
shows the program in action.
The code for the program is in the Chapter 3 folder on the CD-ROM that came with this
book;the file name is counter.cpp.
For Loops, Strings, and Arrays: Word Jumble
Figure 3.1
loops do all of the counting,while a pair of nested
For Loops, Strings, and
Arrays: Word Jumble
Chapter 3
ouve seen how to work with single values,but in this chapter youll learn how to
work with sequences ofdata.Youll learn more about
strings
„objects for sequences
ofcharacters.Youll also see how to work with sequences ofany type.And youll
discover a new type ofloop thats perfect for use with these sequences.Specifically,youll
learn to:
Use
loops to iterate over sequences
Use objects,which combine data and functions
Use
objects and their member functions to work with sequences of
characters
Use arrays to store,access,and manipulate sequences ofany type
accesses the objects
data member,while
objects
Although you cant make your own new types (like for an alien spacecraft) just yet,you
can work with previously defined object types.And thats next on the agenda.
Figure 3.3
objects are combined,changed,and erased through familiar opera-
member functions.
want to represent in games„such as,say alien spacecrafts„are objects.Theyre encapsu-
lated,cohesive things that combine qualities (such as an energy level) and abilities (for
example,firing weapons).Often it makes no sense to talk about the individual qualities
and abilities in isolation from each other.
For Loops, Strings, and Arrays: Word Jumble
Figure 3.2
This representation of the definition of an alien spacecraft says that
You can nest
loops by putting one inside the other.Thats what I did in the following
section ofcode,which counts out the elements ofa grid.The outer loop,which begins:
simply executes its loop body
(five) times.But it just so happens that theres another
loop inside this loop,which begins:
As a result,the inner loop executes in full for each iteration ofthe outer loop.In this case,
that means the inner loop executes
(three) times,for the
(five) times the outer
loop iterates,for a total of15 times.Specifically,heres what happens:
1.The outer
loop declares
and initializes it to
.Since
(five),
the program enters the outer loops body.
2.The inner loop declares
and initializes it to
.Since
(three),the
program enters its loop body,sending the values of
to
,which displays
3.The program reaches the end ofthe body ofthe inner loop and increments
to
Since
(three),the program executes the inner loops body
again,displaying
4.The program reaches the end ofthe inner loops body and increments
to
.Since
(three),the program executes the inner loops body again,
displaying
5.The program reaches the end ofthe inner loops body and increments
to
.This
time,however,
(three) and the inner loop ends.
6.The program finishes the first iteration ofthe outer loop by sending
to
ending the first row.
7.The program reaches the end ofthe outer loops body and increments
to
.Since
(five),the program enters the outer loops body again.
8.The program reaches the inner loop,which starts from the beginning once again,
by declaring and initializing
to
.The program goes through the process I
described in Steps 2 through 7,displaying the second row ofthe grid.This process
continues until all five rows have been displayed.
Again,the important thing to remember is that the inner loop is executed in full for each
iteration ofthe outer loop.
So far youve seen how to store individual pieces ofinformation in variables and how to
manipulate those variables using operators and functions.But most ofthe things you
The loop iterates through all ofthe valid positions of
.It starts with 0 and goes
through 11.During each iteration,a character ofthe
object is displayed with
in the real world
Iterating through a sequence is a powerful and often-used technique in games.You might,for exam-
ple,iterate through hundreds of individual units in a strategy game,updating their status and order.Or
,you can supply an optional argument that specifies a character number for the
program to start looking for the substring.The following line will start looking for the string literal
,which,just like
stores a sequence of
values.You can access any individual
value
by providing an index number with the subscripting operator (
).Thats what I do next.
\\ŽThe first element in a sequence is at position 0.In the previous statement,
is thecharacter G.And because counting begins at 0,the last character in the
objectis
,even though the
has 12 characters in it.
Not only can you access characters in a
with the subscripting operator,but
you can also reassign them.Thats what I do next.
I change the first character of
to the character L,which means
becomes
C++ compilers do not perform bounds checking when working with
you can crash your program,so take care when using the subscripting operator.
Iterating through string Objects
Given your new knowledge of
objects,its a snap to iterate through
the individual characters ofa
object.Thats what I do next.
For Loops, Strings, and Arrays: Word Jumble
Creating string Objects
is create three strings in three different ways:
In the first line ofthis group,I simply create the
using the assignment
operator,the same way youve seen for other variables.As a result,
Next,I create
by placing the
The code for the program is in the Chapter 3 folder on the CD-ROM that came with this
book;the file name is string_tester.cpp.
For Loops, Strings, and Arrays: Word Jumble
The preceding code declares an array
MAX_ITEMSstring
objects.(Because
,that means 10
You can initialize an array with values when you declare it by providing an
sequence of elements separated by commas and surrounded by curly braces.Heres an example:
ŽŽŽThe preceding code declares an array of
objects,
,that has a size of
The first three elements of the array are initialized to
,and
If you omit the number of elements when using an initializer list,the array will be created with a
size equal to the number of elements in the list.Heres an example:
ŽŽŽBecause there are three elements in the initializer list,the preceding line creates an array,
,that is three elements in size.Its elements are
,and
You index arrays much like you index
objects.You can access any individual ele-
ment by providing an index number with the subscripting operator (
).Next I add three items to the heros inventory using the subscripting operator.
Žinventory[numItems++] = armorŽ;inventory[numItems++] = shieldŽ;I start by defining
for the number ofitems the hero is carrying at the moment.
Next I assign
to position 0 ofthe array.Because I use the postfix increment opera-
tor,
is incremented after the assignment to the array.The next two lines add
to the array,leaving
at the correct value of
when the code finishes.
Now that the hero is stocked with some items,I display his inventory.
This should remind you ofstring indexing.The code loops through the first three ele-
,displaying each
object in order.
Next the hero trades his sword for a battle axe.I accomplish this through the following
{
const int MAX_ITEMS = 10;
int numItems = 0;
inventory[numItems++] = swordŽ;
cout Your items:\nŽ;
for (int i = 0; i numItems; ++i)
cout inventory[i] endl;
cout \nYou trade your sword for a battle axe.Ž;
cout inventory[i] endl;
cout \nThe item name  inventory[0]  has ;
For Loops, Strings, and Arrays: Word Jumble
While
objects provide a great way to work with a sequence ofcharacters,arrays
provide a way to work with elements ofany type.That means you can use an array to store
a sequence ofintegers for,say,a high-score list.But it also means that you can use arrays
to store elements ofprogrammer-defined types,such as a sequence ofitems that an RPG
character might carry.
Introducing the Heros Inventory Program
The Heros Inventory program maintains the inventory ofa hero from a typical RPG.As
in most RPGs,the hero is from a small,insignificant village,and his father was killed by
an evil warlord.(Whats a quest without a dead father?) Now that the hero has come of
age,its time for him to seek his revenge.
In this program,the heros inventory is represented by an array.The array is a sequence of
objects„one for each item in the heros possession.The hero trades and even finds
new items.Figure 3.4 shows the program in action.
The code for the program is in the Chapter 3 folder on the CD-ROM that came with this
book;the file name is heros_inventory.cpp.
Figure 3.4
The heros inventory is a sequence of
objects stored in an array.
member function removes a specified substring from a
object.One way
to call the member function is to specify the beginning position and the length ofthe sub-
string,as I did in this code:
The previous line removes the four-character substring starting at position 5.Because
,the member function removes the substring
and,as a result,
becomes
Another way to call
is to supply just the beginning position ofthe substring.This
removes all ofthe characters starting at that position number to the end ofthe
object.Thats what I do next.
This line removes all ofthe characters ofthe
object starting at position 4.Since
,the member function removes the substring
and,as a result,
becomes
Yet another way to call
is to supply no arguments,as I did in this code:
The previous line erases every character in
.As a result,
becomes the empty
string,which is equal to
member function returns a
ifthe
object is empty and
otherwise.I use
in the following code:
is equal to the empty string,
returns
,and the screen dis-
plays the message,
The stringfile from the standard library defines many other useful member functions for
objects.These include member functions for appending,copying,inserting,replacing,and swapping
objects.For a full listing of all stringmember functions,check out Appendix F on the CD-
ROM that came with this book,which documents the Standard Template Library.Look for the topic
For Loops, Strings, and Arrays: Word Jumble
The code for the program is in the Chapter 3 folder on the CD-ROM that came with this
book;the file name is tic-tac-toe_board.cpp.
You can concatenate
objects and C-style strings,but the result is always a
object (so the code
would produce an error).You can com-
pare
objects and C-style strings using the relational operators.And you can even
use C-style strings as arguments in
C-style strings have the same shortcomings as arrays.One ofthe biggest is that their
lengths are fixed.So the moral is:Use
objects whenever possible,but be prepared
to work with C-style strings ifnecessary.
As youve seen,sequences are great for games.You can use them in the form ofa string to
store a players name,or you can use them in the form ofany array to store a list ofitems
For Loops, Strings, and Arrays: Word Jumble
Figure 3.5
The tic-tac-toe board is represented by a two-dimensional array.
So what happens ifyou do attempt to access an array element outside the bounds ofthe
array? It depends,because youd be accessing some unknown part ofthe computers mem-
ory.At worst,ifyou attempt to assign some value to an element outside the bounds ofan
array you could cause your program to do unpredictable things,and it might even crash.
Testing to make sure that an index number is a valid array position before using it is called
.Its critical for you to perform bounds checking when theres a chance
that an index you want to use might not be valid.
Before
objects came along,C++ programmers represented strings with arrays of
characters terminated by a null character.These arrays ofcharacters are now called
C-style
strings
because the practice began in C programs.You can declare and initialize a C-style
string like you would any other array.
ŽC-style strings terminate with a character called the
null character
to signify their end.You
can write the null character as
.I didnt need to use the null character in the previous
code because it is stored at the end ofthe string for me.So technically,
ments.(However,functions that work with C-style strings will say that
,which makes sense and is in line with how
objects work.)
As with any other type ofarray,you can specify the array size when you define it.So
another way to declare and initialize a C-style string is
ŽThe previous code creates a C-style string that can hold 80 printable characters (plus its
terminating null character).
C-style strings dont have member functions.But the
file,which is part ofthe stan-
ŽThe previous code reassigns the element at position 0 in
.Now the first three elements of
are
,and
Array indexing begins at 0,just as you saw with
objects.This means that the following code
defines a five-element array.
Valid position numbers are 0 through 4,inclusive.There is no element
! An attempt
could lead to disastrous results,including a program crash.
You can access the member functions ofan array element by writing the array element,
followed by the member selection operator,followed by the member function name.This
sounds a bit complicated,but its not.Heres an example:
For Loops, Strings, and Arrays: Word Jumble
jumble[index1] = jumble[index2];jumble[index2] = temp;}In the preceding code,I created a copy ofthe word
to...well,jumble.I generated
two random positions in the
object and swapped the characters at those positions.
I did this a number oftimes equal to the length ofthe word.
Welcoming the Player
Now its time to welcome the player,which is what I do next.
As enthralling as you think your game is,you should always provide a way for the player to exit it.
Next,I enter the game loop.
The loop continues to ask the player for a guess until the player either guesses the word or
asks to quit.
Introducing Word Jumble
{
enum fields {WORD, HINT, NUM_FIELDS};
You can list a final enumerator in an enumeration as a convenient way to store the number of ele-
ments.Heres an example:
In the previous code,
,the exact number of difficulty levels in the enumera-
tion.As a result,the second line of code displays the message,
Next,I pick a random word from my choices.
string theHint = WORDS[choice][HINT]; // hint for wordI generate a random index based on the number ofwords in the array.Then I assign both
the random word at that index and its corresponding hint to the variables
Jumbling the Word
Now that I have the word for the player to guess,I need to create a jumbled version ofit.
For Loops, Strings, and Arrays: Word Jumble
in the real world
Even though puzzle games dont usually break into the top-ten list of games,major companies still
publish them year after year.Why? For one simple reason:Theyre profitable.Puzzle games,while not
usually blockbusters,can still sell well.There are many gamers out there (casual and hardcore) who
are drawn to the Zen of a well-designed puzzle game.And puzzle games cost much less to produce
than the high-profile games that require large production teams and years of development time.
Introducing Word Jumble
Figure 3.6
Hmm...the word looks jumbled.Ž
The preceding code declares a 3
3 (since
are both three) two-dimen-
sional character array.It also initializes all ofthe elements.
Its possible to simply declare a multidimensional array without initializing it.Heres an example:
The preceding code declares an 8
8,two-dimensional character array,
.By the way,
multidimensional arrays arent required to have the same size for each dimension.The following is
a perfectly valid declaration for a game map represented by individual characters:
For Loops, Strings, and Arrays: Word Jumble
1.What are some ofthe things from your favorite game that you could represent as
objects? What might their data members and member functions be?
2.What are the advantages ofusing an array over using a group ofindividual
variables?
3.What are some limitations imposed by a fixed array size?
4.What are the advantages and disadvantages ofoperator overloading?
5.What kinds ofgames could you create using
objects,arrays,and
your main tools?
Exercises
1.Improve the Word Jumble game by adding a scoring system.Make the point value
for a word based on its length.Deduct points ifthe player asks for a hint.
2.Whats wrong with the following code?
3.Whats wrong with the following code?
Q:Should I ever use C-style strings?
A:You should opt for
objects whenever possible.Ifyoure working on an
existing project that uses C-style strings,then you might have to work with C-
style strings.
Q:What is operator overloading?
A:Its a process that allows you to define the use offamiliar operators in different
contexts with different but predictable results.For example,the
operator that is
used to add numbers is overloaded by the
type to join strings.
Q:Cant operator overloading be confusing?
A:Its true that by overloading an operator you give it another meaning.But the new
meaning applies only in a specific new context.For example,its clear in the
expression
operator adds numbers,while in the expression
,the
operator joins strings.
Q:Can I use the
operator to concatenate strings?
A:Yes,the
operator is overloaded so it works with strings.
For Loops, Strings, and Arrays: Word Jumble
C-style strings are character arrays terminated with the null character.They are the
standard way to represent strings in the C language.And even though C-style
strings are perfectly legal in C++,
objects are the preferred way to work
with sequences ofcharacters.
Multidimensional arrays allow for access to array elements using multiple sub-
scripts.For example,a chessboard can be represented as a two-dimensional array,
When the loop ends,the player has either won or quit,so its time to say goodbye.
For Loops, Strings, and Arrays: Word Jumble
The code for the program is in the Chapter 4 folder on the CD-ROM that came with this
book;the file name is heros_inventory2.cpp.
Using Vectors
The algorithms defined in the STL work with its containers.The
algorithms
are common
functions that game programmers find themselves repeatedly applying to groups ofval-
ues.They include algorithms for sorting,searching,copying,merging,inserting,and
removing container elements.The cool thing is that the same algorithm can work its
magic on many different container types.
Iterators
are objects that identify elements in containers and can be manipulated to move
among elements.Theyre great for,well,iterating through containers.In addition,itera-
tors are required by the STL algorithms.
All ofthis makes a lot more sense when you see an actual implementation ofone ofthe
container types,so thats up next.
Using Vectors
The Standard Template Library: Hangman
Figure 4.1
This time the heros inventory is represented by a vector.
The Standard Template
Library: Hangman
Chapter 4
o far youve seen how to work with sequences ofvalues using arrays.But there are
more sophisticated ways to work with collections ofvalues.In fact,working with col-
lections is so common that part ofstandard C++ is dedicated to doing just that.In
This page intentionally
Figure 4.2
The program performs a few vector manipulations that you can accomplish only with iterators.
Again,just as with arrays,I use the subscripting operator to assign a new value to an exist-
Although vectors are dynamic,you cant increase a vectors size by applying the subscripting oper-
The Standard Template Library: Hangman
The preceding code declared a vector with a size of 10 and initialized all 10 elements to
Finally,you can declare a vector and initialize it with the contents of another vector.
The preceding code created a new vector with the same contents as the vector
Next I give the hero the same three starting items as in the previous version ofthe pro-
gram.
member function adds a new element to the end ofa vector.In the pre-
ceding lines I added
,and
to
.As a result,
isequal to
is equal to
,and
is equal to
Next I display the number ofitems the hero has in his possession.
Using Vectors
There are additional ways to declare a vector.You can declare one with a starting size by specify-
ing a number in parentheses after the vector name.
The preceding code declared a vector to hold
object elements with a starting size of 10.You
can also initialize all of a vectors elements to the same value when you declare it.You simply sup-
ply the number of elements followed by the starting value,as in:
The Standard Template Library: Hangman
The code for the program is in the Chapter 4 folder on the CD-ROM that came with this
book;the file name is heros_inventory3.cpp.
The Standard Template Library: Hangman
the computer,but the second is easier for humans to use.In general,you can use the
operator to access the member functions or data members ofan object that an iterator
references.
Next I add a new item to the heros inventory.This time,though,I dont add the item to
the end ofthe sequence;instead,I insert it at the beginning.
One form ofthe
member function inserts a new element into a vector just before
the element referred to by a given iterator.You supply two arguments to this version of
„the first is an iterator,and the second is the element to be inserted.In this case,
I inserted
into
just before the first element.As a result,all ofthe other
elements will move down by one.This version ofthe
member function returns
an iterator that references the newly inserted element.In this case,I dont assign the
returned iterator to a variable.
member function on a vector invalidates all of the iterators that reference ele-
down by one.
Next I show the contents ofthe vector to prove the insertion worked.
Next I remove an item from the heros inventory.However,this time I dont remove the
item at the end ofthe sequence;instead,I remove one from the middle.
One form ofthe
member function removes an element from a vector.You supply
one argument to this version of
„the iterator that references the element you want
to remove.In this case,I passed
,which is equal to the iterator that
references the third element in
.This removes the
object equal to
Changing the Value of a Vector Element
Next I change the first element in the vector from the
object equal to
to the
object equal to
Whenever you dereference an iterator to access a data member or member function,surround the
dereferenced iterator with a pair of parentheses.This ensures that the dot operator will be applied
to the object the iterator references.
The code
The Standard Template Library: Hangman
In the test statement ofthe loop,I test the return value of
make sure the two are not equal.The
member function returns an iterator one past
the last element in a container.This means the loop will continue until
has moved
through all ofthe elements in
.Figure 4.4 shows an abstract view ofthe iterator
returned by a call to this member function.(Note that the figure is abstract because the
vector
doesnt contain the string literals
,and
;it con-
The
end()vector
might seem counterintuitive,but it works well for loops that move through a container.
The action statement in the loop,
,increments
,which moves it to the next ele-
ment in the vector.Depending upon the iterator,you can perform other mathematical
operations on iterators to move them around a container.Most often,though,youll find
that you simply want to increment an iterator.
In the loop body,I send
to
.By placing the dereference operator (
) in front of
,I display the value ofthe element to which the iterator refers (not the iterator itself).
By placing the dereference operator in front ofan iterator,youre saying,Treat this as the
thing that the iterator references,not as the iterator itself.Ž
Figure 4.4
might invalidate all iterators referencing the vector.
Is all ofthis iterator talk a little too abstract for you? Are you tired ofanalogies about Post-
it notes? Fear not„next,I put an actual iterator to work.
Looping through a Vector
Next I loop through the contents ofthe vector and display the heros inventory.
In the preceding code,I used a
loop to move from the first to the last element of
.At this general level,this is exactly how I looped through the contents ofthe vector
in Heros Inventory 2.0.But instead ofusing an integer and the subscripting operator to
access each element,I used an iterator.Basically,I moved the Post-it note through the
entire sequence ofelements and displayed the value ofeach element to which the note is
stuck.There are a lot ofnew ideas in this little loop,so Ill tackle them one at a time.
In the initialization statement ofthe loop,I assign the return value of
.The
member function returns an iterator that refers to a containers first ele-
ment.So in this case,the statement assigns an iterator that refers to the first element of
object equal to
) to
.Figure 4.3 shows an abstract view of
the iterator returned by a call to
.(Note that the figure is abstract because
the vector
doesnt contain the string literals
,and
;it con-
The Standard Template Library: Hangman
Figure 4.3
Next I sort the scores.
algorithm sorts the elements ofa sequence in ascending order.You must sup-
ply as iterators the starting and ending points ofthe sequence to sort.In this particular
case,I passed the iterators returned by
.These two iterators
indicate that I want to sort all ofthe elements in
.As a result,
contains all of
the scores in ascending order.
Next I display the scores to prove the sorting worked.
Next I prepare to use the
algorithm to combine two vectors that contain high
scores.First,I create a new vector named
,which contains three additional
scores.Then I create an empty vector with a size of
to hold the results
ofthe merge.Finally,I merge the vectors
and place the resulting
sequence in
algorithm combines two sorted sequences into another sorted sequence.An
iterator to the resulting sequence is returned.The algorithm requires the beginning and
ending points ofthe two sequences to be merged and the beginning point ofthe resulting
sequence.The resulting container must be large enough to accommodate the merged
sequence.
In this case,I passed the iterators returned by
,followed by
,to indicate that I want to merge the entire
sequence ofelements in
with the entire sequence ofelements in
.I passed
to indicate that I want the results put in
,starting at the begin-
ning position ofthe vector.
The container you specify to hold the results of
of the elements in the newly merged sequence.
does not increase the size of the container.
&#xint0;vectorint allScores(6); //need container big enough to hold results
moreScores.begin(), moreScores.end(),
cout \nAll High Scores:\nŽ;
cout *iter endl;
Although you might not want to randomize a list of high scores,
is a valuable
algorithm for games.You can use it for everything from shuffling a deck of cards to mixing up the
The Standard Template Library: Hangman
The code for the program is in the Chapter 4 folder on the CD-ROM that came with this
book;the file name is high_scores.cpp.
As a result,all ofthe following elements will move up by one.This version ofthe
member function returns an iterator that references the element after the element that was
removed.In this case,I dont assign the returned iterator to a variable.
member function on a vector invalidates all of the iterators that reference elements
after the removal point because all of the elements after the removal point are shifted up by one.
Next I show the contents ofthe vector to prove the removal worked.
The STL defines a group ofalgorithms that allow you to manipulate elements in contain-
ers through iterators.Algorithms exist for common tasks such as searching,sorting,and
copying container elements.These algorithms are your built-in arsenal offlexible and effi-
cient weapons.By using them,you can leave the mundane task ofmanipulating container
elements in common ways to the STL so you can concentrate on writing your game.The
powerful thing about these algorithms is that they are generic„the same algorithm can
work with elements ofdifferent container types.
Introducing the High Scores Program
The High Scores program creates a vector ofhigh scores.It uses STL algorithms to ran-
domize and then sort the scores.Then the program creates another vector ofscores and
merges the two„again with an algorithm.Figure 4.5 illustrates the program.
The Standard Template Library: Hangman
Figure 4.5
randomize,sort,
scores.
Planning Your Programs
Planning Your Programs
Table 4.1
ContainerTypeDescription
SequentialDouble-ended queue
SequentialLinear list
AssociativeCollection of key/value pairs in which each key is associated
with exactly one value
AssociativeCollection of key/value pairs in which each key may be
associated with more than one value
The Standard Template Library: Hangman
Right after I declare and initialize the vector,this code reports that its size and capacity are
both 10.However,after an element is added,the code reports that the vectors size is 11
while its capacity is 20.Thats because the capacity ofa vector doubles every time a pro-
gram reallocates additional memory for it.In this case,when a new score was added,
memory was reallocated and the capacity ofthe vector doubled from 10 to 20.
member function increases the capacity ofa vector to the number supplied
as an argument.Using
gives you control over when a reallocation ofadditional
memory occurs.Heres an example:
Right after I declare and initialize the vector,this code reports that its size and capacity are
both 10.However,after I reserve memory for 10 additional elements,the code reports that
the vectors size is still 10 while its capacity is 20.
By using
to keep a vectors capacity large enough for your purposes,you can
delay memory reallocation to a time ofyour choosing.
As a beginning game programmer,its good to be aware of how vector memory allocation works;
however,dont obsess over it.The first game programs youll write probably wont benefit from a
Understanding Vector Performance
A very cool property of STL algorithms is that they can work with containers defined outside of the
s„because theyre designed to.
Understanding Vector Performance
Like all STL containers,vectors provide game programmers with sophisticated ways to
work with information,but this level ofsophistication can come at a performance cost.
And iftheres one thing game programmers obsess about,its performance.But fear not,
vectors and other STL containers are incredibly efficient.In fact,theyve already been used
in published PC and console games.However,these containers have their strengths and
weaknesses;a game programmer needs to understand the performance characteristics of
the various container types so that he can choose the right one for the job.
Examining Vector Growth
Although vectors grow dynamically as needed,every vector has a specific size.When a new
element added to a vector pushes the vector beyond its current size,the computer reallo-
cates memory and might even copy all ofthe vector elements to this newly seized chunk
ofmemory real estate.This can cause a performance hit.
The Standard Template Library: Hangman
Next I enter the main loop,which continues until the player has made too many incorrect
guesses or has guessed the word.
The Standard Template Library: Hangman
Before I write a single line in C++,I plan the game program using pseudocode.
Figure 4.6
The Hangman game in action
Even though anyone,even a non-programmer,can understand my plan,my pseudocode
feels vaguely like a program.The first four lines resemble an
statement with an
clause,and thats intentional.When you write your plan,you should try to incorporate the
feel ofthe code that youre representing with pseudocode.
Your programming plan might not be finished after only one draft.Often pseudocode
needs multiple passes before it can be implemented in programming code.
Stepwise refine-
ment
is one process used to rewrite pseudocode to make it ready for implementation.
The Standard Template Library: Hangman
Exercises
1.Write a program using vectors and iterators that allows a user to maintain a list of
his or her favorite games.The program should allow the user to list all game titles,
add a game title,and remove a game title.
2.Assuming that
is a vector that holds elements oftype
,whats wrong with
Q:Why does the STL define more than one sequential container type?
A:Different sequential container types have different performance properties.
Theyre like tools in a toolbox;each tool is best suited for a different job.
Q:What are container adaptors?
A:Container adaptors are based on one ofthe STL sequence containers;they repre-
sent standard computer data structures.Although they are not official containers,
they look and feel just like them.
Q:Whats a stack?
A:A data structure in which elements are removed in the reverse order from how
they were added.This means that the last element added is the first one removed.
This is just like a real-life stack,from which you remove the last item you placed
on the top ofthe stack.
Q:Whats a queue?
A:A data structure in which elements are removed in the same order in which they
were added.This is just like a real-life queue,such as a line ofpeople in which the
The Standard Template Library: Hangman
Its very efficient to iterate through a vector.Its also very efficient to insert or
remove an element from the end ofa vector.
The Standard Template Library: Hangman
Before you can call a function youve written,you have to declare it.One way to declare a
function is to write a
function prototype
„code that describes the function.You write a
prototype by listing the return value ofthe function (or
ifthe function returns no
Although you dont have to use prototypes,they offer a lot of benefits„not the least of which is
making your code clearer.
Defining functions means writing all the code that makes the function tick.You define a
function by listing the return value ofthe function (or
ifthe function returns no
like a program you could have written way back in Chapter 1.But this program has a fresh
element working behind the scenes„a new function.Take a look at Figure 5.1 to see the
modest results ofthe code.
The code for the program is in the Chapter 5 folder on the CD-ROM that came with this
book;the file name is instructions.cpp.
Figure 5.1
The instructions are displayed by a function.
Functions: Mad Lib
Chapter 5
very program youve seen so far has consisted ofone function„
.However,
once your programs reach a certain size or level ofcomplexity,it becomes hard to
work with them like this.Fortunately,there are ways to break up big programs into
smaller,bite-sized chunks ofcode.In this chapter,youll learn about one way„creating
new functions.Specifically,youll learn to:
Write new functions
This page intentionally
makes your code clearer,and its worth the minor effort.
Introducing the Yes or No Program
The Yes or No program asks the user typical questions a gamer might have to answer.First,
Figure 5.2
generate a compile error.
You call your own functions the same way you call any other function„by writing the
functions name followed by a pair ofparentheses that encloses a valid list ofarguments.
In
,I call my newly minted function simply with:
This line invokes
.Whenever you call a function,control ofthe program
jumps to that function.In this case,it means control jumps to
and the pro-
gram executes the functions code,which displays the game instructions.When a function
finishes,control returns to the calling code.In this case,it means control returns to
The next statement in
void func();
int main()
{
int var = 5; // local variable in main()
func();
cout Back in main() var is:  var \n\nŽ;
{
cout In main() in a new scope var is:  var \n\nŽ;
cout Creating new var in new scope.\nŽ;
int var = 10; // variable in new scope, hides other variable named var
cout In main() in a new scope var is:  var \n\nŽ;
}
cout At end of main() var created in new scope no longer exists.\nŽ;
cout At end of main() var is:  var \nŽ;
Working with Scopes
You can reuse code youve written by copying from one program and pasting it into
Figure 5.3
Even though they have the same name,all three variables have a unique exis-
tence in their own scopes.
in the real world
Its always a waste of time to reinvent the wheel,so
„employing existing software
and other elements in new projects„is a technique that game companies take to heart.The ben-
efits of software reuse include
Increased company productivity.
them from reinventing a less efficient one.
From the header of
,you can see that the function accepts a
function definition.If they dont,youll generate a nasty compile error.
Actually,theres a little more going on behind the scenes here.When the string literal
,a
void hide_global();
int main()
{
cout In main() glob is:  glob \n\nŽ;
hide_global();
cout In main() glob is:  glob \n\nŽ;
change_global();
cout In main() glob is:  glob \n\nŽ;
Using Global Variables
Using Global Variables
Through the magic ofencapsulation,the functions youve seen are all totally sealed off
Figure 5.4
You can access and change global variables from anywhere in a program„but
This new scope is a nested scope in
.The first thing I do in this nested scope is dis-
play
.Ifa variable hasnt been declared in a scope,the computer looks up the levels
ofnested scopes one at a time to find the variable you requested.In this case,because
hasnt been declared in this nested scope,the computer looks one level up to the scope that
.As a result,the program displays that variables value„
However,the next thing I do in this nested scope is declare a new variable named
initialize it to 10.Now when I send
to
is displayed.This time the computer
doesnt have to look up any levels ofnested scopes to find
;theres a
local to this
scope.And dont worry,the
I first declared in
still exists;its simply hidden in
this nested scope by the new
Although you can declare variables with the same name in a series of nested scopes,its not a good
Next,when the nested scope ends,the
that was equal to
goes out ofscope and ceases
to exist.However,the first
I created is still around,so when I display
with the following line,the program displays
When you define variables inside
loops,
loops,
statements,and
statements,
these variables dont exist outside their structures.They act like variables declared in a nested
scope.For example,in the following code,the variable
doesnt exist outside the loop.
But beware„some older compilers,such as Microsoft Visual C++ 6.0,dont properly implement
I recommend that you use an IDE with a modern compiler,such as Dev-C++,which is on the CD-
ROM that came with this book.After you install Dev-C++,check out Appendix A,Creating Your
Working with Scopes
This works just as youd expect„
is displayed.
Next I call
.Once I enter the function,Im in a separate scope outside ofthe scope
defined by
.As a result,I cant access the variable
.This
means that when I next define a variable named
with the following line,this
int main()
{
int number = askNumber(5);
number = askNumber(10, 5);
cout Thanks for entering:  number \n\nŽ;
default argument
Figure 5.5
for a number.
Then,back in
,I send
to
with:
Because the global variable
was changed,
is displayed.
Minimizing the Use of Global Variables
Just because you can doesnt mean you should.This is a good programming motto.
Just like with global variables,you can hide a global constant by declaring a local constant with the
same name.However,you should avoid this because it can lead to confusion.
How exactly can global constants make game programming code clearer? Well,suppose
youre writing an action game in which you want to limit the total number ofenemies that
can blast the poor player at once.Instead ofusing a numeric literal everywhere,such as
you could define a global constant
thats equal to
.Then whenever you see
that global constant name,you know exactly what it stands for.
One caveat:You should only use global constants ifyou need a constant value in more
than one part ofyour program.Ifyou only need a constant value in a specific scope (such
as in a single function),use a local constant instead.
The program displays
because as a global variable,
is available to any part ofthe
program.To show this again,I next call
,and the computer executes the
following code in that function.
Again,
is displayed.That makes sense because Im displaying the exact same variable in
each function.
Hiding Global Variables
You can hide a global variable like any other variable in a scope;you simply declare a new
variable with the same name.Thats exactly what I do next,when I call
.The
key line in that function doesnt change the global variable
;instead,it creates a new
variable named
,local to
,that hides the global variable.
As a result,when I send
to
next in
with the following line,
played.
The global variable
remains hidden in the scope of
To prove that the global variable was only hidden and not changed,next I display
with:
Once again,
is displayed.
Although you can declare variables in a function with the same name as a global variable,its not
Altering Global Variables
Just as you can access a global variable from anywhere in your program,you can alter one
from anywhere in your program,too.Thats what I do next,when I call the
function.The key line ofthe function assigns
to the global variable
To show that it worked,I display the variable in
with:
string triple(string text);
int main()
{
cout Tripling 5:  triple(5) \n\nŽ;
cout Tripling gamer:  triple(gamerŽ);
To implement function overloading,you need to write multiple definitions for the same function
Figure 5.6
Function overloading allows you to triple the values of two different types using
the same function name.
By the way,you dont repeat the default argument in the function definition,as you can
When you are calling a function with default arguments,once you omit an argument,you
The code for the program is in the Chapter 5 folder on the CD-ROM that came with this
book;the file name is mad_lib.cpp.
Figure 5.8
After the user provides all of the necessary information,the program displays the
literary masterpiece.
When you inline a function,you really make a request to the compiler,which has the ultimate deci-
formance,it wont inline the function.
Calling an inlined function is no different than calling a non-inlined function,as you see
with my first call to
This line ofcode assigns
one halfofits original value.
Assuming that the compiler grants my request for inlining,this code doesnt result in a
function call.Instead,the compiler places the code to halve
right at this place in the
program.In fact,the compiler does this for all three calls to the function.
in the real world
Although obsessing about performance is a game programmers favorite hobby,theres a danger in
Introducing the Mad Lib Game
The Mad Lib game asks for the users help in creating a story.The user supplies the name
ofa person,a plural noun,a number,and a verb.The program takes all ofthis informa-
tion and uses it to create a personalized story.Figure 5.8 shows a sample run ofthe
program.
The code for the program is in the Chapter 5 folder on the CD-ROM that came with this
book;the file name is taking_damage.cpp.
You can call an overloaded function the same way you call any other function,by using its
Figure 5.7
The character
Q:What does it mean to hide a variable?
A:A variable is hidden when you declare it inside a new scope with the same name
Defining a function means writing all the code that makes the function tick.
You can use the
{
int num;
{
cout Welcome to Mad Lib.\n\nŽ;
string name = askText(Please enter a name: );
string noun = askText(Please enter a plural noun: );
string verb = askText(Please enter a verb: );
tellStory(name, noun, number, bodyPart, verb);
(such as tabs or spaces).So when a user is prompted for a body part,he can enter
itations.
The code for the program is in the Chapter 6 folder on the CD-ROM that came with this
book;the file name is referencing.cpp.
References: Tic-Tac-Toe
Figure 6.1
The variable
single score value.
References: Tic-Tac-Toe
Chapter 6
he concept ofreferences is simple,but its implications are profound.In this chap-
ter,youll learn about references and how they can help you write more efficient
game code.Specifically,youll learn to:
Create references
Access and change referenced values
Pass references to functions to alter argument values or for efficiency
Return references from a function for efficiency or to alter values
Using References
eference
provides another name for a variable.Whatever you do to a reference is done
to the variable to which it refers.You can think ofa reference as a nickname for a vari-
able„another name that the variable goes by.In the first program in this chapter,Ill
show you how to create references.Then,in the next few programs,Ill show you why
youd want to use references and how they can improve your game programs.
Introducing the Referencing Program
The Referencing program demonstrates references.The program declares and initializes a
variable to hold a score and then creates a reference that refers to the variable.The pro-
gram displays the score using the variable and the reference to show that they access the
same single value.Next,the program shows that this single value can be altered through
either the variable or the reference.Figure 6.1 illustrates the program.
This page intentionally
Exercises
1.Whats wrong with the following prototype?
2.Rewrite the Hangman game from Chapter 4 using functions.Include a function to
{
int myScore = 150;
cout Calling badSwap()\nŽ;
badSwap(myScore, yourScore);
cout Calling goodSwap()\nŽ;
goodSwap(myScore, yourScore);
References: Tic-Tac-Toe
variable safe and unalterable.But other times you might want to change an argument
variable from inside the function to which it was passed.You can accomplish this by using
references.
Introducing the Swap Program
The Swap program defines two variables„one that holds my pitifully low score and
another that holds your impressively high score.After displaying the scores,the program
calls a function meant to swap the scores.But because only copies ofthe score values are
sent to the function,the argument variables that hold the scores are unchanged.Next,the
program calls another swap function.This time,through the use ofreferences,the argu-
ment variablesvalues are successfully exchanged„giving me the great big score and leav-
ing you with the small one.Figure 6.2 shows the program in action.
The code for the program is in the Chapter 6 folder on the CD-ROM that came with this
book;the file name is referencing.cpp.
Figure 6.2
Passing references allows
to alter the argument variables.
Both lines ofcode display
because they each access the same single chunk ofmemory
that stores the number
.Remember,there is only one value,and it is stored in the
variable
A reference always refers to the variable with which it was initialized.You cant reassign a refer-
ence to refer to another variable so,for example,the results of the following code might not be
obvious.
The line
because a reference cant be reassigned.However,because
,the code
is equivalent to
.And after all is said and done,
Passing References to Alter Arguments
Now that youve seen how references work,you might be wondering why youd ever use
them.Well,references come in quite handy when you are passing variables to functions
References: Tic-Tac-Toe
Creating References
is create a variable to hold my score.
Then I create a reference that refers to
The preceding line declares and initializes
,a reference that refers to
does not hold its own
value;its simply
One way to understand references is to think ofthem as nicknames.For example,suppose
youve got a friend named Eugene,and he (understandably) asks to be called by a nick-
name„Gibby (not much ofan improvement,but its what Eugene wants).So when youre
at a party with your friend,you can call him over using either Eugene or Gibby.Your
friend is only one person,but you can call him using either his name or a nickname.This
Because a reference must always refer to another value,you must initialize the reference when you
Accessing Referenced Values
Next I send both
to
the function read-only access to the argument.Although constant references are very use-
A constant reference comes in handy in another way.If you need to assign a constant value to a
reference,you have to assign it to a constant reference.(A non-constant reference wont do.)
Passing a Constant Reference
,I create
with the following line,which
passes the vector as a constant reference.
This results in an efficient and safe function call.Its efficient because only a reference is
passed;the vector is not copied.Its safe because the reference to the vector is a constant
reference;
cant be changed by
compile error.
Next,
lists the elements in the vector using a constant reference to
Then control returns to
and the program ends.
At this point youve seen three different ways to pass arguments„by value,as a reference,
References: Tic-Tac-Toe
inventory.push_back(shieldŽ);
display(inventory);
In general,you should avoid changing an argument variable.Try to write functions that send back
Passing References for Efficiency
Introducing the Inventory Displayer Program
The Inventory Displayer program creates a vector ofstrings that represents a heros inven-
tory.The program then calls a function that displays the inventory.The program passes
the displayer function the vector ofitems as a reference,so its an efficient call;the vector
isnt copied.However,theres a new wrinkle.The program passes the vector as a special
kind ofreference that prohibits the displayer function from changing the vector.Figure
6.3 shows you the program.
The code for the program is in the Chapter 6 folder on the CD-ROM that came with this
book;the file name is inventory_displayer.cpp.
References: Tic-Tac-Toe
Figure 6.3
The vector
is passed in a safe and efficient way to the function
that displays the heros items.
with the following line,copies of
Passing References for Efficiency
The preceding code doesnt assign a reference to
.It cant,because
Instead,the code copies the element to which the returned reference refers (the element
) and assigns that new copy ofthe
object to
.Because
this kind ofassignment involves copying an object,its more expensive than assigning one
References: Tic-Tac-Toe
Figure 6.5
The computer is full
of...confidence.
The body ofthe function
contains only one statement,which returns a ref-
erence to the element at position
in the vector.
{
&#xstri;&#xng00;vectorstring inventory;
References: Tic-Tac-Toe
Figure 6.4
board itselfcould be a vector of
s.There are nine squares on a Tic-Tac-Toe board,so
the vector should have nine elements.Each square on the board will correspond to an ele-
ment in the vector.Figure 6.6 illustrates what I mean.
Each square or position on the board is represented by a number,0…8.That means the
vector will have nine elements,giving it position numbers 0…8.Because each move indi-
cates a square where a piece should be placed,a move is also just a number,0…8.That
means a move could be represented as an
The side the player and computer play could also be represented by a
,just like a game piece.A variable to represent the side ofthe current turn would
,either an
The pseudocode inspires the different functions Ill need.I created a list ofthem,think-
References: Tic-Tac-Toe
Figure 6.6
Table 6.1
Tic-Tac-Toe Functions
FunctionDescription
Displays the game instructions.
Asks a yes or no question.Receives a question.
This game is your most ambitious project yet.You certainly have all the skills you need to
in the real world
Game designers work countless hours on concept papers,design documents,and prototypes before
programmers write any game code.Once the design work is done,the programmers start their
work„more planning.Its only after programmers write their own technical designs that they then
begin coding in earnest.The moral of this story? Plan.Its easier to scrap a blueprint than a 50-story
Its back to your favorite language thats not really a language„pseudocode.Because Ill
be using functions for most ofthe tasks in the program,I can afford to think about the
Introducing the Tic-Tac-Toe Game
This function asks for a number within a range and keeps asking until the player enters a
valid number.It receives a question,a high number,and a low number.It returns a num-
ber within the range specified.
References: Tic-Tac-Toe
}
announceWinner(winner(board), computer, human);
Introducing the Tic-Tac-Toe Game
In the global constants section,
is shorthand for the
charX
,one ofthe two pieces in the
represents the
charO
,the other piece in the game.
,also a
,represents
an empty square on the board.Its a space because when its displayed,it will look like an
empty square.
that represents a tie game.And
used to repre-
sent neither side ofthe game,which I use to indicate that no one has won yet.
As you can see,the
function is almost exactly the pseudocode I created earlier.
References: Tic-Tac-Toe
Introducing the Tic-Tac-Toe Game
Table 6.1
Tic-Tac-Toe Functions (continued)
FunctionDescription
Calculates the opposing piece given a piece.Receives
Instead,I choose to pass by value,even though its not as efficient as passing by reference.
I pass by value because I need to work with and modify a copy ofthe board as I place
References: Tic-Tac-Toe
This function receives a board and a move.It returns
ifthe move is a legal one on the
board or
ifthe move is not legal.A legal move is represented by the number ofan
empty square.
Introducing the Tic-Tac-Toe Game
In this initial section ofthe function,I define a constant,two-dimensional array of
References: Tic-Tac-Toe
Introducing the Tic-Tac-Toe Game
Q:How does passing a constant reference save overhead?
A:When you pass a large object to a function by value,your program makes a copy
ofthe object.This can be an expensive operation depending on the size ofthe
object.Passing a reference is like passing only access to the large object;it is an
inexpensive operation.
Q:Can I make a reference to a reference?
A:Not exactly.You can assign one reference to another reference,but the new refer-
ence will simply refer to the value to which the original reference refers.
Q:What happens ifI declare a reference without initializing it?
A:Your compiler should complain because its illegal.
Q:Why should I avoid changing the value ofa variable that I pass through a refer-
ence?
A:Because it could lead to confusion.Its impossible to tell from only a function call
References: Tic-Tac-Toe
Passing a reference provides direct access to the argument variable passed to a
function.As a result,the function can make changes to the argument variable.
A constant reference cant be used to change the value to which it refers.You
declare a constant reference by using the keyword
You cant assign a constant reference or a constant value to a non-constant
reference.
Passing a constant reference to a function protects the argument variable from
being changed by that function.
Changing the value ofan argument variable passed to a function can lead to con-
fusion,so game programmers consider passing a constant reference before passing
a non-constant reference.
Returning a reference can be more efficient than returning a copy ofa value,espe-
cially when you are returning large objects.
You can return a constant reference to an object so the object cant be changed
through the returned reference.
A basic technique ofgame AI is to have the computer consider all ofits legal
moves and all ofits opponents legal replies before deciding which move to
take next.
Q:Different programmers put the reference operator (
) in different places when
declaring a reference.Where should I put it?
A:Three basic styles exist with regard to using the referencing operator.Some pro-
grammers opt for
,while others opt for
.Still oth-
.The computer is fine with all three.There are cases to
be made for each style;however,the most important thing is to be consistent.
Q:Why cant I initialize a non-constant reference with a constant value?
A:Because a non-constant reference allows you to change the value to which it
refers.
Q:IfI initialize a constant reference with a non-constant variable,can I change the
value ofthe variable?
A:Not through the constant reference because when you declare a constant refer-
ence,youre saying that the reference cant be used to change the value to which it
refers (even ifthat value can be changed by other means).
In this chapter,you should have learned the following concepts:
A reference is an alias;its another name for a variable.
You create a reference using
„the referencing operator.
A reference must be initialized when its defined.
A reference cant be changed to refer to a different variable.
Whatever you do to a reference is done to the variable to which the reference
refers.
When you assign a reference to a variable,you create a new copy ofthe
referenced value.
When you pass a variable to a function by value,you pass a copy ofthe variable to
When you pass a variable to a function by reference,you pass access to the
variable.
Passing by reference can be more efficient than passing by value,especially when
you are passing large objects.
References: Tic-Tac-Toe
{
if (isLegal(move, board))
board[move] = human;
if (winner(board) == human)
{
cout move endl;
in the real world
The Tic-Tac-Toe game considers only the next possible move.Programs that play serious games of
strategy,such as chess,look far deeper into the consequences of individual moves and consider
many levels of moves and countermoves.In fact,good computer chess programs can consider lit-
erally millions of board positions before making a move.
This function receives the winner ofthe game,the computers piece,and the humans
piece.The function announces the winner or declares a tie.
Introducing the Tic-Tac-Toe Game
Introducing the Pointing Program
The Pointing program demonstrates the mechanics ofpointers.The program creates a
variable for a score and then creates a pointer to store the address ofthat variable.The
program shows that you can change the value ofa variable directly,and the pointer will
reflect the change.It also shows that you can change the value ofa variable through a
pointer.It then demonstrates that you can change a pointer to point to another variable
entirely.Finally,the program shows that pointers can work just as easily with objects.
Figure 7.1 illustrates the results ofthe program.
The code for the program is in the Chapter 7 folder on the CD-ROM that came with this
book;the file name is pointing.cpp.
Pointers: Tic-Tac-Toe 2.0
Figure 7.1
The pointer
first points to the variable
and then to the variable
,while the pointer
points to the variable
Pointers: Tic-Tac-Toe 2.0
Chapter 7
ointers are a powerful part ofC++.In some ways,they behave like iterators from
the STL.Often you can use them in place ofreferences.But pointers offer func-
tionality that no other part ofthe language can.In this chapter,youll learn the basic
Computer memory is a lot like a neighborhood,but instead of houses in which people store their
stuff,you have memory locations where you can store data.Just like a neighborhood where houses
sit side by side,labeled with addresses,chunks of computer memory sit side by side,labeled with
This page intentionally
Q:Whats wrong with returning a reference to a local variable?
A:The local variable doesnt exist once the function ends,which means that youre
returning a reference to a non-existent object,which is illegal.
1.What are the advantages and disadvantages ofpassing an argument by value?
2.What are the advantages and disadvantages ofpassing a reference?
3.What are the advantages and disadvantages ofpassing a constant reference?
4.What are the advantages and disadvantages ofreturning a reference?
5.Should game AI cheat in order to create a more worthy opponent?
Exercises
1.Improve the Mad Lib game from Chapter 5 by using references to make the pro-
gram more efficient.
2.Whats wrong with the following program?
,for example.Another way to say this is that
can only store the
address ofan
To declare a pointer ofyour own,begin with the type ofobject to which the pointer will
point,followed by an asterisk,followed by the pointer name.When you declare a pointer,
you can put whitespace on either side ofthe asterisk.So
all declare a pointer named
When you declare a pointer,the asterisk only applies to the single variable name that immediately
follows it.So the following statement declares
is not a pointer! Its a variable of type
.One way to make this clearer is to play with the
However,the clearest way to declare a pointer is to declare it in its own statement,as in the fol-
lowing lines.
As with other variables,you can initialize a pointer in the same statement you declare it.
Thats what I do next with the following line,which assigns
to
Assigning
to a pointer has special meaning.Loosely translated,it means,Point to noth-
ing.ŽProgrammers call a pointer with the value ofzero a
.You should always
initialize a pointer with some value when you declare it,even ifthat value is zero.
Many programmers assign NULL to a pointer instead of 0 to make the pointer a null pointer.NULL
is a constant equal to 0 and is defined in multiple library files,including
Assigning Addresses to Pointers
Pointers: Tic-Tac-Toe 2.0
pScore = &score; //assign pointer pScore address of variable score
cout Assigning &score to pScore\nŽ;
cout &score is:  &score \nŽ; //address of score variable
cout pScore is:  pScore \nŽ; //address stored in pointer
cout Adding 500 to score\nŽ;
score += 500;
cout Adding 500 to *pScore\nŽ;
*pScore += 500;
cout Assigning &newScore to pScore\nŽ;
int newScore = 5000;
cout pScore is:  pScore \nŽ;
cout newScore is:  newScore \nŽ;
cout Assigning &str to pStr\nŽ;
string str = scoreŽ;
cout (*pStr).size() is:  (*pStr).size() \nŽ;
&#x pSt;&#xr-00;&#x pSt;&#xr-00;cout pStr-size() is:  pStr-size() \nŽ;
Whenever you dereference a pointer to access a data member or member function,surround the
dereferenced pointer by a pair of parentheses.This ensures that the dot operator will be applied to
the object to which the pointer points.
Just as with iterators,you can use the
operator with pointers for a more readable way
to access object members.Thats what I demonstrate next with the following line.
The preceding statement again displays the number ofcharacters in the
equal to
;however,Im able to substitute
making the code more readable.
There are still some pointer mechanics you need to understand before you can start to use
pointers effectively in your game programs.You can use the keyword
to restrict the
way a pointer works.These restrictions can act as safeguards and can make your pro-
gramming intentions clearer.Since pointers are quite versatile,restricting how a pointer
can be used is in line with the programming mantra ofasking only for what you need.
As youve seen,pointers can point to different objects at different times in a program.
However,by using the
keyword when you declare and initialize a pointer,you can
restrict the pointer so it can only point to the object it was initialized to point to.A pointer
like this is called a
.Another way to say this is to say that the address stored
in a constant pointer can never change„its constant.Heres an example ofcreating a con-
stant pointer:
The preceding code creates a constant pointer,
,which points to
.You create a
constant pointer by putting
right before the name ofthe pointer when you declare it.
Like all constants,you must initialize a constant pointer when you first declare it.The fol-
lowing line is illegal and will produce a big,fat compile error.
is a constant pointer,it cant ever point to any other memory location.The
following code is also quite illegal.
Pointers: Tic-Tac-Toe 2.0
Dont change the value to which a pointer points when you want to change the pointer itself.For
example,if I want to change
,then the following line would be a big
mistake.
This code simply changes the value to which
currently points;it doesnt change
itself.If
,then the previous code is equivalent to
still points to the same variable it pointed to before the assignment.
So far,the Pointing program has worked only with values ofa built-in type,
.But you
can use pointers with objects just as easily.I demonstrate this next with the following
lines,which create
,a
object equal to
,and
,a pointer that points to
is a pointer to
,meaning that it can point to any
object.Another way to
say this is to say that
can store the address ofany
You can access an object through a pointer using the dereference operator.Thats what I
do next with the following line.
By using the dereference operator with
,I send the object to which
to
.As a result,the text
is displayed.
You can call the member functions ofan object through a pointer the same way you can
call the member functions ofan object through an iterator.One way to do this is by using
the dereference operator and the member access operator,which is what I do next with
the following lines.
The code
says,Take the result ofdereferencing
and call that objects
member function.ŽBecause
refers to the
object equal to
,the code
returns
Dont dereference a null pointer because it could lead to disastrous results.
Next,I add
to
with the following line.
When I send
to
is displayed,as youd expect.When I send
to
the contents of
are again sent to
,and
is displayed once more.
Next,I add
to the value to which
points with the following line.
points to
,the preceding line ofcode adds
to
.Therefore,
when I next send
to
is displayed.Then,when I send
to
...you
is displayed again.
Dont change the value of a pointer when you want to change the value of the object to which the
pointer points.For example,if I want to add
points to,then the follow-
ing line would be a big mistake.
The preceding code adds
,not to the value to which
inally pointed.As a result,
now points to some address that might contain anything.Deref-
erencing a pointer like this can lead to disastrous results.
Unlike references,pointers can point to different objects at different times during the life
ofa program.Reassigning a pointer works like reassigning any other variable.Next,I reas-
sign
with the following line.
As the result,
now points to
.To prove this,I display the address of
by sending
to
,followed by the address stored in
.Both statements dis-
play the same address.Then I send
to
.Both display
they both access the same chunk ofmemory that stores this value.
Pointers: Tic-Tac-Toe 2.0
Figure 7.2
The pointer
,which stores the value
The code for the program is in the Chapter 7 folder on the CD-ROM that came with this
book;the file name is swap_pointer_ver.cpp.
Pointers: Tic-Tac-Toe 2.0
Figure 7.3
Passing pointers allows a function to alter variables outside of the functions
scope.
The first example declares and initializes a constant pointer.A constant pointer can only
point to the object to which it was initialized to point.The value„the memory address„
stored in the pointer itselfis constant and cant change.A constant pointer can only point
to a non-constant value;it cant point to a constant.
The second example declares a pointer to a constant.A pointer to a constant cant be used
to change the value to which it points.A pointer to a constant can point to different
objects during the life ofa program.A pointer to a constant can point to a constant or
non-constant value.
The third example declares a constant pointer to a constant.A constant pointer to a con-
stant can only point to the value to which it was initialized to point.In addition,it cant
be used to change the value to which it points.A constant pointer to a constant can be ini-
tialized to point to a constant or a non-constant value.
Even though references are the preferred way to pass arguments because oftheir cleaner
syntax,you still might need to pass objects through pointers.For example,suppose youre
using a graphics engine that returns a pointer to a 3D object.Ifyou want another function
to use this object,youll probably want to pass the pointer to the object for efficiency.
Therefore,its important to know how to pass pointers as well as references.
Introducing the Swap Pointer Version Program
The Swap Pointer Version program works just like the Swap program from Chapter 6,
except that the Swap Pointer Version program uses pointers instead ofreferences.The
Swap Pointer Version program defines two variables„one that holds my pitifully low
score and another that holds your impressively high score.After displaying the scores,the
program calls a function meant to swap the scores.Because only copies ofthe score val-
ues are sent to the function,the original variables are unaltered.Next,the program calls
another swap function.This time,through the use ofconstant pointers,the original vari-
ablesvalues are successfully exchanged (giving me the great big score and leaving you
with the small one).Figure 7.3 shows the program in action.
combines the restrictions ofa constant pointer and a point-
er to a constant.This means that a constant pointer to a constant can only point to the
object that it was initialized to point to.In addition,it cant be used to change the value of
the object to which it points.Heres the declaration and initialization ofsuch a pointer:
The preceding code creates a constant pointer to a constant named
that points to
the constant
Like a pointer to a constant,a constant pointer to a constant can point to either a non-constant or
constant value.
You cant reassign a constant pointer to a constant.The following line is not legal.
You cant use a constant pointer to a constant to change the value to which it points.This
means that the following line is illegal.
In many ways,a constant pointer to a constant acts like a constant reference,which can
only refer to the value it was initialized to refer to and which cant be used to change that
grams,you should stick with constant references whenever possible.References have a cleaner syn-
tax than pointers and can make your code easier to read.
Ive presented a lot ofinformation on constants and pointers,so I want to provide a sum-
mary to help crystallize the new concepts.Here are three examples ofthe different ways
in which you can use the keyword
when you are declaring pointers:
Pointers: Tic-Tac-Toe 2.0
Although you cant change
itself,you can use
to change the value to which it
Although you can use a constant pointer instead of a reference in your programs,you should stick
with references whenever possible.References have a cleaner syntax than pointers and can make
As youve seen,you can use pointers to change the values to which they point.However,
by using the
keyword when you declare a pointer,you can restrict a pointer so it cant
be used to change the value to which it points.A pointer like this is called a
.Heres an example ofdeclaring such a pointer:
The preceding code declares a pointer to a constant,
.You declare a pointer to a
constant by putting
right before the type ofvalue to which the pointer will point.
You assign an address to a pointer to a constant as you did before.
However,you cant use the pointer to change the value to which it points.The following
Although you cant use a pointer to a constant to change the value to which it points,the
pointer itselfcan change.This means that a pointer to a constant can point to different
objects in a program.The following code is perfectly legal.
{
&#xstri;&#xng00;vectorstring inventory;
Pointers: Tic-Tac-Toe 2.0
Figure 7.4
are constant pointers and will each accept a memory address.I
You can also pass a constant pointer to a constant.This works much like passing a constant refer-
ence,which is done to efficiently pass an object that you dont need to change.Ive adapted the
Inventory Displayer program from Chapter 6,which demonstrates passing constant references,to
pass a constant pointer to a constant.The program is in the Chapter 7 folder on the CD-ROM that
came with this book;the file name is inventory_displayer_pointer_ver.cpp.
Pointers: Tic-Tac-Toe 2.0
The call to
returns a pointer to
.The statement assigns that
pointer to
.This is an efficient assignment because assigning a pointer to a pointer
does not involve copying the
To help you understand the results ofthis line ofcode,take a look at Figure 7.5,which
shows a representation of
after the assignment.(Note that the figure is abstract
because the vector
doesnt contain the string literals
,and
;instead,it contains
Next I send
to
is displayed.
Pointers: Tic-Tac-Toe 2.0
Figure 7.5
Figure 7.6
object,totally independent from
The body ofthe function
contains only one statement,which returns a
pointer to the element at position
in the vector pointed to by
In the preceding code,
is equivalent to
.Both return the ele-
Next,I access the score at position
with the following line,which displays
In the preceding code,
is equivalent to
.Both return the ele-
.In general,you can write
as*(arrayName + i),where
is the name ofan array.
When you pass an array to a function,its usually a good idea to also pass the number of elements
As you can see from the function header of
,the array name is accepted as a con-
stant pointer.
The function body adds
to each score.
I treat
just like any array and use the subscripting operator to access each ofits ele-
ments.Alternatively,I could have treated
as a pointer and substituted
for the expression
,but I opted for the more readable version.
After
ends,control returns to
.To prove that
increase the high scores,I call a function to show the scores.
also accepts
as a pointer.However,as you can see from
the functions header,the function accepts it as a constant pointer to a constant.
Pointers: Tic-Tac-Toe 2.0
const int NUM_SCORES = 3;
cout Displaying scores using array name as a constant pointer.\nŽ;
cout *highScores endl;
cout Increasing scores by passing array as a constant pointer.\n\nŽ;
increase(highScores, NUM_SCORES);
cout Displaying scores by passing array as a constant pointer to a
constant.\nŽ;
display(highScores, NUM_SCORES);
in a contiguous block ofmemory,you can use the array name as a pointer for random
access to elements.This relationship also has important implications for how you can pass
and return arrays,as youll soon see.
Introducing the Array Passer Program
The Array Passer program creates an array ofhigh scores and then displays them,using
the array name as a constant pointer.Next,the program passes the array name as a con-
stant pointer to a function that increases the scores.Finally,the program passes the array
name to a function as a constant pointer to a constant to display the new high scores.
Figure 7.8 shows the results ofthe program.
The code for the program is in the Chapter 7 folder on the CD-ROM that came with this
book;the file name is array_passer.cpp.
Pointers: Tic-Tac-Toe 2.0
Figure 7.8
Using an array name as a pointer,the high scores are displayed,altered,and
passed to functions.
An assignment like this one,where an object is copied,is more expensive than the assign-
Figure 7.7
Pointers: Tic-Tac-Toe 2.0
Q:What good are null pointers?
A:Theyre often returned by functions as a sign offailure.For example,ifa function
is supposed to return a pointer to an object that represents the graphics screen,
but that function couldnt initialize the screen,it might return a null pointer.
Q:How does using the keyword
when declaring a pointer affect the pointer?
A:It depends on how you use it.Generally,you use
when you are declaring a
pointer to restrict what the pointer can do.
Q:What kinds ofrestrictions can I impose on a pointer by declaring it with
A:You can restrict a pointer so it can only point to the object it was initialized to
point to,or you can restrict a pointer so it cant change the value ofthe object it
points to,or both.
Q:Why would I want to restrict what a pointer can do?
Q:How is a pointer different from the variable to which it points?
A:A pointer stores a memory address.Ifa pointer points to a variable,it stores the
address ofthat variable.
Q:What good is it to store the address ofa variable that already exists?
A:One big advantage ofstoring the address ofan existing variable is that you can
pass a pointer to the variable for efficiency instead ofpassing the variable by
Q:Does a pointer always have to point to an existing variable?
A:No.You can create a pointer that points to an unnamed chunk ofcomputer mem-
ory as you need it.Youll learn more about allocating memory in this dynamic
fashion in Chapter 9,Advanced Classes and Dynamic Memory:Game Lobby.Ž
Q:Why should I pass variables using references instead ofpointers whenever
Just like an iterator,a pointer is declared to refer to a value ofa specific type.
Its good programming practice to initialize a pointer when you declare it.
Ifyou assign
to a pointer,the pointer is called a null pointer.
Pointers: Tic-Tac-Toe 2.0
By passing the array in this way,I keep it safe from changes.Because all I want to do is dis-
play each element,its the perfect way to go.
Finally,the body of
runs and all ofthe scores are listed,showing that theyve
each increased by 500.
You can pass a C-style string to a function,just like any other array.In addition,you can pass a
Because an array name is a pointer,you can return an array using the array name,just as
you would any other pointer to an object.
Introducing the Tic-Tac-Toe 2.0 Game
The project for this chapter is a modified version ofthe project from Chapter 6,the Tic-
Tac-Toe game.From the players perspective,the Tic-Tac-Toe 2.0 game looks exactly the
same as the original because the changes are under the hood„Ive replaced all ofthe ref-
erences with pointers.This means that objects such as the Tic-Tac-Toe board are passed
as constant pointers instead ofas references.This has other implications,including the
fact that the address ofa Tic-Tac-Toe board must be passed instead ofthe board itself.
The new version ofthe program is in the Chapter 7 folder on the CD-ROM that came
with this book;the file name is tic-tac-toe2.cpp.I wont go over the code because much of
it remains the same.But even though the number ofchanges isnt great,the changes are
critical.This is a good program to study because,although you should use references
whenever you can,you should be equally comfortable passing pointers.
In this chapter,you should have learned the following concepts:
Computer memory is organized in an ordered way,where each chunk ofmemory
has its own unique address.
A pointer is a variable that contains a memory address.
In many ways,pointers act like iterators from the STL.For example,just as with
iterators,you use pointers to indirectly access an object.
To declare a pointer,you list a type,followed by an asterisk,followed by a name.
Introducing the Simple Critter Program
The Simple Critter program defines a brand-new type called
for creating virtual
Figure 8.1
Each critter says hi and announces how hungry it is.
Classes: Critter
Chapter 8
bject-oriented programming
(OOP) is a different way ofthinking about program-
This page intentionally
Exercises
1.Write a program with a pointer to a pointer to a
object.Use the pointer to
the pointer to call the
member function ofthe
2.Rewrite the final project from Chapter 5,the Mad Lib game,so that no
objects are passed to the function that tells the story.Instead,the function should
accept pointers to
3.Will the three memory addresses displayed by the following program all be the
same? Explain whats going on in the code.
When you instantiate objects,you often want to do some initialization„usually assigning
values to data members.Luckily,a class has a special member function known as a
structor
that is automatically called every time a new object is instantiated.This is a big
convenience because you can use a constructor to perform initialization ofthe new object.
Introducing the Constructor Critter Program
The Constructor Critter program demonstrates constructors.The program instantiates a
object,which automatically invokes its constructor.First,the constructor
announces that a new critter has been born.Then,it assigns the value passed to it to the
Figure 8.2
The
constructor initializes a new objects hunger level automatically.
As a result,I have two
Its time to put these critters to work.Next,I give my first critter a hunger level.
The preceding code assigns
to
s data member
.Just like when you are
accessing an available member function ofan object,you can access an available data
member ofan object using the member selection operator.
To prove that the assignment worked,I display the critters hunger level.
The preceding code displays
s data member
and correctly shows
.Just like
Defining New Types
In a class definition,you can also declare member functions to represent object abilities.
You might have noticed the keyword
in the class definition.You can ignore it for now.Youll
learn more about it a bit later in this chapter,in the section,Specifying Public and Private Access
Levels.Ž
You can define member functions outside ofa class definition.Outside ofthe
definition,I define the
{
Critter crit1;
crit1.m_Hunger = 9;
cout crit1s hunger level is  crit1.m_Hunger .\nŽ;
crit2.m_Hunger = 3;
cout crit2s hunger level is  crit2.m_Hunger .\n\nŽ;
Defining New Types
{
Critter(int hunger = 0);
should call an objects member functions,allo
wing the object to maintain its own data
members and ensure their integrity.Fortunately,you can enforce data member restric-
Figure 8.3
objects
I define the constructor outside ofthe class with the following code:
The constructor displays a message saying that a new critter has been born and initializes
the objects
data member with the argument value passed to the constructor.If
no value is passed,then the constructor uses the default argument value of
You can use
as a shorthand way to assign values to data members in a con-
You dont explicitly call a constructor;however,whenever you instantiate a new object,its
constructor is automatically called.In
,I put my constructor into action with the
following code:
When
is instantiated,its constructor is automatically called and the message
is displayed.Then,the constructor assigns
to the objects
data member.
To prove that the constructor worked,back in
I call the objects
{
int m_Hunger;
Critter(int hunger = 0); // constructor prototype
requires no arguments.If you dont define a default constructor,the compiler
class.If you write your own constructor,then the compiler wont provide a default constructor for
you.Its usually a good idea to have a default constructor,so you should make sure to supply your
The code for the program is in the Chapter 8 folder on the CD-ROM that came with this
book;the file name is static_critter.cpp.
Figure 8.4
The program stores the total number of
and accesses that data member in two different ways.
Okay,I lied a little.A constant member function can alter a static data member.Youll learn about
static data members a bit later in this chapter,in the Declaring and Initializing Static Data Mem-
bersŽsection.Also,if you qualify a data member with the
keyword,then even a constant
member function can modify it.For now,though,dont worry about either of these exceptions.
You can declare a constant member function by putting the keyword
the function header.Thats what I do in
with the following line,which declares
In the preceding code,
Just as you can with regular functions,you can inline member functions.One way to inline a mem-
ber function is to define it right inside of the class definition,where youd normally only declare the
member function.If you include a member function definition in a class,then of course you dont
need to define it outside of the class.
The one exception to this rule is that when you define a member function in a class definition using
the keyword
,the member function is not automatically inlined.Youll learn about virtual
functions in Chapter 10,Inheritance and Polymorphism:Blackjack.Ž
At this point,you might be wondering why youd go to the trouble ofmaking a data mem-
ber private only to grant full access to it through accessor functions.The answer is that
you dont generally grant full access.For example,take a look at the accessor member
have public access levels using the keyword
.Again in
,I start a public section
with the following line:
By using
,Im saying that any data member or member function that follows (until
another access level specifier) will be public.This means that any part ofthe program can
access them.Because I declare all ofthe member functions in this section,it means that
any part ofmy code can call any member function through a
Next,I specify a private section with the following line:
By using
,Im saying that any data member or member function that follows
(until another access level specifier) will be private.This means that only code in the
class can directly access it.Since I declare
in this section,it means that
only the code in
can directly access an objects
data member.Therefore,I
cant directly access an objects
data member through the object in
as Ive
done in previous programs.So the following line in
,ifuncommented,would be an
illegal statement:
is private,I cant access it outside ofthe
class.Again,only code in
can directly access the data member.
Ive only shown you how to make data members private,but you can make member func-
tions private,too.Also,you can repeat access modifiers.So ifyou want,you could have a
private section,followed by a public section,followed by another private section in a class.
Finally,member access is private by default.Until you specify an access modifier,any class
members you declare will be private.
An
accessor member function
allows indirect access to a data member.Because
private,I wrote an accessor member function,
You can also access a static member through any object of the class.Assuming that
object,I could display the total number of critters with the following line:
Figure 8.5
If you fail to feed or entertain your critter,it will have a mood change for the worse.
Notice that I had to qualify
with
.Outside ofits class,you have to qualify
a static data member with its class name.
You can also access a static member through any object of the class.Assuming that
object,I could display the total number of critters with the following line:
I also access this static data member in the
constructor with the following line,
which increments
This means that every time a new object is instantiated,
is incremented.Notice
that I didnt qualify
with
.Just as with non-static data members,you dont
have to qualify a static data member with its class name inside a class.
Although I made my static data member public,you can make a static data member
private„but then,like any other data member,you can only access it in a class
static member function
exists for the entire class.I define a static member in
with
the following line,which defines a static member function
int main()
{
cout The total number of critters is: ;
Critter crit1, crit2, crit3;
cout \nThe total number of critters is: ;
You can declare a static variable in non-class functions,too.The static variable maintains its value
is a private data member that represents the critters hunger level,while
is a private data member that represents its boredom level.Ill go through each member
function in its own section.
The constructor takes two arguments,
.The arguments each have a
default value ofzero,which I specified in the constructor prototype back in the class def-
inition.I use
to initialize
to initialize
The core ofthe game is the critter itself.Therefore,I first plan my
class.Because I
want the critter to have independent hunger and boredom levels,I know that the class will
have private data members for those.
The critter should also have a mood,directly based on its hunger and boredom levels.My
first thought was to have a private data member,but a critters mood is really a calculated
value based on its hunger and boredom.Instead,I decided to have a private member func-
tion that calculates a critters mood on the fly,based on its current hunger and boredom
levels.
Figure 8.6
Some game programmers prefix private data member names with
data member names with
so that theyre instantly recognizable.
A constant member function cant modify non-static data members or call non-
constant member functions ofits class.
Q:What is procedural programming?
A:A paradigm where tasks are broken down into a series ofsmaller tasks and imple-
mented in manageable chunks ofcode,such as functions.In procedural program-
ming,functions and data are separate.
Q:What is an object?
A:An entity that combines data and functions.
Q:Why create objects?
A:Because the world„and especially a game world„is full ofobjects.By creating
your own types,you can represent objects and their relationships to other objects
more directly and intuitively than you might be able to otherwise.
Q:What is object-oriented programming?
A:A paradigm where work is accomplished through objects.It allows programmers
to define their own types ofobjects.The objects usually have relationships to each
other and can interact.
Q:Is C++ an object-oriented programming language or a procedural programming
A:C++ is a multi-paradigm programming language.It allows a game programmer
to write games in a procedural way or an object-oriented way„or through a
combination ofboth (to name just a few options).
Q:Should I always try to write object-oriented game programs?
A:Although object-oriented programming is used in almost every commercial game
} while (choice != 0);
In
,I instantiate a new
object.Because I dont supply values for
,the data members start out at
,and the critter begins life happy and content.
Next,I create a menu system.Ifthe player enters
,the program ends.Ifthe player enters
,the program calls the objects
member function.Ifthe player enters
,the pro-
gram calls the objects
member function.Ifthe player enters
,the program calls the
objects
member function.Ifthe player enters anything else,he is told that the
choice is invalid.
The Talk() Member Function
member function announces the critters mood,which can be happy,okay,
frustrated,or mad.
Introducing the Critter Farm Program
The Critter Farm program defines a new kind ofcritter with a name.After the program
announces a new critters name,it creates a critter farm„a collection ofcritters.Finally,
the program calls roll on the farm and each critter announces its name.Figure 9.1 shows
the results ofthe program.
The code for the program is in the Chapter 9 folder on the CD-ROM that came with this
book;the file name is critter_farm.cpp.
Figure 9.1
The critter farm is a collection of critters,each with a name.
Advanced Classes
and Dynamic Memory:
Game Lobby
Chapter 9
++ gives a game programmer a high degree ofcontrol over the computer.One of
the most fundamental abilities is direct control over memory.In this chapter,
youll learn about
dynamic memory
„memory that you manage yourself.But with
great power comes great responsibility,so youll also see the pitfalls ofdynamic memory
and how to avoid them.Youll learn a few more things about classes,too.Specifically,youll
learn to:
Combine objects
Use friend functions
Overload operators
Dynamically allocate and free memory
Avoid memory leaks
Produce deep copies ofobjects
Using Aggregation
Game objects are often composed ofother objects.For example,in a racing game,a drag
racer could be seen as a single object composed ofother individual objects,such as a body,
four tires,and an engine.Other times,you might see an object as a collection ofrelated
objects.In a zookeeper simulation,you might see the zoo as a collection ofan arbitrary
number ofanimals.You can mimic these kinds ofrelationships among objects in OOP
aggregation
„the combining ofobjects so that one is part ofanother.For example,
you could write a
data member thats an
Or,you could write a
data member that is a collection of
5.When is it a good idea to calculate an objects attribute on the fly rather than stor-
Exercises
Q:What are the benefits ofencapsulation?
A:In the world ofOOP,encapsulation protects the integrity ofan object.For exam-
ple,you might have a
object with a
data member.By preventing
direct access to this data member,you can guarantee that it never becomes an ille-
gal value (such as a negative number).
Q:Should I provide access to data members through accessor member functions?
A:Some game programmers say you should never provide access to data members
through accessor member functions because even though this kind ofaccess is
indirect,it goes against the idea ofencapsulation.Instead,they say you should
write classes with member functions that provide the client with all ofthe func-
tionality it could need,eliminating the clients need to access a specific data
member.
Q:What are mutable data members?
A:Data members that can be modified even by constant member functions.You cre-
ate a mutable data member using the keyword
.You can also modify a
mutable data member ofa constant object.
Q:Why is it useful to have a default constructor?
A:Because there might be times when objects are automatically created without any
argument values passed to a constructor„for example,when you create an array
ofobjects.
Q:What is a structure?
A:A structure is very similar to a class.The only real difference is that the default
access level for structures is public.You define a structure by using the keyword
Q:Why does C++ have both structures and classes?
A:So that C++ retains backward compatibility with C.
Q:When should I use structures?
&#xstri;&#xng00;#include string
using namespace std;
class Critter
{
//make following global functions friends of the Critter class
friend void Peek(const Critter& aCritter);
friend ostream& operator(ostream& os, const Critter& aCritter);
public:
Critter(const string& name = Ž): m_Name(name) {}
private:
string m_Name;
};
void Peek(const Critter& aCritter);
ostream& operator(ostream& os, const Critter& aCritter);
int main()
{
Critter crit(PoochieŽ);
cout Calling Peek() to access crits private data member, m_Name: \nŽ;
Peek(crit);
cout \nSending crit object to cout with the operator:\nŽ;
cout crit;
Finally,I take roll through the
objects
This iterates through the vector,calling each
objects
Figure 9.2
The name of the critter is displayed through a friend function,and the
By passing the string literal
,the constructor is called and a
name is instantiated,which the constructor assigns to
.A new critter named Poochie
is born.
Next,I display the critters name with the following line:
adds a copy of an object to a vector,this means that I create an extra copy
.This is no big deal in the Critter Farm program,but
if I were adding many large objects,it could become a performance issue.You can reduce this over-
head by using,say,a vector of pointers to objects.Youll see how to work with pointers to objects
later in this chapter.
void Add(const Critter& aCritter) { m_Critters.push_back(aCritter); }
rit;&#xter0;for (vectorCritter::const_iterator iter = m_Critters.begin();
iter != m_Critters.end(); ++iter)
The code for the program is in the Chapter 9 folder on the CD-ROM that came with this
book;the file name is heap.cpp.
Figure 9.3
The two
values are stored on the heap.
This means I can simply display a
object by sending it to
with the
opera-
tor,which is what I do in
with the following line,which displays the text
This function works because
is ofthe type
,which already overloads the
operator so that you can send built-in types to
So far,whenever youve declared a variable,C++ has allocated the necessary memory for it.
When the function that the variable was created in ended,C++ freed the memory.This
memory,which is used for local variables,is called the
.But theres another kind of
memory that persists independently ofthe functions in a program.You,the programmer,
are in charge ofallocating and freeing this memory,collectively called the
free store
At this point,you might be thinking,Why bother with another type ofmemory? The
stack works just fine,thank you.ŽUsing the dynamic memory ofthe heap offers great
benefits that can be summed up in one word:efficiency.By using the heap,you can use
only the amount ofmemory you need at any given time.Ifyou have a game with a level
that has 100 enemies,you can allocate the memory for the enemies at the beginning ofthe
level and free the memory at the end.The heap also allows you to create an object in one
function that you can access even after that function ends (without having to return a
copy ofthe object).You might create a screen object in one function and return access to
it.Youll find that dynamic memory is an important tool in writing any significant game.
Introducing the Heap Program
The Heap program demonstrates dynamic memory.The program dynamically allocates
memory on the heap for an integer variable,assigns it a value,and then displays it.Next,the
program calls a function that dynamically allocates memory on the heap for another inte-
ger variable,assigns it a value,and returns a pointer to it.The program takes the returned
pointer,uses it to display the value,and then frees the allocated memory on the heap.Finally,
the program contains two functions that demonstrate the misuse ofdynamic memory.
I dont call these functions,but I use them to illustrate what
to do with dynamic
memory.Figure 9.3 shows the program.
Creating Friend Functions
A friend function can access any member ofa class ofwhich its a friend.You specify that
a function is a friend ofa class by listing the function prototype preceded by the keyword
inside the class definition.Thats what I do inside the
definition with the
following line,which says that the global function
is a friend of
can access any member of
even though its not a member func-
tion ofthe class.
takes advantage ofthis relationship by accessing the private data
to display the name ofa critter passed to the function.
When I call
with the following line,the private data member
is displayed and
appears on the screen.
Ive written two functions in the Heap program that purposely create memory leaks in
order to show you what
to do when using dynamic memory.The first function is
,which simply allocates a chunk ofmemory on the heap for an
IfI were to call this function,memory would be lost forever.(Okay,it would be lost until
the program ended.) The problem is that
,which is the only connection to the newly
acquired chunk ofmemory on the heap,is a local variable and ceases to exist when the
ends.So,theres no way to free the allocated memory.Take a look at
Figure 9.4 for a visual representation ofhow the leak occurs.
To avoid this memory leak,I could do one oftwo things.I could use
tion body,
,allocates a new piece ofmemory on the heap,assigns
to it,and has
point to that piece ofmemory.So far,so good.The second line,
,points
to a new piece ofmemory on the heap,which stores
.The problem is that the memory on the heap that stores
now has nothing pointing
to it,so there is no way for the program to free that memory.As a result,that piece of
memory has essentially leaked out ofthe system.Check out Figure 9.5 for a visual repre-
sentation ofhow the leak occurs.
Figure 9.4
The memory that stores
accessed to be freed,so it has leaked out of the
That memory is returned to the heap for future use.The data that was stored in it is no
longer available.Next,I use
Because you need to free memory that youve allocated once youre finished with it,a good rule of
Using
or reassign it to point to a new,valid chunk of memory.
Avoiding Memory Leaks
One problem with allowing a programmer to allocate and free memory is that he might
You can initialize memory on the heap at the same time you allocate it by placing a value,sur-
rounded by parentheses,after the type.This is even easier than it sounds.For example,the follow-
variable and assigns
to it.The
One ofthe major advantages ofmemory on the heap is that it can persist beyond the
function in which it was allocated,meaning that you can create an object on the heap in
one function and return a pointer or reference to it.Thats what I demonstrate with the
following line:
The statement calls the function
,which allocates a chunk ofmemory on the
and assigns
to it.
The code for the program is in the Chapter 9 folder on the CD-ROM that came with this
book;the file name is heap_data_member.cpp.
Working with Data Members and the Heap
Figure 9.6
Objects,each with a data member that points to a value on the heap,are
instantiated,destroyed,and copied.
The last statement ofthe function,
Figure 9.5
,the memory that
is no longer accessible and has leaked out of the system.
Initialized to another object through an initializer
Provided as a single argument to the objects constructor
The copying is done by a special member function called the
copy constructor
.Like con-
structors and destructors,a default copy constructor is supplied for you ifyou dont write
one ofyour own.The default copy constructor simply copies the value ofeach data mem-
ber to data members ofthe same name in the new object„a
member-wise copy
For simple classes,the default copy constructor is usually fine.However,when you have a
class with a data member that points to value on the heap,you usually write your own
copy constructor.Why? Imagine a
object that has a data member thats a pointer
to a
object on the heap.With only a default copy constructor,the automatic copy-
ing ofthe object would result in a new object that points to the same single
Working with Data Members and the Heap
Figure 9.8
were made,both
member that points to the same chunk of memory on the heap.
destructor
is member function thats called just before an object is destroyed.
Destructors are most often used by programmers to perform any necessary cleanup before
an object disappears forever.A destructor must have the name ofthe class preceded by
When you have a class that allocates memory on the heap,you should write a destructor that
cleans up and frees that memory.
Figure 9.7
object.The
stored on the heap.
crit.SayHi();
}
//passing object by value invokes its copy constructor
void testCopyConstructor(Critter copy)
copy.SayHi();
}
void testAssignmentOp()
{
Critter crit1(crit1Ž);
Critter crit2(crit2Ž);
crit1 = crit2;
Working with Data Members and the Heap
overloaded assignment operator ofyour own.Ifyou dont,youll end up with shallow
copies ofobjects when you assign one object to another.To avoid this problem,I over-
loaded the assignment operator for
to this memory.In the next line,
When you have a class with data members that point to memory on the heap,you should consider
writing a copy constructor that allocates memory for a new object and creates a deep copy.
When both sides ofan assignment statement are objects ofthe same class,the class
assignment operator member function is called.Like a default copy constructor,a default
assignment operator member function is supplied for you ifyou dont write one ofyour
own.Also like the default copy constructor,the default assignment operator provides only
member-wise duplication.
For simple classes,the default assignment operator is usually fine.However,when you
have a class with a data member that points to a value on the heap,you usually provide an
Working with Data Members and the Heap
Figure 9.10
With a proper copy constructor,the original and the copy each point to their
own chunk of memory on the heap.Then,when the copy is destroyed,the
Why is this a problem? Once
s destructor is called,freeing
the memory on the heap pointed to by
s
data member.Because ofthis,
data member would point to memory that has been freed,which would mean that
s
data member would be a dangling pointer! Figure 9.9 provides you with
a visual representation ofthis.Note that the image is abstract because the name ofthe
critter is actually stored as a
object,not a string literal.
What you really need is a copy constructor that produces a new object with its own chunk
ofmemory on the heap that the object points to„a
deep copy
.Thats what I do when I
define the following copy constructor,which overloads the default one provided by the
compiler.
Figure 9.9
object is destroyed,the memory on
the heap that it shared with the original object is freed.As result,the original
object now has a dangling pointer.
The first thing I do is create a
class to represent the players who are waiting in the
game lobby.Because I dont know how many players Ill have in my lobby at one time,it
makes sense to use a dynamic data structure.Normally,Id go to my toolbox ofcontain-
ers from the STL.But I decided to take a different approach in this program and create my
own kind ofcontainer using dynamically allocated memory that I manage.I didnt do this
Figure 9.11
The lobby holds players who are removed in the order in which they were
Next,I want to prove that the assignment didnt produce shallow copies and that both
have data members that point to two different chunks ofmemory on the
heap.So,I change the value stored in the chunk ofmemory to which the data member of
When you have a class with a data member that points to memory on the heap,you should con-
sider overloading the assignment operator for the class.
Introducing the Game Lobby Program
The Game Lobby program simulates a game lobby„a waiting area for players,usually in
an online game.The program doesnt actually involve an online component.It creates a
single line in which players can wait.The user ofthe program runs the simulation and has
four choices.He can add a person to the lobby,remove a person from the lobby (the first
person in line is the first to leave),clear out the lobby,or quit the simulation.Figure 9.11
shows the program in action.
Working with Data Members and the Heap
Ifthe lobby isnt empty,the player is added to the end ofthe line.The function accom-
plishes this by moving through the list one node at a time,using
s
objects every time its called.For
small lists this isnt a problem,but with large lists this inefficient process can become unwieldy.
There are more efficient ways to do what this function does.In one of the chapter exercises,your
Figure 9.14
The list of players just before and just after a new player node is added.
I declare the function
a friend of
object to
operator.
The
class has a data member,
,which points to
objects on the heap.Because
of this,I included a destructor that frees all of the memory occupied by the
However,I didnt define a copy constructor or overload the assignment operator in the class.For
the Game Lobby program,this isnt necessary.But if I wanted a more robust
class,I would
of the chapter exercises.
member function adds a player to the end ofthe line in the lobby.
Working with Data Members and the Heap
is a pointer that points to a
object,which represents the
represents the head ofthe line.
Because each
data member,you can link a bunch of
linked list
.Individual elements oflinked lists are often called
.Figure 9.13
provides a visual representation ofa game lobby„a series ofplayer nodes linked with one
player at the head ofthe line.
One way to think about the player nodes is as a group oftrain cars that carry cargo and
are connected.In this case,the train cars carry a name as cargo and are linked through a
pointer data member,
.The
class allocates memory on the heap for each
object in the list.The
provides access to the first
object at the head ofthe list.
The constructor is very simple.It simply initializes the data member
to
,making
it a null pointer.The destructor simply calls
,which removes all the
from the list,freeing the allocated memory.
instantiates a
heap and adds it to the end ofthe list.
removes the first
list,freeing the allocated memory.
Figure 9.13
Each node holds a name and a pointer to the next player in the list.The first player in line is at the
&#xstri;&#xng00;#include string
using namespace std;
class Player
{
Player(const string& name = Ž): m_Name(name), m_pNext(0) {}
Working with Data Members and the Heap
Figure 9.12
{
cout myLobby;
cout endl Enter choice: ;
��cin choice;
switch (choice)
{
case 0: cout Good-bye.\nŽ; break;
default: cout That was not a valid choice.\nŽ;
}
}
while (choice != 0);
Ifthe list is empty,the loop isnt entered and the function ends.Otherwise,the loop is
entered and the function keeps removing the first
object in the list by calling
until there are no more
member function overloads the
operator so I can display a
by sending it to
{
cout The game lobby is empty. No one to remove!\nŽ;
}
Player* pTemp = m_pHead;
Working with Data Members and the Heap
Figure 9.15
The list of players just before and just after a player node is removed.
Inheritance and
Polymorphism: Blackjack
Chapter 10
lasses give you the perfect way to represent game entities that have attributes and
behaviors.But game entities are often related.In this chapter,youll learn about
inheritance and polymorphism,which give you ways to express those connections
and can make defining and using game classes even simpler and more intuitive.
Specifically,youll learn to:
Derive one class from another
Use inherited data members and member functions
Override base class member functions
Define virtual functions to enable polymorphism
Declare pure virtual functions to define abstract classes
Split your code up into multiple files
Introducing Inheritance
One ofthe key elements ofOOP is
inheritance
,which allows you to
derive
a new class from
an existing one.When you do so,the new class automatically
inherits
1.What types ofgame entities could you create with aggregation?
2.Do friend functions undermine encapsulation in OOP?
3.What advantages does dynamic memory offer to game programs?
4.Why are memory leaks difficult errors to track down?
5.Should objects that allocate memory on the heap always be required to free it?
Exercises
1.Improve the
class from the Game Lobby program by writing a copy con-
structor and an overloaded assignment operator for it.
2.The
member function from the Game Lobby program is ineffi-
cient because it iterates through all ofthe player nodes to add a new player to the
end ofthe line.Add an
pointer data member to the
class that always
points to the last player node in the line and use it to more efficiently add a player.
3.Whats wrong with the following code?
Q:What is a friend class?
A:A class that can access all ofthe members ofanother class.
Q:Cant operator overloading become confusing?
A:Yes.Giving too many meanings or unintuitive meanings to operators can lead to
code thats difficult to understand.
Q:What happens when I instantiate a new object on the heap?
A:All ofthe data members will occupy memory on the heap and not on the stack.
Q:Can I access an object through a constant pointer?
A:Sure.But you can only access constant member functions through a constant
pointer.
Q:Whats wrong with shallow copies?
A:Because shallow copies share references to the same chunks ofmemory,a change
to one object will be reflected in another object.
Q:What is a linked list?
A:A dynamic data structure that consists ofa sequence oflinked nodes.
Q:How is a linked list different from a vector?
A:Linked lists permit insertion and removal ofnodes at any point in the list but do
using namespace std;
class Enemy
{
public:
int m_Damage;
Enemy(): m_Damage(10) {}
void Attack() const
{ cout Attack inflicts  m_Damage  damage points!\nŽ; }
};
class Boss : public Enemy
{
int m_DamageMultiplier;
Boss(): m_DamageMultiplier(3) {}
void SpecialAttack() const
{ cout Special Attack inflicts  (m_DamageMultiplier * m_Damage);
cout  damage points!\nŽ; }
};
int main()
{
cout Creating an enemy.\nŽ;
Enemy enemy1;
cout \nCreating a boss.\nŽ;
Boss boss1;
Cleaner code
.Because the functionality ofbase classes exists only once in a pro-
gram,you dont have to wade through the same code repeatedly,which makes
programs easier to understand and modify.
Figure 10.2
The
without you having to write any code for them at all.Then,to make a boss tough,
you could add a member function
Figure 10.1
Members that are specified as
are not accessible outside ofthe class,except in
some cases ofinheritance.As a refresher,here are the three levels ofmember access:
members are accessible to all code in a program.
members are accessible only in their own class and certain derived
classes,depending upon the access level used in inheritance.
members are only accessible in their own class,which means they are not
directly accessible in any kind ofderived class.
When you derive a class from an existing one,you can use an access modifier,such as
,which I used in deriving
Using public derivation means that public members in the base class become public mem-
bers in the derived class,protected members in the base class become protected members
in the derived class,and private members are inaccessible.
Even if base data members are private,you can still use them indirectly through base class mem-
tions.
inherits all of
s public member functions as public member
functions.It also means that
inherits
as a protected data member.The upshot
class can access
.The class essentially acts as ifI sim-
ply copied and pasted the code for these two
class members right into the
nition.But through the beauty ofinheritance,I didnt have to do this.
You can derive a new class with the
keywords,but theyre rarely used.
Youre not stuck with every base class member function you inherit in a derived class as
is.You have options that allow you to customize how those inherited member functions
//Demonstrates access control under inheritance
&#xiost;&#xream;#include iostream
using namespace std;
class Enemy
{
Enemy(): m_Damage(10) {}
void Attack() const
{ cout Attack inflicts  m_Damage  damage points!\nŽ; }
protected:
int m_Damage;
};
class Boss : public Enemy
{
Boss(): m_DamageMultiplier(3) {}
void SpecialAttack() const
{ cout Special Attack inflicts  (m_DamageMultiplier * m_Damage);
cout  damage points!\nŽ; }
private:
int m_DamageMultiplier;
};
int main()
{
cout Creating an enemy.\nŽ;
Enemy enemy1;
cout \nCreating a boss.\nŽ;
Boss boss1;
The fact that base class destructors are called for objects of derived classes ensures that each class
on the heap.
Next I call an inherited member function ofthe
object,which displays the exact same
That makes perfect sense because the same code is being executed and both objects have
data member equal to
.Notice that the function call looks the same as it did
.The fact that
inherited the member function from
makes no differ-
ence in how the function is called.
You might have noticed that I made all of the members of the classes public,including their data
members.I did this because it makes for the simplest first example of a base and a derived class.
You also might have noticed that I used the keyword
.For
now,dont worry about this.Ill cover it all in the next example program.
To derive classes ofyour own,follow my example.After the class name in a class defini-
tion,put a colon followed by an access modifier (such as
),followed by the name of
the base class.Its perfectly acceptable to derive a new class from a derived class,and some-
times it makes perfect sense to do so.However,to keep things simple,Im only going to
deal with one level ofinheritance.
There are actually a few base class member functions that are not inherited by derived
classes.They are
Constructors
Copy constructors
Destructors
Overloaded assignment operators
You have to write your own versions ofthese in the derived class.
Instantiating Objects from a Derived Class
In
,I instantiate an
member function.This
works just as youd expect.The interesting part ofthe program begins next,when I instan-
tiate a
After this line ofcode,I have a
object with an
data member equal to
data member equal to
.How did this happen? Although construc-
tors and destructors are not inherited from a base class,they are called when an instance
is created or destroyed.In fact,a base class constructor is called before the derived class
constructor to create its part ofthe final object.
In this case,when a
object is instantiated,the default
constructor is automati-
When you override an overloaded base class member function,you hide all of the other overloaded
versions of the base class member function„meaning that the only way to access the other versions
of the member function is to explicitly call the base class member function.So if you override an
overloaded member function,its a good idea to override every version of the overloaded function.
You can directly call a base class member function from any function in a derived class.
All you have to do is prefix the class name to the member function name with the scope
resolution operator.Thats what I do in the
definition ofthe
explicitly calls the
.Because
overrides the classinherited version,its as ifIve extended
the definition ofwhat it means for a boss to attack.What Im essentially saying is that
when a boss attacks,the boss does exactly what an enemy does and then adds a laughs.
When I call the member function for a
with the following line,
member function is called because Ive overloaded
member function does is explicitly call
s
member function,which displays the message
member function finishes by displaying the message
You can extend the way a member function of a base class works in a derived class by overriding
inition in the derived class and adding some functionality.
You already know how to write an overloaded assignment operator and a copy construc-
tor for a class.However,writing them for a derived class requires a little bit more work
because they arent inherited from a base class.
Being able to call a base class constructor is useful when you want to pass specific values to it.
You can override a base class member function in a derived class and give it a new defin-
ition simply by defining the function in the derived class.Thats what I do with the
Dont confuse override with overload.When you override a member function,you provide a new
definition of it in a derived class.When you overload a function,you create multiple versions of it
with different signatures.
This new definition is executed when I call the member function through any
It replaces the definition of
inherited from
objects.When I call
with the following line,the message
is displayed.
Overriding member functions is useful when you want to change or extend the behavior
ofbase class member functions in derived classes.
{ cout The enemy says he will fight you.\nŽ; }
void Attack() const
{ cout Attack! Inflicts  m_Damage  damage points.Ž; }
private:
int m_Damage;
};
class Boss : public Enemy
{
Boss(int damage = 30): Enemy(damage) //call base constructor with argument
{}
void Taunt() const
{ cout The boss says he will end your pitiful existence.\nŽ; }
void Attack() const
{
Enemy::Attack();
}
};
int main()
{
cout Creating an enemy.\nŽ;
cout \n\nCreating a boss.\nŽ;
Boss boss1;
work in your derived class.You can override them by giving them new definitions in your
derived class.You can also explicitly call a base class member function from any member
function ofyour derived class.
Introducing the Overriding Boss Program
The Overriding Boss program demonstrates calling and overriding base class member
functions in a derived class.The program creates an enemy that taunts the player and then
attacks him.Next,the program creates a boss from a derived class.The boss also taunts
the player and attacks him,but the interesting thing is that the inherited behaviors of
taunting and attacking are changed for the boss (who is a bit cockier than the enemy).
These changes are accomplished through function overriding and calling a base class
member function.Figure 10.3 shows the results ofthe program.
The code for the program is in the Chapter 10 folder on the CD-ROM that came with this
book;the file name is simple_boss2.cpp.
Figure 10.3
The
,creating new behaviors for the functions in
also a member ofthe base class,you can use a pointer to the base class to point to an object
ofthe derived class.Thats what I do in
with the following line,which instantiates
object on the heap and creates a pointer to
that points to the
Why in the world would you want to do this? Its useful because it allows you to deal with
objects without requiring that you know their exact type.For example,you could have a
function that accepts a pointer to
that could work with either an
object.The function wouldnt have to know the exact type ofobject being passed to it;it
could work with the object to produce different results depending on the objects type.But
thats not what happens as the result ofthe next line ofcode.
Instead,the line displays the text
Yikes! I called the
object and got the results of
s
function,even though I overrode
.This happened as a result of
early bind-
,in which the exact member function is bound based on the pointer type„in this case,
.What I need is to have the member function called based on the type ofobject being
pointed to,not fixed by pointer type.I can achieve this flexibility of
through
virtual functions
,which allow for polymorphic behavior.
To create a virtual member function,simply add the keyword
before the name of
the function when you declare it.Thats what I do in
with the following line:
is a virtual function.Its virtual in
and its inherited as a vir-
.This means that when I override
with the following
line,the correct version of
will be called (based on the type ofobject) and will
not be fixed by the type ofpointer.
Once a member function is defined as virtual,its virtual in any derived class.This means you dont
have to use the keyword
when you override a virtual member function in a derived class,
but you should use it anyway because it will remind you that the function is indeed virtual.
I prove that the behavior will be polymorphic in
with the following line,which
results in the
being called and the text
being displayed on the screen.
{ cout The enemy says he will fight you.\nŽ; }
protected:
int* m_pDamage;
};
class Boss : public Enemy
{
public:
Boss(int multiplier = 3)
{ m_pDamageMultiplier = new int(multiplier); }
virtual ~Boss()
{
ensures that the correct distructors are called for objects pointed to by pointers to a base
class.Figure 10.4 shows the results ofthe program.
The code for the
program is in the Chapter 10 folder on the CD-ROM that came with this book;the file
name is virtual_boss2.cpp.
Figure 10.4
and destructors are called for objects pointed to by pointers to a base class.
When you overload the assignment operator in a derived class,you usually want to call
the assignment operator member function from the base class,which you can explicitly
call using the base class name as a prefix.If
is derived from
,the overloaded
assignment operator member function defined in
could start:
The explicit call to
s assignment operator member function handles the data mem-
bers inherited from
.The rest ofthe member function would take care ofthe data
For the copy constructor,you also usually want to call the copy constructor from a base
class,which you can call just like any base class constructor.If
is derived from
the copy constructor defined in
could start:
By calling
s copy constructor with
,you copy that
s data members into
object.In the remainder of
copy constructor,you can take care ofcopy-
ing the data members declared in
into the new object.
Introducing Polymorphism
One ofthe pillars ofOOP is
polymorphism
,which means that a member function will
produce different results depending on the type ofobject for which it is being called.For
example,suppose you have a group ofbad guys that the player is facing,and the group is
made ofobjects ofdifferent types that are related through inheritance,such as enemies
and bosses.Through the magic ofpolymorphism,you could call the same member func-
tion for each bad guy in the group,say to attack the player,and the type ofeach object
The code for the program is in the Chapter 10 folder on the CD-ROM that came with this
book;the file name is abstract_creature.cpp.
A good rule of thumb is that if you have any virtual member functions in a class,you should make
the destructor virtual,too.
At times you might want to define a class to act as a base for other classes,but it doesnt
make sense to instantiate objects from this class because its so generic.For example,sup-
pose you have a game with a bunch oftypes ofcreatures running around in it.Although
Figure 10.5
The orc is an object of a class derived from an abstract class for all creatures.
Virtual functions produce polymorphic behavior through references as well.
The benefits of virtual functions arent free;there is a performance cost associated with the over-
head.Therefore,you should use virtual functions only when you need them.The good news is that
once youve defined one virtual member function in a class,defining another doesnt cost you much
more.
is essentially the act of cutting off part of an object.Assigning an object of a derived class
to a variable of a base class is legal,but you slice the object,losing the data members declared in
the derived class and losing access to member functions of the derived class.Therefore,you should
avoid slicing objects.
Defining Virtual Destructors
When you use a pointer to a base class to point to an object ofa derived class,you have a
Creating Implementation Files
Because header files for classes only contain the class definition,you need to store the class
implementation in another file.You do this in a file with the same name as the header
file,but with the familiar .cpp extension.The implementation file that corresponds to
is named critter.cpp and contains the implementation ofthe
class.Heres
the code,which is in the Chapter 10 folder on the CD-ROM that came with this book.
(The file name is critter.cpp.)
When you include a header file that you wrote,you surround the file name with quotation marks.
#define CRITTER_H
class Critter
{
public:
Organizing Your Code
piler,so check out its documentation.
Creating Header Files
Header files
are meant to be included in other files.Youve already seen header files.In fact,
every program in this book includes at least one header file from the standard library,
When you break up your program into multiple files,you generally write your own header
files„usually one for each class.The files include only the class definition,not its imple-
mentation.Following is the header file for the Critter project.It is included in the Chapter
10 folder on the CD-ROM that came with this book;the file name is critter.h.(By conven-
tion,header file names end in .h.)
Organizing Your Code
When your game programs are filled with many functions and classes,they become
unwieldy as a single file.In addition,it might be nice to reuse parts ofone program,such
Organizing Your Code
Figure 10.6
The simple application is the result of three separate C++ files.
Before you start coding a project with multiple classes,it is helpful to map them out on
paper.You might make a list and include a briefdescription ofeach class.Table 10.1 shows
my first pass at such a list for the Blackjack game.
To keep things simple,all member functions will be public and all data members will be
protected.Also,Ill use only public inheritance,which means that each derived class will
inherit all ofits base class members.
In addition to describing your classes in words,it helps to draw a family tree ofsorts to
visualize how your classes are related.Thats what I did in Figure 10.8.
Figure 10.7
One player wins;the other is not so lucky.
Table 10.1
ClassBase ClassDescription
NoneA Blackjack playing card.
NoneA Blackjack hand.A collection of
objects.
DeckHand
A Blackjack deck.Has extra functionality that
GenericPlayerHand
A generic Blackjack player.Not a full player,but the common
elements of a human player and the computer player.
PlayerGenericPlayer
A human Blackjack player.
HouseGenericPlayer
The computer player,the house.
NoneA Blackjack game.
#include critter.hŽ
using namespace std;
int main()
{
cout Instantiating a Critter object.\n\nŽ;
Critter crit;
The last part ofmy planning is to map out the basic flow ofone round ofthe game.I wrote
some pseudocode for the
class
member function.Heres what I came up with:
At this point you know a lot about the Blackjack program and you havent even seen a sin-
gle line ofcode yet! But thats a good thing.Planning can be as important as coding (ifnot
more so).Because Ive spent so much time describing the classes,I wont describe every part
ofthe code.Ill just point out significant or new ideas.The code for the program is in the
Chapter 10 folder on the CD-ROM that came with this book;the file name is blackjack.cpp.
The Card Class
After some initial statements,I define the
class for an individual playing card.
Table 10.5
MemberDescription
Table 10.6
MemberDescription
Table 10.7
MemberDescription
Creates a standard deck of 52 cards.
Shuffles cards.
the generic player can and wants to hit.
Table 10.8
MemberDescription
A deck of cards.
The casinos hand,the house.
Collection of human players.A vector of
objects.
Table 10.4
MemberDescription
Generic players name.
virtual bool IsHitting() I
Table 10.2
MemberDescription
Rank of the card (ace,2,3,and so on).
13 ranks.
Suit of the card (clubs,diamonds,hearts,or spades).
enumeration for the four possible suits.
Table 10.3
MemberDescription
Collection of cards.Stores pointers to
objects.
Adds a card to the hand.Adds a pointer to
Clears all cards from the hand.Removes all pointers in the vector
Figure 10.8
Inheritance hierarchy of classes for the Blackjack game.
shaded because it turns out to be an abstract class.
member function has an important responsibility.It not only removes all of
the pointers from the vector
,but it destroys the associated
objects and frees
the memory on the heap that they occupied.This is just like a real-world Blackjack game
in which cards are discarded when a round is over.The virtual class destructor calls
The destructor of the class is virtual,but notice that I dont use the keyword
class when I actually define the destructor.You only use the keyword inside the class definition.
Dont worry;the destructor is still virtual.
Although Ive already covered this,I want to point it out again.All ofthe
objects will
exist on the heap.Any collection ofcards,such as a
object,will have a vector ofpoint-
ers to a group ofthose objects on the heap.
friend ostream& operator(ostream& os, const Card& aCard);
Card(rank r = ACE, suit s = SPADES, bool ifu = true);
//create a standard deck of 52 cards
void Populate();
//shuffle cards
void Shuffle();
//deal one card to a hand
void Deal(Hand& aHand);
//give additional cards to a generic player
void AdditionalCards(GenericPlayer& aGenericPlayer);
};
Deck::Deck()
{
m_Cards.reserve(52);
Populate();
}
Deck::~Deck()
{}
void Deck::Populate()
{
Clear();
for (int s = Card::CLUBS; s = Card::SPADES; ++s)
for (int r = Card::ACE; r = Card::KING; ++r)
Êrd;&#x::ra;&#xnk00;Add(new Card(static_castCard::rank(r),
Êrd;&#x::su;&#xit00;static_castCard::suit(s)));
}
void Deck::Shuffle()
{
random_shuffle(m_Cards.begin(), m_Cards.end());
}
void Deck::Deal(Hand& aHand)
{
if (!m_Cards.empty())
{
aHand.Add(m_Cards.back());
m_Cards.pop_back();
}
else
{
cout Out of cards. Unable to deal.Ž;
}
}
House(const string& name = HouseŽ);
virtual ~House();
void Push() const;
};
Player::Player(const string& name): GenericPlayer(name)
{}
Player::~Player()
{}
bool Player::IsHitting() const
{
cout m_Name , do you want a hit? (Y/N): ;
��cin response;
member function faithfully implements the pseudocode I wrote earlier about
how a round ofplay should be implemented.
After declaring the overloaded
functions,I write the programs
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
cout *pPlayer endl;
cout m_House endl;
//deal additional cards to players
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
m_Deck.AdditionalCards(*pPlayer);
//reveal houses first card
//deal additional cards to house
m_Deck.AdditionalCards(m_House);
if (m_House.IsBusted())
{
//everyone still playing wins
++pPlayer)
�if ( !(pPlayer-IsBusted()) )
�pPlayer-Win();
}
//compare each player still playing to house
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end();
++pPlayer)
�if ( !(pPlayer-IsBusted()) )
class represents a game ofBlackjack.
{
{
cout endl;
Deal(aGenericPlayer);
cout aGenericPlayer endl;
if (aGenericPlayer.IsBusted())
aGenericPlayer.Bust();
}
}
Type casting
is a way of converting a value of one type to a value of another type.One way to do
.You use
creates a standard deck of52 cards.The member function loops through all of
the possible combinations of
values.It uses
to cast
loop variables to the proper enumerated types defined in
shuffles the cards in the deck.It randomly rearranges the pointers in
with
from the Standard Template Library.This is the reason I include the
deals one card from the deck to a hand.It adds a copy ofthe pointer stored in the last
element ofthe
objects
vector to the
objects
vector.Then it removes
the pointer from the
objects
vector,effectively transferring the card.The pow-
is that it accepts a reference to a
object,which means it can work
equally well with a
object.And through the magic ofpolymorphism,
can call the objects
member function without knowing the exact object type.
gives additional cards to a generic player until the generic player either
stops hitting or busts.The member function accepts reference to a
you can pass a
object to it.Again,through the magic ofpolymorphism,
Q:When should you make a destructor virtual?
A:Ifyou have any virtual member functions in a class,you should make the destruc-
tor virtual,too.However,some programmers say that to be safe,you should
always make a destructor virtual.
Q:Can constructors be virtual?
A:No.This also means that copy constructors cant be declared as virtual either.
Q:What good are abstract classes ifyou cant instantiate any objects from them?
A:Abstract classes can be very useful.They can contain many common class mem-
bers that other classes will inherit,which saves you the effort ofdefining those
members over and over again.
Q:Why split your programs into multiple files?
A:It might be convenient to put all ofthe code for small programs into one file,but
it becomes unwieldy to work with a single file for large projects.
Q:Is it really necessary to use the
,and
directives in my header
A:Yes.Although you might not really need them in some projects,its not uncom-
mon for fundamental header files to be included across many files.And using
the directives can prevent your project from trying to include the same file more
than once.
1.What benefits does inheritance bring to game programming?
2.How does polymorphism expand the power ofinheritance?
3.What kinds ofgame entities might it make sense to model through inheritance?
4.What kinds ofgame-related classes would be best implemented as abstract?
5.Why is it advantageous to be able to point to a derived class object with a base
class pointer?
Exercises
1.Split the Blackjack game program into multiple files based on individual classes.
(Trap:Both the
classes access the
class namespace.)
2.Improve the Blackjack game program by forcing the deck to repopulate before a
round ifthe number ofcards is running low.
3.In the Blackjack game program,define copy constructors and overloaded assign-
ment operator member functions to the
class and all ofits subclasses.
Q:How many levels ofinheritance can you have?
In this chapter,you should have learned the following concepts:
One ofthe key elements ofOOP is inheritance,which allows you to derive a new
class from an existing one.The new class automatically inherits data members and
member functions from the existing class.
A derived class does not inherit constructors,copy constructors,destructors,or an
overloaded assignment operator.
Base class constructors are automatically called before the derived class constructor
when a derived class object is instantiated.
Base class destructors are automatically called after the derived class destructor
when a derived class object is destroyed.
Protected members are accessible only in their own class and certain derived
classes,depending upon the derivation access level.
Using public derivation means that public members in the base class become pub-
lic members in the derived class,protected members in the base class become pro-
tected members in the derived class,and private members are (as always)
inaccessible.
You can override base class member functions by giving them new definitions in a
derived class.
You can explicitly call a base class member function from a derived class.
You can explicitly call the base class constructor from a derived class instructor.
Polymorphism is the quality whereby a member function will produce different
results depending on the type ofobject for which it is called.
Virtual functions allow for polymorphic behavior.
Once a member function is defined as virtual,its virtual in any derived class.
Slicing is essentially the act ofcutting offpart ofan object.
A pure virtual function is a function to which you dont need to give a definition.
You specify a pure virtual function by placing an equal sign and a zero at the end
ofthe function header.
An abstract class has at least one pure virtual member function.
An abstract class cant be used to instantiate an object.
You can split your programs among multiple files.
The following function definition overloads the
operator so I can send a
object to
the standard output.
with ifstatements,38
inheritance,advantages of,280
escape sequence,19
executable files,creating,2…3
exiting
break statements for,51
Hangman program,124
Expensive Calculator program,11…13
deque containers,119
iterators,109,110
pointers,195…196,197
derived classes.
See also
inheritance;polymor-
from abstract class,298
Designers Network program,52…55
destructors,262
base class destructors,283…284
copy constructors and,262…265
virtual destructors,defining,295…296
Dev-C++,3,4,73
Die Roller program,58…59
directives.
See also
preprocessor directives
using directives,9…10
display,updating,63
displayBoard() function for Tic-Tac-Toe game,
division,integers and,12…13
do loops,48…50
looping with,49…50
double type,15
dynamic arrays,100
dynamic memory,245,252…258.
See also
early binding,294
Blackjack game,303…321
Card class in,306,308…310
classes,designing,304…307
Deck class in,307,315…317
Game class in,307,318…320
GenericPlayer class in,307,312…313
Hand class in,306,310…312
House class in,307,314…315
main() function in,320
operator() member function and,321
overloading functions in,321
planning logic,208
Player class in,307,313…314
bool variables,15,35
bounds checking,87
with string objects,80
branching
with else statements,42
with switch statements,46
break statements,50…52
for exiting loops,51
with switch statements,44
bugs.
errors
busting,303
C++ Builder Studio,3
C-style comments,6
C-style strings,87…88
capacity() member function,116…117
Card class in Blackjack game,306,308…310
character variables,18…19
See also
abstract class;inheritance
abstract class,296…298
deriving class from,298
pure virtual functions,declaring,297…298
Abstract Creature program,296…297
abstraction,132
encapsulation compared,137
access levels for objects,226…231
access member functions,229…230
access modifiers with class members,285…286
addition operators,12
addresses to pointers,assigning,194…195
aggregation,245…249
container data members for,248…249
object data members with,247…248
AI (Artificial Intelligence),174
algorithms,112…116
definitions file for,114
merge() algorithm,115…116
random_shuffle() algorithm,114
sort() algorithm,115
in STL (Standard Template Library),100
AND operator,55…56
login combinations using,56
announceWinner() function for Tic-Tac-Toe
game,185…186
ANSI standard,4
ANSI/ISO standard,4
application files,302…303
argument variable,164…165
arguments,60.
See also
default arguments;pass-
references for altering,164…167
value,passing by,166…167
for types,20
variables,naming,17…18
namespace,7
std namespace,9…11
nested scopes,140…141
nesting
for loops,75
ifstatements,40
new operator with heap,254…255
not equal to operator,36
NOT operator,57
null character with C-style strings,87
null pointers,194
object files,2…3
object-oriented programming (OOP),2,219
objects,75…77.
See also
aggregation;constructors;
member functions
order ofoperations
declaring,107…108
defined,107
dereferencing,109,110
looping through vectors,108…109
in STL (Standard Template Library),100
with string objects,80…81
keywords,17
late binding,294
legal variable names,17
less than operator,36
less than or equal to operator,36
libraries.
See also
STL (Standard Template
Library)
I/O,standard library for,4
link errors,3
linked lists,270
linkers,2…3
list containers,118,119
Lobby class in Game Lobby program,269…271
Lobby::AddPlayer() member function,271…272
Lobby::Clear() member function,273…274
Lobby::RemovePlayer() member function,
local variables,139
logical errors,3…4
with else clauses,42…43
logical operators,52…58
NOT operator,57
AND operator,55…56
OR operator,56…57
order ofoperations for,57…58
loop body,48
See also
break statements for exiting,51
continue statements for jumping to,52
do loops,48…50
infinite loops,49…50
for Tic-Tac-Toe game,182
vector,looping through,108…109
while loops,46…48
Lost Fortune program,27…30
player information,obtaining,29
copy constructors in,290…291
instantiating objects from,283…284
overloaded assignment operators in,290…291
destructors,283…284
instantiating objects from derived class,283…284
overloaded assignment operators in derived
classes,290…291
overriding base class member functions,
private members,286
protected members,286
public members,286
using inherited members,284
initializer lists,85
initializing
arrays,85
C-style strings,87…88
constructors,226
for loops,71…72
Hangman program variables and constants,122
heap,memory on,255
multidimensional arrays,90
pointers,194
references,163
static data members,233
variables,19
inlining functions,151…153
calling inlined functions,153
member functions,230
specifying functions for inlining,152…153
insert() vector member function,111
instantiating
derived class,objects from,283…284
objects,222…223
instructions() function for Tic-Tac-Toe game,179
Instructions program,129…130
int type,15
integers,12…13
variables,assigning values to,18
wrap around,dealing with,24…25
Inventory Displayer program,168…169
Inventory Pointer program,205…206
Inventory Referencer program,171…172
isLegal() function for Tic-Tac-Toe game,183
ISO standard,4
iterators,105…112.
See also
vectors
altering,109
constant iterators,107
while loops,46…48
creating,51
looping with,47…48
preference for,49
whitespace
in Game Over program,6
ifstatements and,38
winner() function for Tic-Tac-Toe game,181…182
Word Jumble game,90…94
game loop for,93
picking words for,91…92
Swap Pointer Version program,201…203
Swap program,165…166
switch statements,43…46
branching with,46
syntactic sugar,111
syntax errors,3
Taking Damage program,151…152
representing data for Tic-Tac-Toe game,175…176
reserve() member function,117
return statement with functions,134…135
return values
encapsulation,136…137
sort() algorithm,115
sorting
algorithm for,115
merging sequences and,115…116
source code,2…3
speed ofC++,2
stack,252
queue containers,119
standard library,4
standard output,displaying text through,7…8
Static Critter program,231…233
static data members,231…235
accessing,233…234
declaring,233
initializing,233
static member functions
calling,234…235
defining,234
std namespace,9…11
stepwise refinement,120
STL (Standard Template Library),99…100.
also
containers;vectors
algorithms in,100
compilers with,102
iterators in,100
streams,29
string literal,7
string objects,77…82
with C-style strings,87…88
concatenating,79
creating,79
empty() member function,82
erase() member function,82
find() member function,81
indexing,80
iterating through,80…81
listing ofmember functions,82
size() member function for,79…80
String Tester program,77…78
strings,7
Stroustrup,Bjarne,1
subclass,282…283
subscripting operators
with arrays,85
with vectors,104
subtraction operators,12
superclass,282…283
support for C++,2
License Agreement/Notice of Limited Warranty
Beginning
of tips and techniques for the game developers of tom
Perfect your programming skills and create eye-catching
Game Development
WWW.COURSEPTR.COM/GAMEDEV
Game Art for Teens
for Teens
RISETOTHETOP OFYOUR
GAMEWITHCOURSEPTR!
Professional
Trade
Reference

Приложенные файлы

  • pdf 24046477
    Размер файла: 3 MB Загрузок: 0

Добавить комментарий