多米诺骨牌程序开发问题:vector传递与游戏启动逻辑困惑
解决多米诺骨牌程序的两个核心问题
嘿,我来帮你搞定这两个开发中的问题,结合你的游戏规划给你具体的解决方案:
问题1:无法将vector从shuffle函数传入printDom,仅需显示playerDom
这个问题大概率是vector的传递方式或者函数参数匹配出了问题。你需要确保shuffle后的playerDom能正确传递到printDom,并且printDom只处理这个vector。
核心解决方案:
- 用引用传递避免vector拷贝:如果shuffle函数是修改
playerDom,直接传引用,这样修改会直接作用在原vector上,不需要返回值。 - 确保
printDom的参数就是playerDom,并且只遍历这个vector输出。
代码示例:
首先定义你的骨牌结构体(假设你还没定义):
struct Domino { int left; int right; Domino(int l, int r) : left(l), right(r) {} };
然后是洗牌函数(C++11+推荐用shuffle代替旧的random_shuffle):
#include <vector> #include <random> #include <algorithm> #include <iostream> using namespace std; // 洗牌函数:传引用修改原playerDom void shuffleDominoes(vector<Domino>& playerDom) { random_device rd; mt19937 gen(rd()); // 生成随机数引擎 shuffle(playerDom.begin(), playerDom.end(), gen); } // 打印玩家骨牌的函数:仅接收playerDom并输出 void printDom(const vector<Domino>& playerDom) { cout << "你的骨牌:"; for (const auto& dom : playerDom) { cout << "[" << dom.left << "|" << dom.right << "] "; } cout << endl; }
调用方式(确保shuffle后直接传playerDom给printDom):
int main() { // 初始化玩家骨牌(示例:先加几张测试) vector<Domino> playerDom; playerDom.emplace_back(1,2); playerDom.emplace_back(3,4); playerDom.emplace_back(5,6); // 洗牌 shuffleDominoes(playerDom); // 打印玩家骨牌 printDom(playerDom); // 其他逻辑... return 0; }
这样就能保证printDom只显示playerDom的内容,不会出现传递失效的问题。
问题2:如何启动游戏并实现你的规划逻辑
根据你的游戏规划,我整理了一套完整的游戏启动和运行流程,包含初始化、回合循环、胜负判断的核心逻辑:
游戏核心流程步骤:
- 初始化所有骨牌:生成标准28张多米诺骨牌(从[0|0]到[6|6])
- 洗牌并分配骨牌:洗牌后给玩家和电脑各分7张,剩余的作为抽牌堆,选一张作为起始骨牌放入
playedDom - 游戏主循环:交替进行玩家和电脑回合,直到某一方骨牌为空
- 玩家/电脑回合:判断是否有可匹配首尾点数的骨牌,有则放到
playedDom的头部或尾部;没有则抽牌(抽牌堆空则跳过回合) - 胜负判断:每次回合后检查
playerDom或computerDom是否为空,为空则对应方获胜
- 玩家/电脑回合:判断是否有可匹配首尾点数的骨牌,有则放到
完整代码框架示例:
#include <vector> #include <random> #include <algorithm> #include <iostream> #include <iterator> using namespace std; struct Domino { int left; int right; Domino(int l, int r) : left(l), right(r) {} }; // 洗牌函数(通用,可洗任意骨牌vector) void shuffleDominoes(vector<Domino>& dominoes) { random_device rd; mt19937 gen(rd()); shuffle(dominoes.begin(), dominoes.end(), gen); } // 打印骨牌的通用函数(可传任意骨牌vector) void printDom(const vector<Domino>& dominoes, const string& label) { cout << label << ":"; for (const auto& dom : dominoes) { cout << "[" << dom.left << "|" << dom.right << "] "; } cout << endl; } int main() { // -------------------------- 1. 初始化所有骨牌 -------------------------- vector<Domino> allDominoes; for (int i = 0; i <= 6; ++i) { for (int j = i; j <= 6; ++j) { allDominoes.emplace_back(i, j); } } // -------------------------- 2. 洗牌并分配骨牌 -------------------------- shuffleDominoes(allDominoes); vector<Domino> playerDom; vector<Domino> computerDom; vector<Domino> playedDom; // 玩家和电脑各拿7张 for (int i = 0; i < 7; ++i) { playerDom.push_back(allDominoes.back()); allDominoes.pop_back(); computerDom.push_back(allDominoes.back()); allDominoes.pop_back(); } // 设置起始骨牌(从剩余堆拿第一张) if (!allDominoes.empty()) { playedDom.push_back(allDominoes.back()); allDominoes.pop_back(); } printDom(playedDom, "起始骨牌"); printDom(playerDom, "你的初始骨牌"); // -------------------------- 3. 游戏主循环 -------------------------- bool gameRunning = true; while (gameRunning) { // 检查胜负 if (playerDom.empty()) { cout << "\n🎉 你赢了!" << endl; gameRunning = false; break; } if (computerDom.empty()) { cout << "\n😢 电脑赢了!" << endl; gameRunning = false; break; } // -------------------------- 玩家回合 -------------------------- cout << "\n===== 你的回合 =====" << endl; printDom(playedDom, "当前已出牌"); int headVal = playedDom.front().left; int tailVal = playedDom.back().right; cout << "可匹配点数:头部[" << headVal << "] | 尾部[" << tailVal << "]" << endl; printDom(playerDom, "你的骨牌"); bool playerPlayed = false; int choice; cout << "请输入要出的骨牌索引(从0开始,输入-1抽牌):"; cin >> choice; if (choice == -1) { // 抽牌逻辑 if (!allDominoes.empty()) { playerDom.push_back(allDominoes.back()); allDominoes.pop_back(); cout << "你抽了一张骨牌!" << endl; printDom(playerDom, "你的骨牌"); } else { cout << "没有骨牌可抽,跳过回合!" << endl; } } else if (choice >= 0 && choice < playerDom.size()) { Domino chosen = playerDom[choice]; bool canPlace = false; // 判断是否能放头部 if (chosen.left == headVal) { swap(chosen.left, chosen.right); playedDom.insert(playedDom.begin(), chosen); canPlace = true; } else if (chosen.right == headVal) { playedDom.insert(playedDom.begin(), chosen); canPlace = true; } // 判断是否能放尾部 else if (chosen.left == tailVal) { playedDom.push_back(chosen); canPlace = true; } else if (chosen.right == tailVal) { swap(chosen.left, chosen.right); playedDom.push_back(chosen); canPlace = true; } if (canPlace) { playerDom.erase(playerDom.begin() + choice); cout << "你出了骨牌:[" << chosen.left << "|" << chosen.right << "]" << endl; playerPlayed = true; } else { cout << "这张骨牌无法匹配,重新选择!" << endl; continue; // 回到输入步骤 } } else { cout << "无效索引,请重新输入!" << endl; continue; } // -------------------------- 电脑回合 -------------------------- cout << "\n===== 电脑回合 =====" << endl; bool computerPlayed = false; for (auto it = computerDom.begin(); it != computerDom.end(); ++it) { Domino chosen = *it; bool canPlace = false; // 检查头部匹配 if (chosen.left == headVal || chosen.right == headVal) { if (chosen.left == headVal) swap(chosen.left, chosen.right); playedDom.insert(playedDom.begin(), chosen); canPlace = true; } // 检查尾部匹配 else if (chosen.left == tailVal || chosen.right == tailVal) { if (chosen.right == tailVal) swap(chosen.left, chosen.right); playedDom.push_back(chosen); canPlace = true; } if (canPlace) { computerDom.erase(it); cout << "电脑出了骨牌:[" << chosen.left << "|" << chosen.right << "]" << endl; computerPlayed = true; break; } } if (!computerPlayed) { if (!allDominoes.empty()) { computerDom.push_back(allDominoes.back()); allDominoes.pop_back(); cout << "电脑抽了一张骨牌!" << endl; } else { cout << "电脑没有骨牌可抽,跳过回合!" << endl; } } } return 0; }
关键细节说明:
- 骨牌匹配时需要考虑翻转:比如已出牌头部是3,玩家的骨牌是[5|3],可以直接放头部;如果是[3|5],需要翻转成[5|3]再放头部
- 抽牌堆空了之后,无法抽牌的玩家/电脑直接跳过回合
- 每次回合后都要检查胜负条件,确保游戏能及时结束
内容的提问来源于stack exchange,提问作者jgato
相关产品推荐
相关产品推荐

