Você está na página 1de 19

9

My object all sublime


I shall achieve in time.

Classes:
A Deeper Look,
Part 1

W. S. Gilbert

Is it a world to hide virtues


in?
William Shakespeare

Dont be consistent, but be


simply true.
Oliver Wendell Holmes, Jr.

OBJECTIVES
In this chapter you will learn:

This above all: to thine own


self be true.
William Shakespeare

How to use a preprocessor wrapper to prevent multiple


denition errors caused by including more than one copy
of a header le in a source-code le.
To understand class scope and accessing class members
via the name of an object, a reference to an object or a
pointer to an object.
To dene constructors with default arguments.
How destructors are used to perform termination
housekeeping on an object before it is destroyed.
When constructors and destructors are called.
The logic errors that may occur when a public member
function of a class returns a reference to private data.
To assign the data members of one object to those of
another object by default memberwise assignment.

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Chapter 9 Classes: A Deeper Look, Part 1

Solutions
9.4
(Enhancing Class Time) Provide a constructor that is capable of using the current time from
the time() functiondeclared in the C++ Standard Library header <ctime>to initialize an object
of the Time class.
ANS: [Note: We provide two solutions. The first one only uses function time. The second
one uses several other data member and functions in <ctime> header.]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

// Exercise 9.4 Solution: Time.h


#ifndef TIME_H
#define TIME_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

// Exercise 9.4 Solution: Time.cpp


// Member-function definitions for class Time.
#include <iostream>
using std::cout;

class Time
{
public:
Time(); // constructor
void setTime( int, int, int ); // set hour, minute and second
void printUniversal(); // print time in universal-time format
void printStandard(); // print time in standard-time format
private:
int hour; // 0 - 23 (24-hour clock format)
int minute; // 0 - 59
int second; // 0 - 59
bool isLeapYear( int ); // check if input is a leap year
}; // end class Time
#endif

#include <iomanip>
using std::setfill;
using std::setw;
#include <ctime>
using std::time;
#include "Time.h" // include definition of class Time from Time.h
Time::Time()
{
const int
const int
const int
const int
const int
const int
const int
const int

CURRENT_YEAR = 2004;
START_YEAR = 1970;
HOURS_IN_A_DAY = 24;
MINUTES_IN_AN_HOUR = 60;
SECONDS_IN_A_MINUTE = 60;
DAYS_IN_A_YEAR = 365;
DAYS_IN_A_LEAPYEAR = 366;
TIMEZONE_DIFFERENCE = 5;

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

int leapYear = 0;
int days;
// calculate leap year
for ( int y = START_YEAR; y <= CURRENT_YEAR; y++ )
{
if ( isLeapYear( y ) )
leapYear++;
} // end for
int dayTimeInSeconds = time( 0 ) - HOURS_IN_A_DAY *
MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE * (
DAYS_IN_A_YEAR * ( CURRENT_YEAR - START_YEAR ) + leapYear );
// calculate current second, minute and hour
for ( int s = 0; s < SECONDS_IN_A_MINUTE; s++ )
{
for ( int m = 0; m < MINUTES_IN_AN_HOUR; m++ )
{
for ( int h = 0; h <= HOURS_IN_A_DAY; h++ )
{
if ( isLeapYear( CURRENT_YEAR ) )
days = DAYS_IN_A_LEAPYEAR;
else
days = DAYS_IN_A_YEAR;
for ( int d = 0; d <= days; d++ )
{
if ( s + m * SECONDS_IN_A_MINUTE +
h * MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE +
d * HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR *
SECONDS_IN_A_MINUTE == dayTimeInSeconds )
{
setTime( h-TIMEZONE_DIFFERENCE, m, s );
} // end if
} // end for
} // end for
} // end for
} // end for
} // end Time constructor
// set new Time value using universal time; ensure that
// the data remains consistent by setting invalid values to zero
void Time::setTime( int h, int m, int s )
{
hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour
minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute
second = ( s >= 0 && s < 60 ) ? s : 0; // validate second
} // end function setTime
// print Time in universal-time format (HH:MM:SS)
void Time::printUniversal()
{
cout << setfill( '0' ) << setw( 2 ) << hour << ":"

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Chapter 9 Classes: A Deeper Look, Part 1

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

<< setw( 2 ) << minute << ":" << setw( 2 ) << second;
} // end function printUniversal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

// Exercise 9.4 Solution: Ex09_04.cpp


