9.15

( TicTacToe 类) 创建TicTacToe 类, 使你可以编写一个完整的三连棋( tic-tac -toe ) 游戏程序。这个类包含一个作为private 数据的3 × 3 的二维整数数组。构造函数应将空棋盘初始化为0 。允许两个人玩游戏。无论第一人移动到哪里, 都在指定的棋格中放置1 ; 无论第二人移动到哪里, 都在指定的棋格中放置2 。每次移动都必须到达一个空格。在每次移动后, 确定是否已分胜负, 还是出现了平局。如果有兴趣, 还可以将程序修改成人机对战游戏。此外, 可以让玩家决定谁先走谁后走。如果还想继续挑战, 那么可以开发一个程序, 在4 × 4 × 4 的棋盘上玩三维的三连棋游戏。注意:这是一个极具挑战性的项目, 可能需要长达几个星期的努力工作!

实现代码

#include <iostream>
using namespace std;
class TicTacToe
{
   
public:
	TicTacToe()
	{
   
		for (int i = 0; i < 3; ++i)
		{
   
			for (int j = 0; j < 3; ++j)
			{
   
				a[i][j] = 0;
			}
		}
	}
	void run()
	{
   
		int status = 0, person = 1;
		do
		{
   
			show();
			cout << "Input:";
			int x, y;
			cin >> x >> y;
			if ((x >= 1 && x <= 3) && (y >= 1 && y <= 3) && 0 == a[x - 1][y - 1])
			{
   
				a[x - 1][y - 1] = person;
			}
			else
			{
   
				cout << "Error" << endl;
				continue;
			}
			person = (1 == person ? 2 : 1);
			status = over();
			cout << status << endl;
		} while (0 == status);
		show();
		if (1 == status)
		{
   
			cout << "First player wins." << endl;
		}
		else if (2 == status)
		{
   
			cout << "Second player wins." << endl;
		}
		else
		{
   
			cout << "DRAW" << endl;
		}
	}
	
private:
	int a[3][3];
	void show()
	{
   
		cout << "-------" << endl;
		for (int i = 0; i < 3; ++i)
		{
   
			for (int j = 0; j < 3; ++j)
			{
   
				cout << '|';
				if (1 == a[i][j])
					cout << "X";
				else if (2 == a[i][j])
					cout << "O";
				else
					cout << " ";
			}
			cout << '|' << endl;
			cout << "-------" << endl;
		}
	}
	int over()
	{
   
		bool full = true;
		for (int i = 0; i < 3 && full; ++i)
		{
   
			for (int j = 0; j < 3; ++j)
			{
   
				if (0 == a[i][j])
				{
   
					full = false;
					break;
				}
			}
		}
		if (full)
			return 3;
		for (int i = 0; i < 3; ++i)
		{
   
			if (a[i][0] != 0 && a[i][0] == a[i][1] && a[i][1] == a[i][2])
			{
   
				return a[i][0];
			}
		}
		for (int i = 0; i < 3; ++i)
		{
   
			if (a[0][i] != 0 && a[0][i] == a[1][i] && a[1][i] == a[2][i])
			{
   
				return a[0][i];
			}
		}
		if (a[0][0] != 0 && a[0][0] == a[1][1] && a[1][1] == a[2][2])
		{
   
			return a[0][0];
		}
		if (a[0][2] != 0 && a[0][2] == a[1][1] && a[1][1] == a[2][0])
		{
   
			return a[0][2];
		}
		return false;
	}
};
int main()
{
   
	TicTacToe ttt;
	ttt.run();
}

9.20

(SavingAccount 类)创建一个SavingAccount 类。使用一个static 数据成annualInterestRate 保存每个存款者的年利率。类的每个对象都包含一个private 数据成员savingsBalance , 用以指示存款者目前的存款金额。该类提供成员函数calculateMonthlyInterest , 它将余额乘以annualInterestRate 再除以12 来计算月利息, 这个利息应该加到savingsBalance 中。该类还提供一个static 成员函数modifylnterestRate , 匕将static 的annualInterestRate 设置为一个新值编写一个驱动程序测试SavingsAccount类。实例化SavingsAccount 类的两个对象saver1和saver2, 余额分别是2000.00美元和3000.00美元。将annuaIInterestRate 设置为3 %,然后计算月利率并打印每个存款者的新余额。接着再将annualInterestRate 设置为4 % , 计算下一个月的利息并打印每个存款者的新余额。

