连连看小游戏改进
为了使游戏符合一般连连看的游戏法则,将之前删去的判定规则又添加回来
bool canConnect(int x1, int y1, int x2, int y2) { num = 0; int x_num = abs(x1 - x2); int y_num = abs(y1 - y2); int x1_ = x1, x2_ = x2, y1_ = y1, y2_ = y2; justic = vector<vector<bool>>(rows, vector<bool>(cols)); for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) justic[i][j] = false; if (board[x1][y1] != board[x2][y2]) return false; if ((x_num == 1 && y_num == 0) || (x_num == 0 && y_num == 1)) return true; else { if (!have_path(x1_, x2_, y1_, y2_)) return false; else return true; } }
两个块相邻或者他们之间有空块可以联通,都可以消去
判断是否有空块路径的代码如下
bool have_path(int x1, int x2, int y1, int y2) { if (x1 == x2 && y1 == y2) return true; if (x1 < 0 || x1 >= rows || x2 < 0 || x2 >= rows || y1 < 0 || y1 >= cols || y2 < 0 || y2 >= cols || justic[x1][y1] || (num++ != 0 && board[x1][y1] != 0)) return false; justic[x1][y1] = true; bool mapi = have_path(x1 + 1, x2, y1, y2) || have_path(x1 - 1, x2, y1, y2) || have_path(x1, x2, y1 + 1, y2) || have_path(x1, x2, y1 - 1, y2); return mapi; }
完整代码如下
#include <iostream> #include <cstdlib> #include <ctime> #include <chrono> #include <vector> #include <algorithm> using namespace std; int k = 0; int INITIAL_ROWS = 4; int INITIAL_COLS = 4; int TIME_LIMIT = 120; // 游戏时间限制,单位:秒 const int SCORE_PER_PAIR = 10; // 每成功配对一对方块的得分 const int MAX_REFRESHES = 3; // 最大刷新次数 class Game { private: int num; int rows; int cols; vector<vector<int>> board; int score; int refreshesLeft; chrono::steady_clock::time_point startTime; int level; vector<vector<bool>> justic; public: Game() : rows(INITIAL_ROWS), cols(INITIAL_COLS), level(1) { score = 0; refreshesLeft = MAX_REFRESHES; initializeBoard(); startTime = chrono::steady_clock::now(); } void initializeBoard() { srand(time(0)); board = vector<vector<int>>(rows, vector<int>(cols)); vector<int> numbers; for (int i = 0; i < (rows * cols) / 2; ++i) { int num = rand() % 5 + 1; // 随机生成1到10之间的数字 numbers.push_back(num); numbers.push_back(num); } random_shuffle(numbers.begin(), numbers.end()); int k = 0; for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { board[i][j] = numbers[k++]; } } } void displayTimeLeft(int timeLeft) { cout << "剩余时间: " << timeLeft << "s" << endl; } void displayBoard() { auto currentTime = chrono::steady_clock::now(); int elapsedTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime).count(); int timeLeft = TIME_LIMIT - elapsedTime; cout << "得分 " << score << " 剩余时间 " << timeLeft << "s" << " 等级 " << level << endl; cout << endl; for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { if (board[i][j] == 0) { cout << "· "; // 已消除的块用"."表示 } else { // 使用ANSI转义码添加颜色 switch (board[i][j]) { case 1: cout << "\033[31m" << board[i][j] << "\033[0m "; // 红色 break; case 2: cout << "\033[32m" << board[i][j] << "\033[0m "; // 绿色 break; case 3: cout << "\033[33m" << board[i][j] << "\033[0m "; // 黄色 break; case 4: cout << "\033[34m" << board[i][j] << "\033[0m "; // 蓝色 break; case 5: cout << "\033[35m" << board[i][j] << "\033[0m "; // 紫色 break; default: cout << board[i][j] << " "; // 默认颜色 break; } } } cout << endl; cout << endl; } } bool isValidCoordinate(int x, int y) { return x >= 1 && x <= rows && y >= 1 && y <= cols; } bool have_path(int x1, int x2, int y1, int y2) { if (x1 == x2 && y1 == y2) return true; if (x1 < 0 || x1 >= rows || x2 < 0 || x2 >= rows || y1 < 0 || y1 >= cols || y2 < 0 || y2 >= cols || justic[x1][y1] || (num++ != 0 && board[x1][y1] != 0)) return false; justic[x1][y1] = true; bool mapi = have_path(x1 + 1, x2, y1, y2) || have_path(x1 - 1, x2, y1, y2) || have_path(x1, x2, y1 + 1, y2) || have_path(x1, x2, y1 - 1, y2); return mapi; } bool canConnect(int x1, int y1, int x2, int y2) { num = 0; int x_num = abs(x1 - x2); int y_num = abs(y1 - y2); int x1_ = x1, x2_ = x2, y1_ = y1, y2_ = y2; justic = vector<vector<bool>>(rows, vector<bool>(cols)); for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) justic[i][j] = false; if (board[x1][y1] != board[x2][y2]) return false; if ((x_num == 1 && y_num == 0) || (x_num == 0 && y_num == 1)) return true; else { if (!have_path(x1_, x2_, y1_, y2_)) return false; else return true; } } void removeBlock(int x, int y) { board[x][y] = 0; // 使用0表示空块 } bool isBoardEmpty() { for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { if (board[i][j] != 0) { return false; } } } return true; } bool hasMoreMoves() { for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { if (board[i][j] != 0) { for (int k = i; k < rows; ++k) { for (int l = (k == i ? j + 1 : 0); l < cols; ++l) { if (board[k][l] != 0 && canConnect(i, j, k, l)) { return true; } } } } } } return false; } void refreshBoard() { initializeBoard(); cout << "这个棋盘刷新了哦" << endl; } void increaseDifficulty() { ++level; INITIAL_ROWS += k; INITIAL_COLS += k; rows = INITIAL_ROWS; cols = INITIAL_COLS; refreshesLeft = MAX_REFRESHES; board.clear(); // 清空游戏板 // 重新初始化游戏板 srand(time(0)); board = vector<vector<int>>(rows, vector<int>(cols)); vector<int> numbers; for (int i = 0; i < (rows * cols) / 2; ++i) { int num = rand() % 5 + 1; // 随机生成1到5之间的数字 numbers.push_back(num); numbers.push_back(num); } random_shuffle(numbers.begin(), numbers.end()); int k = 0; for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { board[i][j] = numbers[k++]; } } TIME_LIMIT += 20; startTime = chrono::steady_clock::now(); cout << "难度提升,等级 " << level << "!" << endl; play(); } void play() { bool justPaired = false; while (1) { auto currentTime = chrono::steady_clock::now(); int elapsedTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime).count(); int timeLeft = TIME_LIMIT - elapsedTime; displayBoard(); int choice; if (!justPaired && refreshesLeft > 0) { cout << "你还有" << refreshesLeft << "次刷新机会,按1刷新游戏,按0进入游戏: "; cin >> choice; if (choice == 1 && refreshesLeft > 0 && !justPaired) { refreshBoard(); refreshesLeft--; continue; } } else { } if (timeLeft <= 0) { cout << "时间到了兄弟" << endl; break; } if (!hasMoreMoves()) { cout << "我看是移动不了了兄弟,重开吧" << endl; break; } int x1, y1, x2, y2; cout << "请输入第一个坐标(x y): "; cin >> x1 >> y1; cout << "请输入第二个坐标(x y): "; cin >> x2 >> y2; if (x1 == x2 && y1 == y2) { cout << "请连接两个点" << endl; justPaired = true; continue; } if (!isValidCoordinate(x1, y1) || !isValidCoordinate(x2, y2)) { cout << "无效坐标,请重新输入" << endl; justPaired = true; continue; // 回到循环开始处重新获取用户输入 } // 调整输入,使之从1开始计数转换为从0开始计数 x1 -= 1; y1 -= 1; x2 -= 1; y2 -= 1; if (canConnect(x1, y1, x2, y2)) { justPaired = true; removeBlock(x1, y1); removeBlock(x2, y2); score += SCORE_PER_PAIR; if (isBoardEmpty()) { cout << "祝贺你,你做到了" << endl; k = k + 2; increaseDifficulty(); } } else { score -= 5; justPaired = true; cout << "失败了,兄弟,再试试" << endl; } } cout << "你的最终得分是: " << score << endl; } }; int main() { cout << "欢迎来到胡管的地狱游戏!!!" << endl; cout << "规则如下:" << endl; cout << "1. 连接两个水平或垂直相邻的匹配块,或者是中间存在空块的相同数字的方块。" << endl; cout << "2. 连接正确得分+10,连接错误得分-5。" << endl; cout << "3. 你现在有 " << TIME_LIMIT << " 秒去清除块。" << endl; cout << "4. 你目前有 " << MAX_REFRESHES << " 次机会刷新游戏,记住按1刷新游戏。" << endl; cout << "5. 输入坐标为(x y),其中x和y从1开始。" << endl; cout << "6. 通关当前关卡后难度升级。" << endl; cout << "==========================================" << endl; Game game; game.play(); return 0; }