#include <iostream>
using std::cout;
using std::endl;

// print Time in standard-time format (HH:MM:SS AM or PM)


void Time::printStandard()
{
cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":"
<< setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 )
<< second << ( hour < 12 ? " AM" : " PM" );
} // end function printStandard
// check if a year is a leap year
bool Time::isLeapYear( int y )
{
if ( ( y % 400 == 0 ) || ( ( y % 4 == 0 ) && ( y % 100 != 0 ) ) )
return true;
else
return false;
} // end function isLeapYear

#include "Time.h"
int main()
{
Time t; // create Time object
// display current time
cout << "The universal time is ";
t.printUniversal();
cout << "\nThe standard time is ";
t.printStandard();
cout << endl;
return 0;
} // end main

The universal time is 14:54:06


The standard time is 2:54:06 PM

1
2
3
4
5
6

// Exercise 9.4 Solution: Time.h


#ifndef TIME_H
#define TIME_H
class Time
{

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
7
8
9
10
11
12
13
14
15
16
17
18

public:
Time(); // constructor
void setTime( int, int, int ); // set hour, minute and second
void printUniversal(); // print time in universal-time format
void printStandard(); // print time in standard-time format
private:
int hour; // 0 - 23 (24-hour clock format)
int minute; // 0 - 59
int second; // 0 - 59
}; // end class Time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

// Exercise 9.4 Solution: Time.cpp


// Member-function definitions for class Time.
#include <iostream>
using std::cout;

#endif

#include <iomanip>
using std::setfill;
using std::setw;
#include <ctime>
using std::localtime;
using std::time;
using std::time_t;
#include "Time.h" // include definition of class Time from Time.h
Time::Time()
{
const time_t currentTime = time( 0 );
const tm *localTime = localtime( &currentTime );
setTime( localTime->tm_hour, localTime->tm_min, localTime->tm_sec );
} // end Time constructor
// set new Time value using universal time; ensure that
// the data remains consistent by setting invalid values to zero
void Time::setTime( int h, int m, int s )
{
hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour
minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute
second = ( s >= 0 && s < 60 ) ? s : 0; // validate second
} // end function setTime
// print Time in universal-time format (HH:MM:SS)
void Time::printUniversal()
{
cout << setfill( '0' ) << setw( 2 ) << hour << ":"
<< setw( 2 ) << minute << ":" << setw( 2 ) << second;
} // end function printUniversal

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

6
40
41
42
43
44
45
46

Chapter 9 Classes: A Deeper Look, Part 1

// print Time in standard-time format (HH:MM:SS AM or PM)


void Time::printStandard()
{
cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":"
<< setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 )
<< second << ( hour < 12 ? " AM" : " PM" );
} // end function printStandard

9.6
(Rational Class) Create a class called Rational for performing arithmetic with fractions.
Write a program to test your class.
Use integer variables to represent the private data of the classthe numerator and the denominator. Provide a constructor that enables an object of this class to be initialized when it is
declared. The constructor should contain default values in case no initializers are provided and
should store the fraction in reduced form. For example, the fraction
2
--4
would be stored in the object as 1 in the numerator and 2 in the denominator. Provide public
member functions that perform each of the following tasks:
a) Adding two Rational numbers. The result should be stored in reduced form.
b) Subtracting two Rational numbers. The result should be stored in reduced form.
c) Multiplying two Rational numbers. The result should be stored in reduced form.
d) Dividing two Rational numbers. The result should be stored in reduced form.
e) Printing Rational numbers in the form a/b, where a is the numerator and b is the denominator.
f) Printing Rational numbers in floating-point format.
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

// Exercise 9.6 Solution: Rational.h


#ifndef RATIONAL_H
#define RATIONAL_H
class Rational
{
public:
Rational( int = 0, int = 1 ); // default constructor
Rational addition( const Rational & ); // function addition
Rational subtraction( const Rational & ); // function subtraction
Rational multiplication( const Rational & ); // function multi.
Rational division( const Rational & ); // function division
void printRational (); // print rational format
void printRationalAsDouble(); // print rational as double format
private:
int numerator; // integer numerator
int denominator; // integer denominator
void reduction(); // utility function
}; // end class Rational
#endif

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

// Exercise 9.6 Solution: Rational.cpp