实现代码

ConsoleApplication.cpp

#include <iostream>
#include "SavingAccount.h"
using namespace std;
double SavingAccount::annualInterestRate = 0.03;
int main()
{
   
	SavingAccount saver1(2000.00), saver2(3000.00);
	cout << "saver1 的新余额: " << saver1.calculateMonthlyInterset() << endl;
	cout << "saver2 的新余额: " << saver2.calculateMonthlyInterset() << endl;
	SavingAccount::annualInterestRate = 0.04;
	cout << "saver1 的新余额: " << saver1.calculateMonthlyInterset() << endl;
	cout << "saver2 的新余额: " << saver2.calculateMonthlyInterset() << endl;
}

SavingAccount.h

#pragma once
class SavingAccount
{
   
public:
	SavingAccount(double SavingBalance);
	static double annualInterestRate;
	double calculateMonthlyInterset();
	static void modifyInterestRate(double interestRate);
private:
	double savingBalance = 0;
};

SavingAccount.cpp

#include "SavingAccount.h"
SavingAccount::SavingAccount(double SavingBalance)
{
   
	savingBalance = SavingBalance;
}
double SavingAccount::calculateMonthlyInterset()
{
   
	double monthlyInterest = savingBalance / 12 * annualInterestRate;
	savingBalance += monthlyInterest;
	return savingBalance;
}
void SavingAccount::modifyInterestRate(double interestRate)
{
   
	annualInterestRate = interestRate;
}

6.21

( lntegerSet 类) 创建类lntegerset , 它的每个对象可以存储0 ~ 1 范围内的整数。集合在内部表示为bool 值的一个vector 对象。如果整数i 在这个集合内, 则数组元素aCi ] 是true 。如果整数j 不在这个集合内, 则元素a[jJ 为false 。默认的构造函数将集合初始化为所谓的“ 空集合" , 即其数组表示中所有元素都是false 的集合。
a ) 提供常用集合操作的成员函数。例如, 提供unionOfSets 成员函数, 它生成第三个集合, 这个集合是两个现有集合理论上的并集( 即如果两个现有集合中只要有一个集合的元素为true , 则第三个集合中的数组元素设置为true ; 如果在两个集合中的元素都为false , 则第三个集合中的数组元素设置为false ) 。
b ) 提供intersectionOfSets 的成员函数, 该函数生成第三个集合, 是两个现有集合论上的交集( 即如果两个现有集合中只要有一个集合的元素为false , 则第三个集合中的数组元素设置为false ; 如果在两个集合中的两个元素都为true ,则第三个集合中的数组元素设置为true)
c ) 提供insertElement 成员函数, 它把一个新整数k 插人到集合中( 通过将a [ k ] 设置为true)
d )提供printset 成员函数, 它把集合打印为用空格隔开的数字列表。只打印集合中出现的元素( 即在该对应位置上值为true 的元素) 。对于空集, 则打印—
e ) 提供isEqualTo 函数, 判定两个集合是否相等。
f) 提供另一个构造函数, 它接受一个整数的数组以及该数组的大小, 并使用该数组初始化集合
对象
现在编写一个驱动程序测试你的lntegerset 类。实例化几个IntegerSet 对象, 并且测试你的所有成员函数是否工作正常。

实现代码

ConsoleApplication.cpp

#include <iostream>
#include "IntegerSet.h"
using namespace std;
int main()
{
   
	IntegerSet is1;
	is1.insertElement(1);
	is1.insertElement(1);
	is1.insertElement(2);
	is1.printSet();
	IntegerSet is2;
	is2.insertElement(2);
	is2.insertElement(3);
	is2.printSet();
	IntegerSet is3 = is1.unionOfSets(is2);
	is3.printSet();
	is3 = is1.intersectionOfSets(is2);
	is3.printSet();
	IntegerSet is4;
	is4.insertElement(2);
	cout << "is3 is ";
	if (!is3.isEqualTo(is4))
		cout << "not ";
	cout << "equal to is4." << endl;
	int arr[] = {
    3,1,4,1,5,9,2,6 };
	IntegerSet is5(arr, sizeof(arr) / sizeof(arr[0]));
	is5.printSet();
}

lntegerset.h

