Files
BasicsOfComputerSoftwareEng…/OOP/01/Exercise02.cpp
2023-02-23 15:18:42 +08:00

461 lines
13 KiB
C++

#include <iostream>
#include <string>
#define BLACK false
#define WHITE true
// 还没有实现判定输赢
// todo: 棋盘满时判定和棋
// clang-format off
std::string boardTitle = " 1 2 3 4 5 6 7 8 9 A B C D E F";
char emptyBoardString[3][29][4] = {
{
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
},
{
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
},
{
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
}
};
// clang-format on
enum putChessPieceResult { failed, success, win, fullBoard };
class ChessPiece {
private:
bool color;
bool isEmptyStatus;
bool isWinStatus;
public:
void init() {
this->isEmptyStatus = true;
this->isWinStatus = false;
this->color = BLACK;
}
void setColor(bool newColor) {
this->isEmptyStatus = false;
this->color = newColor;
}
void setWin() {
this->isWinStatus = true;
}
bool isEmpty() {
return this->isEmptyStatus;
}
bool getColor() {
return this->color;
}
std::string show() {
if (this->isWinStatus) {
return "X";
}
if (this->color == BLACK) {
return "";
}
else {
return "";
}
}
};
class ChessBoard {
private:
ChessPiece ChessPieces[15][15];
int chessCount;
char toHex(int num) {
if (num < 10) {
return num + '0';
}
else {
return num - 10 + 'A';
}
}
public:
void init() {
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
this->ChessPieces[i][j].init();
}
}
this->chessCount = 0;
}
void show() {
std::cout << boardTitle << std::endl;
for (int i = 0; i < 15; i++) {
std::cout << this->toHex(i + 1) << ' ';
char(*emptyLineRef)[29][4] = NULL;
if (i == 0) {
emptyLineRef = &emptyBoardString[0];
}
else if (i == 14) {
emptyLineRef = &emptyBoardString[2];
}
else {
emptyLineRef = &emptyBoardString[1];
}
int j = 0;
for (; j < 15; j++) {
if (this->ChessPieces[i][j].isEmpty()) {
std::cout << (*emptyLineRef)[j * 2];
}
else {
std::cout << this->ChessPieces[i][j].show();
}
if (j < 14) {
std::cout << (*emptyLineRef)[j * 2 + 1];
}
}
std::cout << std::endl;
}
}
// Returns true if success, returns false if not
bool setChess(bool color, int row, int column) {
if (row > 14 || row < 0 || column > 14 || column < 0) {
std::cout << "Out of border!" << std::endl;
return false;
}
if (!this->ChessPieces[row][column].isEmpty()) {
std::cout << "There already is a chess piece!" << std::endl;
return false;
}
this->ChessPieces[row][column].setColor(color);
this->chessCount++;
return true;
}
void reset() {
this->init();
}
bool isFull() {
return this->chessCount == 15 * 15;
}
bool checkWinner(int row, int column, bool color) {
int connetCount = 0;
int i = row, j = column;
int possiblePieces[9][2] = {0};
// vertical
for (; i < 15; i++) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
}
for (i = row - 1; i >= 0; i--) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
}
if (connetCount >= 5) {
for (connetCount--; connetCount >= 0; connetCount--) {
this->ChessPieces[possiblePieces[connetCount][0]]
[possiblePieces[connetCount][1]]
.setWin();
}
return true;
}
// horizontal
i = row;
j = column;
connetCount = 0;
for (; j < 15; j++) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
}
for (j = column - 1; j >= 0; j--) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
}
if (connetCount >= 5) {
for (connetCount--; connetCount >= 0; connetCount--) {
this->ChessPieces[possiblePieces[connetCount][0]]
[possiblePieces[connetCount][1]]
.setWin();
}
return true;
}
// left-up
i = row;
j = column;
connetCount = 0;
while (i < 15 && j < 15) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
i++;
j++;
}
i = row - 1;
j = column - 1;
while (i >= 0 && j >= 0) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
i--;
j--;
}
if (connetCount >= 5) {
for (connetCount--; connetCount >= 0; connetCount--) {
this->ChessPieces[possiblePieces[connetCount][0]]
[possiblePieces[connetCount][1]]
.setWin();
}
return true;
}
// right-up
i = row;
j = column;
connetCount = 0;
while (i >= 0 && j < 15) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
i--;
j++;
}
i = row + 1;
j = column - 1;
while (i < 15 && j >= 0) {
if (this->ChessPieces[i][j].isEmpty()) {
break;
}
if (this->ChessPieces[i][j].getColor() == color) {
possiblePieces[connetCount][0] = i;
possiblePieces[connetCount][1] = j;
connetCount++;
}
else {
break;
}
i++;
j--;
}
if (connetCount >= 5) {
for (connetCount--; connetCount >= 0; connetCount--) {
this->ChessPieces[possiblePieces[connetCount][0]]
[possiblePieces[connetCount][1]]
.setWin();
}
return true;
}
return false;
}
};
class Player {
private:
ChessBoard *board;
std::string playerName;
bool chessType;
int toInt(char input) {
if ('1' <= input && input <= '9') {
return input - '1';
}
else if ('A' <= input && input <= 'F') {
return input - 'A' + 9;
}
else if ('a' <= input && input <= 'f') {
return input - 'a' + 9;
}
else {
return -1;
}
}
public:
void init(std::string name, bool type, ChessBoard *chessBoard) {
this->playerName = name;
this->chessType = type;
this->board = chessBoard;
}
std::string getName() {
return this->playerName;
}
bool getColor() {
return this->chessType;
}
putChessPieceResult setChess(char row, char column) {
int rowCount, columnCount;
rowCount = toInt(row);
columnCount = toInt(column);
if (!this->board->setChess(chessType, rowCount, columnCount)) {
return failed;
}
if (this->board->checkWinner(rowCount, columnCount, this->chessType)) {
std::cout << "\n####################\n"
<< this->playerName << " wins!" << std::endl
<< "####################\n";
return win;
}
if (this->board->isFull()) {
std::cout << "Board is full. Tie!" << std::endl;
return fullBoard;
}
else {
return success;
}
}
};
int main() {
ChessBoard aBoard;
aBoard.init();
aBoard.show();
Player players[2];
{
std::string temp = "";
std::cout << "Player 1 name: ";
std::cin >> temp;
players[0].init(temp, BLACK, &aBoard);
std::cout << "Player 2 name: ";
std::cin >> temp;
players[1].init(temp, WHITE, &aBoard);
}
putChessPieceResult result;
bool nowMovePlayerIndex = false;
do {
std::cout << players[nowMovePlayerIndex].getName() << " ["
<< (players[nowMovePlayerIndex].getColor() ? "◯White"
: "⬤Black")
<< "]: "
<< "Please enter the coordinate of your new chess piece."
<< std::endl;
char row, column;
std::cout << "Row No. ";
std::cin >> row;
fflush(stdin);
while (!(('1' <= row && row <= '9') || ('A' <= row && row <= 'F') ||
('a' <= row && row <= 'f'))) {
std::cout << "Not a valid row number. Try again." << std::endl;
std::cout << "Row No. ";
std::cin >> row;
fflush(stdin);
}
std::cout << "Column No. ";
std::cin >> column;
fflush(stdin);
while (!(('1' <= row && row <= '9') || ('A' <= row) && (row <= 'F') ||
('a' <= row && row <= 'f'))) {
std::cout << "Not a valid column number. Try again." << std::endl;
std::cout << "Column No. ";
std::cin >> column;
fflush(stdin);
}
result = players[nowMovePlayerIndex].setChess(row, column);
if (result == failed) {
continue;
}
else if (result == success) {
nowMovePlayerIndex ^= 1;
aBoard.show();
continue;
}
else {
aBoard.show();
char input;
do {
std::cout << "Reset for another round? (y/n) ";
input = getchar();
fflush(stdin);
} while (input != 'y' && input != 'Y' && input != 'n' &&
input != 'N');
if (input == 'y' || input == 'Y') {
aBoard.reset();
aBoard.show();
continue;
}
else {
break;
}
}
} while (true);
return 0;
}