// Member-function definitions for class Rational.
#include <iostream>
using std::cout;
#include "Rational.h" // include definition of class Rational
Rational::Rational( int n, int d )
{
numerator = n; // sets numerator
denominator = d; // sets denominator
reduction(); // store the fraction in reduced form
} // end Rational constructor
Rational Rational::addition( const Rational &a )
{
Rational t; // creates Rational object
t.numerator = a.numerator * denominator;
t.numerator += a.denominator * numerator;
t.denominator = a.denominator * denominator;
t.reduction(); // store the fraction in reduced form
return t;
} // end function addition
Rational Rational::subtraction( const Rational &s )
{
Rational t; // creates Rational object
t.numerator = s.denominator * numerator;
t.numerator -= denominator * s.numerator;
t.denominator = s.denominator * denominator;
t.reduction(); // store the fraction in reduced form
return t;
} // end function subtraction
Rational Rational::multiplication( const Rational &m )
{
Rational t; // creates Rational object
t.numerator = m.numerator * numerator;
t.denominator = m.denominator * denominator;
t.reduction(); // store the fraction in reduced form
return t;
} // end function multiplication
Rational Rational::division( const Rational &v )
{
Rational t; // creates Rational object
t.numerator = v.denominator * numerator;
t.denominator = denominator * v.numerator;
t.reduction(); // store the fraction in reduced form
return t;

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Chapter 9 Classes: A Deeper Look, Part 1

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

} // end function division

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// Exercise 9.6 Solution: Ex09_06.cpp


#include <iostream>
using std::cout;
using std::endl;

void Rational::printRational ()
{
if ( denominator == 0 ) // validates denominator
cout << "\nDIVIDE BY ZERO ERROR!!!" << '\n';
else if ( numerator == 0 ) // validates numerator
cout << 0;
else
cout << numerator << '/' << denominator;
} // end function printRational
void Rational::printRationalAsDouble()
{
cout << static_cast< double >( numerator ) / denominator;
} // end function printRationalAsDouble
void Rational::reduction()
{
int largest;
largest = numerator > denominator ? numerator : denominator;
int gcd = 0; // greatest common divisor
for ( int loop = 2; loop <= largest; loop++ )
if ( numerator % loop == 0 && denominator % loop == 0 )
gcd = loop;
if (gcd != 0)
{
numerator /= gcd;
denominator /= gcd;
} // end if
} // end function reduction

#include "Rational.h" // include definition of class Rational


int main()
{
Rational c( 2, 6 ), d( 7, 8 ), x; // creates three rational objects
c.printRational(); // prints rational object c
cout << " + ";
d.printRational(); // prints rational object d
x = c.addition( d ); // adds object c and d; sets the value to x
cout << " = ";

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

x.printRational(); // prints rational object x


cout << '\n';
x.printRational(); // prints rational object x
cout << " = ";
x.printRationalAsDouble(); // prints rational object x as double
cout << "\n\n";
c.printRational(); // prints rational object c
cout << " - ";
d.printRational(); // prints rational object d
x = c.subtraction( d ); // subtracts object c and d
cout << " = ";
x.printRational(); // prints rational object x
cout << '\n';
x.printRational(); // prints rational object x
cout << " = ";
x.printRationalAsDouble(); // prints rational object x as double
cout << "\n\n";
c.printRational(); // prints rational object c
cout << " x ";
d.printRational(); // prints rational object d
x = c.multiplication( d ); // multiplies object c and d
cout << " = ";
x.printRational(); // prints rational object x
cout << '\n';
x.printRational(); // prints rational object x
cout << " = ";
x.printRationalAsDouble(); // prints rational object x as double
cout << "\n\n";
c.printRational(); // prints rational object c
cout << " / ";
d.printRational(); // prints rational object d
x = c.division( d ); // divides object c and d
cout << " = ";
x.printRational(); // prints rational object x
cout << '\n';
x.printRational(); // prints rational object x
cout << " = ";
x.printRationalAsDouble(); // prints rational object x as double
cout << endl;
return 0;
} // end main

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

10

Chapter 9 Classes: A Deeper Look, Part 1

1/3 + 7/8 = 29/24


29/24 = 1.20833
1/3 - 7/8 = -13/24
-13/24 = -0.541667
1/3 x 7/8 = 7/24
7/24 = 0.291667
1/3 / 7/8 = 8/21
8/21 = 0.380952