#pragma once
#include <vector>
class IntegerSet
{
   
public:
	IntegerSet();
	IntegerSet(int arr[], int n);
	IntegerSet unionOfSets(IntegerSet is1);
	IntegerSet intersectionOfSets(IntegerSet is1);
	void insertElement(int k);
	void printSet();
	bool isEqualTo(IntegerSet is);
	bool get(int index);
private:
	std::vector<bool> a;
};

lntegerset.cpp

#include <iostream>
#include "IntegerSet.h"
using namespace std;

IntegerSet::IntegerSet()
{
   
	for (int i = 0; i < 101; ++i)
	{
   
		a.push_back(false);
	}
}

IntegerSet::IntegerSet(int arr[], int n)
{
   
	for (int i = 0; i < 101; ++i)
	{
   
		a.push_back(false);
	}
	for (int i = 0; i < n; ++i)
	{
   
		a[arr[i]] = true;
	}
}

IntegerSet IntegerSet::unionOfSets(IntegerSet is1)
{
   
	IntegerSet is2;
	for (int i = 0; i < 101; ++i)
	{
   
		if (get(i) || is1.get(i))
		{
   
			is2.insertElement(i);
		}
	}
	return is2;
}

IntegerSet IntegerSet::intersectionOfSets(IntegerSet is1)
{
   
	IntegerSet is2;
	for (int i = 0; i < 101; ++i)
	{
   
		if (get(i) && is1.get(i))
		{
   
			is2.insertElement(i);
		}
	}
	return is2;
}

void IntegerSet::insertElement(int k)
{
   
	a[k] = true;
}

void IntegerSet::printSet()
{
   
	if (a.empty())
	{
   
		cout << "---" << endl;
	}
	else
	{
   
		for (int i = 0; i < 101; ++i)
		{
   
			if (get(i))
			{
   
				cout << i << ' ';
			}
		}
		cout << endl;
	}
}

bool IntegerSet::isEqualTo(IntegerSet is)
{
   
	for (int i = 0; i < 101; ++i)
	{
   
		if (get(i) != is.get(i))
		{
   
			return false;
		}
	}
	return true;
}

bool IntegerSet::get(int index)
{
   
	return a[index];
}

6.23

( 洗牌和发牌) 编写一个洗牌和发牌的程序。这个程序包含类Card 、类DeckOfCards 和一个驱动程序。类Card 有:
a) int 型的数据成员face 和suit 。
b) 接收两个int 型的代表面值和花色的构造函数用于初始化数据成员。
c) 两个string 类型的static 数组代表面值和花***r> d)— 个toString 函数返回Card , 它的形式是“ face of suit ” 的字符串。可以使用+ 运算符连接字符串。
类DeckOfCards 有:
a )一个名为deck 的card 类型的vector , 它用来存储card
b ) 代表下一个将要处理的牌的整型值currentCard
c )一个用来初始化deck 中card 的默认构造函数。构造函数使用vecror 的函数push-back 将产生的牌添加到vector 的末尾。这个过程对于deck 中的52 张牌都要做一遍。
d) 函数sh uffle 用于洗牌。洗牌算法应该在vector 中反复做。对于每张牌, 随机地选取另一张牌,然后交换这两张牌。
e) dealCard 函数返回下一张牌
f) moreCards 函数返回一个bool 值,代表是否还有牌要处理。
驱动程序产生DeckOfCards 对象, 洗牌, 然后发牌。

6.24

(洗牌和发牌)任务:
a) 确定手上是否有一副对子。
b ) 确定手上是否有两副对子。
c) 确定手上是否有3 张同号牌( 如3 张J) 。
d ) 确定手上是否有4 张同号牌( 如4 张。
e ) 确定手上是否有同花( 即5 张牌花色相同) 。
f) 确定是否有同顺( 即5 张面值连续的牌) 。

实现代码

Card.cpp

#include <iostream>
#include <string>
#include "Card.h"
using namespace std;
Card::Card(int Face, int Suit) :face(Face), suit(Suit)
{
   

}
string Card::faces[] = {
    "A","2","3","4","5","6","7","8","9","10","J","Q","K" };
string Card::suits[] = {
    "Spades","Hearts","Diamonds","Clubs" };
string Card::toString()
{
   
	return faces[face - 1] + " of " + suits[suit - 1];
}

int Card::getFace()
{
   
	return face;
}

int Card::getSuit()
{
   
	return suit;
}

Card.h