9.7
(Enhancing Class Time) Modify the Time class of Figs. 9.89.9 to include a tick member
function that increments the time stored in a Time object by one second. The Time object should
always remain in a consistent state. Write a program that tests the tick member function in a loop
that prints the time in standard format during each iteration of the loop to illustrate that the tick
member function works correctly. Be sure to test the following cases:
a) Incrementing into the next minute.
b) Incrementing into the next hour.
c) Incrementing into the next day (i.e., 11:59:59 PM to 12:00:00 AM).
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

// Exercise 9.7 Solution: Time.h


#ifndef TIME_H
#define TIME_H
class Time
{
public:
public:
Time( int = 0, int = 0, int = 0 ); // default constructor
// set functions
void setTime( int, int, int ); // set hour, minute, second
void setHour( int ); // set hour (after validation)
void setMinute( int ); // set minute (after validation)
void setSecond( int ); // set second (after validation)
// get functions
int getHour(); // return hour
int getMinute(); // return minute
int getSecond(); // return second
void tick(); // increment one second
void printUniversal(); // output time in universal-time format
void printStandard(); // output time in standard-time format
private:
int hour; // 0 - 23 (24-hour clock format)
int minute; // 0 - 59
int second; // 0 - 59
}; // end class Time

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
30
31

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#endif

// Exercise 9.7: Time.cpp


// Member-function definitions for class Time.
#include <iostream>
using std::cout;
#include <iomanip>
using std::setfill;
using std::setw;
#include "Time.h" // include definition of class Time from Time.h
// Time constructor initializes each data member to zero;
// ensures that Time objects start in a consistent state
Time::Time( int hr, int min, int sec )
{
setTime( hr, min, sec ); // validate and set time
} // end Time constructor
// set new Time value using universal time; ensure that
// the data remains consistent by setting invalid values to zero
void Time::setTime( int h, int m, int s )
{
setHour( h ); // set private field hour
setMinute( m ); // set private field minute
setSecond( s ); // set private field second
} // end function setTime
// set hour value
void Time::setHour( int h )
{
hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour
} // end function setHour
// set minute value
void Time::setMinute( int m )
{
minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute
} // end function setMinute
// set second value
void Time::setSecond( int s )
{
second = ( s >= 0 && s < 60 ) ? s : 0; // validate second
} // end function setSecond
// return hour value
int Time::getHour()
{
return hour;

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

11

12

Chapter 9 Classes: A Deeper Look, Part 1

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

} // end function getHour

1
2
3
4
5
6
7
8
9
10

// Exercise 9.7: Ex09_07.cpp


#include <iostream>
using std::cout;
using std::endl;

// return minute value


int Time::getMinute()
{
return minute;
} // end function getMinute
// return second value
int Time::getSecond()
{
return second;
} // end function getSecond
// increment one second
void Time::tick()
{
setSecond( getSecond() + 1 ); // increment second by 1
if ( getSecond() == 0 )
{
setMinute( getMinute() + 1 ); // increment minute by 1
if ( getMinute() == 0 )
setHour( getHour() + 1 ); // increment hour by 1
} // end if
} // end function tick
// print Time in universal-time format (HH:MM:SS)
void Time::printUniversal()
{
cout << setfill( '0' ) << setw( 2 ) << getHour() << ":"
<< setw( 2 ) << getMinute() << ":" << setw( 2 ) << getSecond();
} // end function printUniversal
// print Time in standard-time format (HH:MM:SS AM or PM)
void Time::printStandard()
{
cout << ( ( getHour() == 0 || getHour() == 12 ) ? 12 : getHour() % 12 )
<< ":" << setfill( '0' ) << setw( 2 ) << getMinute()
<< ":" << setw( 2 ) << getSecond() << ( hour < 12 ? " AM" : " PM" );
} // end function printStandard

#include "Time.h" // include definition of class Time


const int MAX_TICKS = 30;
int main()

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

13

Time t; // instantiate object t of class Time


t.setTime( 23, 59, 57 ); // set time
// output Time object t's values
for ( int ticks = 1; ticks < MAX_TICKS; ++ticks )
{
t.printStandard(); // invokes function printStandard
cout << endl;
t.tick(); // invokes function tick
} // end for

return 0;
} // end main

11:59:57
11:59:58
11:59:59
12:00:00
12:00:01
.
.
.

PM
PM
PM
AM
AM

9.11 (Rectangle Class) Create a class Rectangle with attributes length and width, each of which
defaults to 1. Provide member functions that calculate the perimeter and the area of the rectangle.
Also, provide set and get functions for the length and width attributes. The set functions should verify that length and width are each floating-point numbers larger than 0.0 and less than 20.0.
ANS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

// Exercise 9.11 Solution: Rectangle.h


#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle
{
public:
Rectangle( double = 1.0, double = 1.0 ); // default constructor
void setWidth( double w ); // set width
void setLength( double l ); // set length
double getWidth(); // get width
double getLength(); // get length
double perimeter(); // perimeter
double area(); // area
private:
double length; // 1.0 < length < 20.0
double width; // 1.0 < width < 20.0
}; // end class Rectangle
#endif

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

14

Chapter 9 Classes: A Deeper Look, Part 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

// Exercise 9.11 Solution: Rectangle.cpp


// Member-function definitions for class Rectangle.

1
2
3
4
5
6
7
8
9
10
11
12

// Exercise 9.11 Solution: Ex09_11.cpp


#include <iostream>
using std::cout;
using std::endl;
using std::fixed;

#include "Rectangle.h" // include definition of class Rectangle


Rectangle::Rectangle( double w, double l )
{
setWidth(w); // invokes function setWidth
setLength(l); // invokes function setLength
} // end Rectangle constructor
void Rectangle::setWidth( double w )
{
width = w > 0 && w < 20.0 ? w : 1.0; // sets width
} // end function setWidth
void Rectangle::setLength( double l )
{
length = l > 0 && l < 20.0 ? l : 1.0; // sets length
} // end function setLength
double Rectangle::getWidth()
{
return width;
} // end function getWidth
double Rectangle::getLength()
{
return length;
} // end fucntion getLength
double Rectangle::perimeter()
{
return 2 * ( width + length ); // returns perimeter
} // end function perimeter
double Rectangle::area()
{
return width * length; // returns area
} // end function area

#include <iomanip>
using std::setprecision;
#include "Rectangle.h" // include definition of class Rectangle
int main()

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

15

Rectangle a, b( 4.0, 5.0 ), c( 67.0, 888.0 );


cout << fixed;
cout << setprecision( 1 );
// output Rectangle a
cout << "a: length = " << a.getLength() << "; width = "
<< a.getWidth() << "; perimeter = " << a.perimeter()
<< "; area = " << a.area() << '\n';
// output Rectangle b
cout << "b: length = " << b.getLength() << "; width = "
<< b.getWidth() << "; perimeter = " << b.perimeter()
<< "; area = " << b.area() << '\n';

// output Rectangle c; bad values attempted


cout << "c: length = " << c.getLength() << "; width = "
<< c.getWidth() << "; perimeter = " << c.perimeter()
<< "; area = " << c.area() << endl;
return 0;
} // end main

a: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0


b: length = 5.0; width = 4.0; perimeter = 18.0; area = 20.0
c: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0

9.15 (TicTacToe Class) Create a class TicTacToe that will enable you to write a complete program
to play the game of tic-tac-toe. The class contains as private data a 3-by-3 two-dimensional array
of integers. The constructor should initialize the empty board to all zeros. Allow two human players.
Wherever the first player moves, place a X in the specified square. Place an O wherever the second
player moves. Each move must be to an empty square. After each move, determine whether the
game has been won or is a draw. If you feel ambitious, modify your program so that the computer
makes the moves for one of the players. Also, allow the player to specify whether he or she wants to
go first or second. If you feel exceptionally ambitious, develop a program that will play three-dimensional tic-tac-toe on a 4-by-4-by-4 board. [Caution: This is an extremely challenging project that
could take many weeks of effort!]
ANS:

1
2
3
4
5
6
7
8
9
10
11
12

// Exercise 9.15 Solution: TicTacToe.h


#ifndef TICTACTOE_H
#define TICTACTOE_H
class TicTacToe
{
private:
enum Status { WIN, DRAW, CONTINUE }; // enumeration constants
int board[ 3 ][ 3 ];
public:
TicTacToe(); // default constructor
void makeMove(); // make move

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

16

Chapter 9 Classes: A Deeper Look, Part 1

13
14
15
16
17
18
19

void printBoard(); // print board


bool validMove( int, int ); // validate move
bool xoMove( int ); // x o move
Status gameStatus(); // game status
}; // end class TicTacToe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

// Exercise 9.15 Solution: TicTacToe.cpp


// Member-function definitions for class TicTacToe.
#include <iostream>
using std::cin;
using std::cout;

#endif