#pragma once
#include <string>
using namespace std;
class Card
{
   
public:
	Card(int Face, int Suit);
	string toString();
	int getFace();
	int getSuit();
	static string faces[14];
	static string suits[5];
private:
	int face;
	int suit;
	
};

ConsoleApplication.cpp

#include <iostream>
#include <algorithm>
#include "Card.h"
#include "DeckOfCards.h"
using namespace std;
bool oneDuiZi(Card* card)
{
   
	for (int i = 0; i < 5; ++i)
	{
   
		for (int j = i + 1; j < 5; ++j)
		{
   
			if (card[i].getFace() == card[j].getFace())
			{
   
				return true;
			}
		}
	}
	return false;
}

bool twoDuiZi(Card* card)
{
   
	int cnt[13]{
   };
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < 5; ++i)
	{
   
		++cnt[card[i].getFace()-1];
	}
	int ret = 0;
	for (int i : cnt)
	{
   
		if (i >= 2)
		{
   
			++ret;
		}
	}
	return ret >= 2;
}

bool threeTongHao(Card* card)
{
   
	int cnt[13]{
   };
	for (int i = 0; i < 5; ++i)
	{
   
		++cnt[card[i].getFace()-1];
	}
	for (int i : cnt)
	{
   
		if (i >= 3)
		{
   
			return true;
		}
	}
	return false;
}

bool fourTongHao(Card* card)
{
   
	int cnt[13]{
   };
	for (int i = 0; i < 5; ++i)
	{
   
		++cnt[card[i].getFace()-1];
	}
	for (int i : cnt)
	{
   
		if (i >= 4)
		{
   
			return true;
		}
	}
	return false;
}

bool tongHua(Card* card)
{
   
	for (int i = 0; i < 4; ++i)
	{
   
		if (card[i].getSuit() != card[i + 1].getSuit())
		{
   
			return false;
		}
	}
	return true;
}

bool tongShun(Card* card)
{
   
	int a[5]{
   };
	for (int i = 0; i < 5; ++i)
	{
   
		a[i] = card[i].getFace();
	}
	sort(a, a + 4);
	for (int i = 0; i < 4; ++i)
	{
   
		if (a[i] + 1 != a[i + 1])
		{
   
			return false;
		}
	}
	return true;
}

int main()
{
   
	Card card(1, 1);
	cout << card.getFace() << ' ' << card.getSuit() << endl;
	cout << card.toString() << endl << endl;

	DeckOfCards deckOfCards;
	deckOfCards.shuffle();
	Card* cards = deckOfCards.dealCards();
	for (int i = 0; i < 5; ++i)
	{
   
		cout << cards[i].toString() << endl;
	}
	cout << "һ�����ӣ�" << oneDuiZi(cards) << endl;
	cout << "�������ӣ�" << twoDuiZi(cards) << endl;
	cout << "3��ͬ���ƣ�" << threeTongHao(cards) << endl;
	cout << "4��ͬ���ƣ�" << fourTongHao(cards) << endl;
	cout << "ͬ����" << tongHua(cards) << endl;
	cout << "ͬ˳��" << tongShun(cards) << endl;
}

DeckOfCards.cpp

#include <ctime>
#include "DeckOfCards.h"
DeckOfCards::DeckOfCards()
{
   
	for (int i = 0; i < 13; ++i)
	{
   
		for (int j = 0; j < 4; ++j)
		{
   
			Card card(i + 1, j + 1);
			deck.push_back(card);
		}
	}
}

void DeckOfCards::shuffle()
{
   
	srand((unsigned)time(NULL));
	Card card = deck[0];
	while (moreCards())
	{
   
		swap(card, deck[rand() % 52]);
		card = dealCard();
	}
}

Card* DeckOfCards::dealCards()
{
   
	static Card card[5] = {
    deck[0], deck[1], deck[2], deck[3], deck[4] };
	return card;
}

Card DeckOfCards::dealCard()
{
   
	return deck[++currentCard];
}

bool DeckOfCards::moreCards()
{
   
	return currentCard < 51;
}

DeckOfCards.h

#pragma once
#pragma once
#include <vector>
#include "Card.h"
using namespace std;
class DeckOfCards
{
   
public:
	DeckOfCards();
	void shuffle();
	Card* dealCards();
private:
	vector<Card> deck;
	int currentCard = 0;
	Card dealCard();
	bool moreCards();
};