#include <iomanip>
using std::setw;
#include "TicTacToe.h" // include definiton of class TicTacToe
TicTacToe::TicTacToe()
{
for ( int j = 0; j < 3; j++ ) // initialize board
for ( int k = 0; k < 3; k++ )
board[ j ][ k ] = ' ';
} // end TicTacToe constructor
bool TicTacToe::validMove( int r, int c )
{
return r >= 0 && r < 3 && c >= 0 && c < 3 && board[ r ][ c ] == ' ';
} // end function validMove
// must specify that type Status is part of the TicTacToe class.
// See Chapter 24 for a discussion of namespaces.
TicTacToe::Status TicTacToe::gameStatus()
{
int a;
// check for a win on diagonals
if ( board[ 0 ][ 0 ] != ' ' && board[ 0 ][ 0 ] == board[ 1 ][ 1 ] &&
board[ 0 ][ 0 ] == board[ 2 ][ 2 ] )
return WIN;
else if ( board[ 2 ][ 0 ] != ' ' && board[ 2 ][ 0 ] ==
board[ 1 ][ 1 ] && board[ 2 ][ 0 ] == board[ 0 ][ 2 ] )
return WIN;
// check for win in rows
for ( a = 0; a < 3; ++a )
if ( board[ a ][ 0 ] != ' ' && board[ a ][ 0 ] ==
board[ a ][ 1 ] && board[ a ][ 0 ] == board[ a ][ 2 ] )
return WIN;

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

17

// check for win in columns


for ( a = 0; a < 3; ++a )
if ( board[ 0 ][ a ] != ' ' && board[ 0 ][ a ] ==
board[ 1 ][ a ] && board[ 0 ][ a ] == board[ 2 ][ a ] )
return WIN;
// check for a completed game
for ( int r = 0; r < 3; ++r )
for ( int c = 0; c < 3; ++c )
if ( board[ r ][ c ] == ' ' )
return CONTINUE; // game is not finished
return DRAW; // game is a draw
} // end function gameStatus
void TicTacToe::printBoard()
{
cout << "
0
1
2\n\n";
for ( int r = 0; r < 3; ++r )
{
cout << r;
for ( int c = 0; c < 3; ++c )
{
cout << setw( 3 ) << static_cast< char > ( board[ r ][ c ] );
if ( c != 2 )
cout << " |";
} // end for
if ( r != 2 )
cout << "\n ____|____|____\n
} // end for

\n";

cout << "\n\n";


} // end function printBoard
void TicTacToe::makeMove()
{
printBoard();
while ( true )
{
if ( xoMove( 'X' ) )
break;
else if ( xoMove( 'O' ) )
break;
} // end while structure
} // end function makeMove

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

18

Chapter 9 Classes: A Deeper Look, Part 1

100 bool TicTacToe::xoMove( int symbol )


101 {
102
int x;
103
int y;
104
105
do
106
{
107
cout << "Player " << static_cast< char >( symbol )
108
<< " enter move: ";
109
cin >> x >> y;
110
cout << '\n';
111
} while ( !validMove( x, y ) );
112
113
board[ x ][ y ] = symbol;
114
printBoard();
115
Status xoStatus = gameStatus();
116
117
if ( xoStatus == WIN )
118
{
119
cout << "Player " << static_cast< char >( symbol ) << " wins!\n";
120
return true;
121
} // end if
122
else if ( xoStatus == DRAW )
123
{
124
cout << "Game is a draw.\n";
125
return true;
126
} // end else if
127
else // CONTINUE
128
return false;
129 } // end function xoMove
1
2
3
4
5
6
7
8
9
10

// Exercise 9.15 Solution: Ex09_15.cpp


#include "TicTacToe.h" // include definiton of class TicTacToe
int main()
{
TicTacToe g; // creates object g of class TicTacToe
g.makeMove(); // invokes function makeMove
return 0;
} // end main

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

Solutions

|
|
____|____|____
|
|
1
|
|
____|____|____
|
|
2
|
|
Player X enter move: 2 0
0

|
|
____|____|____
|
|
1
|
|
____|____|____
|
|
2 X |
|
Player O enter move: 2 2
0

|
|
____|____|____
|
|
1
|
|
____|____|____
|
|
2 X |
| O
Player X enter move: 1 1
...
Player X enter move: 0 2
0

|
| X
____|____|____
|
|
1
| X | O
____|____|____
|
|
2 X |
| O
Player X wins!

2006 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved.

19

Você também pode gostar