diff --git a/CardGame/.idea/.idea.CardGame/.idea/.gitignore b/CardGame/.idea/.idea.CardGame/.idea/.gitignore new file mode 100644 index 0000000..b856034 --- /dev/null +++ b/CardGame/.idea/.idea.CardGame/.idea/.gitignore @@ -0,0 +1,13 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# Rider 忽略的文件 +/projectSettingsUpdater.xml +/.idea.CardGame.iml +/modules.xml +/contentModel.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/CardGame/.idea/.idea.CardGame/.idea/encodings.xml b/CardGame/.idea/.idea.CardGame/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/CardGame/.idea/.idea.CardGame/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CardGame/.idea/.idea.CardGame/.idea/indexLayout.xml b/CardGame/.idea/.idea.CardGame/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/CardGame/.idea/.idea.CardGame/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/CardGame/.idea/.idea.CardGame/.idea/vcs.xml b/CardGame/.idea/.idea.CardGame/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/CardGame/.idea/.idea.CardGame/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CardGame/CardGame.cpp b/CardGame/CardGame.cpp index 3f47372..f7dc53f 100644 --- a/CardGame/CardGame.cpp +++ b/CardGame/CardGame.cpp @@ -22,7 +22,14 @@ int main() DealCards(N, PA, PB); DispList(*PA); DispList(*PB); - - GamePlay1(*PA,*PB,N); - GamePlay2(*PA,*PB,N); + + cout << "------------------------------" << endl; + cout << "Game Play 1" << endl; + GamePlay1(*PA, *PB, N); + cout << "------------------------------" << endl; + cout << "Game Play 2" << endl; + GamePlay2(*PA, *PB, N); + + DestroyList(*PA); + DestroyList(*PB); } \ No newline at end of file diff --git a/CardGame/CardGame.vcxproj b/CardGame/CardGame.vcxproj index 7b34f64..5869263 100644 --- a/CardGame/CardGame.vcxproj +++ b/CardGame/CardGame.vcxproj @@ -133,7 +133,6 @@ - diff --git a/CardGame/CardGame.vcxproj.filters b/CardGame/CardGame.vcxproj.filters index 7ee0dd6..240ee54 100644 --- a/CardGame/CardGame.vcxproj.filters +++ b/CardGame/CardGame.vcxproj.filters @@ -38,9 +38,6 @@ 头文件 - - 头文件 - 头文件 diff --git a/CardGame/Functions.h b/CardGame/Functions.h index 7ad582e..479c11c 100644 --- a/CardGame/Functions.h +++ b/CardGame/Functions.h @@ -20,12 +20,12 @@ inline void DealCards(int N, SqList*& PA, SqList*& PB) { if (i % 2 == 0) // 发给PA { - InsertElem_i(* PA, j++, num + 1); + InsertElem_i(*PA, j++, num + 1); CardPile[num]--; } else // 发给PB { - InsertElem_i(* PB, k++, num + 1); + InsertElem_i(*PB, k++, num + 1); CardPile[num]--; } break; @@ -41,9 +41,7 @@ inline int FindElem(SqStack& S, int e) { int i = S.top; // 从栈顶开始查找 for (; i >= 0; i--) - { if (S.base[i] == e) return S.top - i; // 返回距离 - } return -1; } @@ -51,4 +49,10 @@ inline int FindElem(SqStack& S, int e) inline bool IsPlayerA(int i) { return i % 2 == 1; +} + +// 返回栈元素数量 +inline int StackSize(SqStack& S) +{ + return S.top + 1; } \ No newline at end of file diff --git a/CardGame/GamePlay1.cpp b/CardGame/GamePlay1.cpp index 66e444b..6fea6eb 100644 --- a/CardGame/GamePlay1.cpp +++ b/CardGame/GamePlay1.cpp @@ -25,9 +25,9 @@ void GamePlay1(SqList PA, SqList PB, int N) // 玩法1初始化 // 对于玩法1,双方均为先抓到的牌先出,赢的牌加在牌尾 SqQueue* QA = new SqQueue; - InitQueue(*QA, 2 * N + 1); + InitQueue(*QA, N * 2 + 1); SqQueue* QB = new SqQueue; - InitQueue(*QB, 2 * N + 1); + InitQueue(*QB, N * 2 + 1); // 将PA和PB的牌分别放入QA和QB for (int i = 1; i <= N; i++) { @@ -95,7 +95,7 @@ void GamePlay1(SqList PA, SqList PB, int N) break; } } - delete Desk; + DestroyStack(*Desk); DestroyQueue(*QA); DestroyQueue(*QB); } \ No newline at end of file diff --git a/CardGame/GamePlay2.cpp b/CardGame/GamePlay2.cpp index 753eda4..d9d56ac 100644 --- a/CardGame/GamePlay2.cpp +++ b/CardGame/GamePlay2.cpp @@ -3,19 +3,70 @@ using namespace std; #include "include/SqList.h" #include "include/SqQueue.h" #include "include/SqStack.h" -#include "include/LinkList.h" #include "FuncRef.h" +#include "Functions.h" + +void DisplayPlayerBCards(int* QB, int N) +{ + for (int i = 0; i < N; i++) + for (int j = 0; j < QB[i]; j++) + cout << i + 1 << " "; + cout << endl; +} + +void DisplayStatus(SqQueue& QA, int* QB, SqStack& Desk, int i, int N) +{ + cout << "------------------------------" << endl; + cout << "Round " << i << endl; + cout << "Player A: "; + DispQueue(QA); + cout << "Player B: "; + DisplayPlayerBCards(QB, N); + cout << "Desk: "; + DispStack(Desk); +} + +bool IsPlayerBWin(int* QB, int N) +{ + for (int i = 0; i < N; i++) + if (QB[i] > 0) return false; + return true; +} + +// 玩家B出牌 +int PlayerBPlay(int* QB, SqStack& Desk, int N) +{ + // 如果栈为空,且B有两张相同面值的牌,则出该面值的牌 + if (StackEmpty(Desk)) + for (int i = 1; i <= N; i++) + if (QB[i - 1] == 2) + return i; + // 如果栈非空,则从栈底遍历,找到第一张手牌中拥有的牌出之 + for (int i = 0; i <= Desk.top; i++) + { + int card = Desk.base[i]; + if (QB[card - 1] > 0) + return card; + } + // 如果以上情况都不满足,则随机出一张牌 + int card; + do + card = rand() % N + 1; + while (QB[card - 1] == 0); + return card; +} void GamePlay2(SqList PA, SqList PB, int N) { SqStack* Desk = new SqStack; // 牌桌上的牌 - InitStack(*Desk, N * 2); + InitStack(*Desk, N * 2 + 1); // 玩法2初始化 // 对于玩法2,PA为先抓到的牌先出,赢的牌加在牌尾;PB为任意出牌 SqQueue* QA = new SqQueue; - InitQueue(*QA, N + 1); - LNode* QB; - InitList(QB); + InitQueue(*QA, N * 2 + 1); + // PB手牌存储方式:下标为面值-1,值为张数 + int* QB = new int[N]; + for (int i = 0; i < N; i++) QB[i] = 0; // 将PA的牌放入QA for (int i = 1; i <= N; i++) { @@ -28,8 +79,68 @@ void GamePlay2(SqList PA, SqList PB, int N) { int e = 0; GetElem_i(PB, i, e); - InsertElem_i(QB, i, e); + QB[e - 1]++; } - DispQueue(*QA); - DispList(QB); + // Step2 玩牌 + int a = 0, b = 0, i = 0; // i的奇偶性决定出牌方 + while (true) + { + int x = 0; + // 双方交替出牌 + if (i++ % 2 == 0) { + DeQueue(*QA, a); + x = a; + } + else { + b = PlayerBPlay(QB, *Desk, N); + QB[b - 1]--; + x = b; + } + // 如果桌面上没有面值为X的牌,则将牌放到牌桌上 + if (FindElem(*Desk, x) == -1) Push(*Desk, x); + // 如果桌面上有面值为X的牌 + else + { + int times = FindElem(*Desk, x); + if (IsPlayerA(i)) // 如果是A出的牌 + { + // 将X放入牌尾 + EnQueue(*QA, x); + // 将桌面上直到X的牌依次放入牌尾 + for (int j = 0; j <= times; j++) + { + int e = 0; + Pop(*Desk, e); + EnQueue(*QA, e); + } + } + else // 如果是B出的牌 + { + // 将X放入手牌 + QB[x - 1]++; + // 将桌面上直到X的牌依次放入手牌 + for (int j = 0; j <= times; j++) + { + int e = 0; + Pop(*Desk, e); + QB[e - 1]++; + } + } + } + DisplayStatus(*QA, QB, *Desk, i, N); + // 判断是否有一方获胜 + if (QueueEmpty(*QA)) + { + cout << "Player B wins!" << endl; + break; + } + else if (IsPlayerBWin(QB, N)) + { + cout << "Player A wins!" << endl; + break; + } + } + DestroyStack(*Desk); + DestroyQueue(*QA); + delete[] QB; } \ No newline at end of file diff --git a/CardGame/include/LinkList.h b/CardGame/include/LinkList.h deleted file mode 100644 index a5833a6..0000000 --- a/CardGame/include/LinkList.h +++ /dev/null @@ -1,255 +0,0 @@ -#pragma once -#include - -template -struct LNode //链表结点 -{ - DT data; //数据域,存储数据元素值 - LNode* next; //指针域,指向下一个结点 -}; - -//算法2.1 -template -bool PriorElem_e(LNode
* L, DT e, DT& pre_e) // 求值为e的元素前驱 -{ - int k; - k = LocateElem_e(L, e); // 1.获取e的位序k - if (k > 1) // 2.位序k大于1 - { - GetElem_i(L, k - 1, pre_e); // 第k-1个元素为e的前驱 - return true; - } - else // 3.元素e无前驱 - return false; // 返回false -} - -//【算法2.14】 创建空单链表 -template -bool InitList(LNode
*& L) -{ - L = new LNode
; // 1.创建头结点 - if (!L) exit(1); // 2.创建失败,退出 - L->next = NULL; // 3.创建成功 - return true; // 返回true -} - -//【算法2.15】 尾插法创建n的元素 -template -bool CreateList_1(LNode
*& L, int n) -{ - int i; - LNode
* p, * s; - p = L; //1.工作指针初始化,指向尾结点 - cout << "依次输入" << n << "个数据元素:" << endl; - for (i = 1; i <= n; i++) // 2.按元素位序正序创建各结点 - { - s = new LNode
; // 2.1 新建一个结点s - if (!s) // 2.2 创建失败,返回false - return false; - cin >> s->data; // 2.3 输入结点值 - s->next = p->next; // 2.4 s 链在表尾 - p->next = s; - p = s; // 2.5 工作指针指向 s - } - return true; // 3.创建成功,返回true -} - -//【算法2.16】 头插法创建n个元素 -template -bool CreateList_2(LNode
* (&L), int n) -{ - int i; - LNode
* s; - cout << "逆序输入" << n << "个数据元素:" << endl; - for (i = 1; i <= n; i++) // 1.按元素位序逆序创建各结点 - { - s = new LNode
; // 1.1 新建一个结点 s - if (!s) // 1.2 创建失败,返回false - return false; - cin >> s->data; // 1.3 输入结点值 - s->next = L->next; // 1.4 s 在头结点后 - L->next = s; - } - return true; // 1.创建成功,返回true -} - -//【算法2.17】 -template -void DestroyList(LNode
* (&L)) // 释放链表所占空间 -{ - LNode
* p; - while (L) // 1. 表非空,从头结点开始,依次释放结点 - { - p = L; // 1.1 处理表头结点 - L = L->next; // 1.2 头指针后移 - delete p; // 1.3 释放表头结点所占内存 - } - L = NULL; // 2.头指针指向空 -} - -//【算法2.18】 获取第i个元素 -template -bool GetElem_i(LNode
* L, int i, DT& e) -{ - LNode
* p; // 1.初始化 - p = L->next; // 1.1 设置工作指针,从首结点开始数结点 - int j = 1; // 1.2 计数器初始化 - while (p && j < i) // 2.定位到第i个元素结点 - { - p = p->next; j++; - } - if (!p || j > i) // 3 未找到,返回false - return false; - else // 4. 找到 - { - e = p->data; // 获取第i个元素值 - return true; // 返回true - } -} - -//【算法2.19】 查找值为e的元素位序 -template -int LocateElem_e(LNode
* L, DT e) -{ - - LNode
* p; // 1.初始化从首元开始查找 - p = L->next; // 1.1从首元开始查找 - int j = 1; // 1.2 计数器初值 - while (p && p->data != e) // 2.顺序查找 - { - p = p->next; // 2.1未找到指针后移 - j++; // 2.2 计数器增1 - } - if (p == NULL) // 3. 判断是否找到 - return 0; // 3.1末找到,返回0 - else - return j; // 3.2 找到,返回位序 -} - -//【算法2.20】 插入第i个元素 -template -bool InsertElem_i(LNode
*& L, int i, DT e) -{ - - int j = 0; - LNode
* p; // 1.初始化 - p = L; // 工作指针初始化 - while (p && j < i - 1) // 2. 定位到插入点前驱 - { - p = p->next; - j++; - } - if (!p || j > i - 1) // 3.判断定位是否成功: - return false; // 3.1 定位失败,不能插入 - else // 3.2 定位成功 - { - LNode
* s; - s = new LNode
; // 3.2.1建立新结点 - s->data = e; // 3.2.2新结点赋值 - s->next = p->next; // 3.2.3结点S链接到p结点之后 - p->next = s; - return true; // 3.2.4 插入成功,返回true - } - -} - -//【算法2.21】 删除第i个元素 -template -bool DeleElem_i(LNode
* (&L), int i) -{ - - LNode
* p, * q; //1.初始化:设置工作指针 - p = L; //查找从头结点开始 - int j = 0; //计数器初始化 - while (p->next && j < i - 1) //2.p定位到删除点的前驱 - { - p = p->next; - j++; - } - if (!p->next || j > i - 1) //3.删除位置不合理,不能删除 - return false; //返回false - else //4.删除操作 - { - q = p->next; //4.1暂存删除结点位置 - p->next = q->next; //4.2从链表中摘除删除结点 - delete q; - return true; //4.3删除成功,返回true - } -} - - -//【算法2.22】 修改第i个元素值 -template -bool PutElem_i(LNode
* (&L), int i, DT e) -{ - LNode
* p; // 1.初始化:设置工作指针 - p = L->next; // 从首结点开始,数结点 - int j = 1; // 计数器初始化 - while (p && j < i) // 2.查找第i个元素结点 - { - p = p->next; j++; - } - if (!p || j > i) // 3.元素不存在,返回false - return false; - else // 4.定位成功 - { - p->data = e; // 修改元素值 - return true; // 返回true - } -} - -// 释放链表所占空间 -template -void ClearList(LNode
* (&L)) -{ - - LNode
* p; - while (L->next) // 从首元结点开始,依次释放结点 - { - p = L->next; - L->next = p->next; - delete p; - } - cout << endl << "表已清空!" << endl; -} - - -//【算法2.23】 测表长 -template -int ListLength(LNode
* L) -{ // 1.初始化 - int len = 0; // 1.1 结点计数器赋初值0 - LNode
* p; // 1.2设置工作指针 - p = L; // 指向头结点 - while (p->next) // 2.数结点个数。有后继结点, - { - len++; p = p->next; // 结点数增1,指针后移 - } - return len; // 3.返回表长 -} - -// -template -bool ListEmpty(LNode
* L) //测表空 -{ - if (L->next == NULL) - return true; //空表,返回1 - else - return false; //不空,返回0 -} - - -//【算法2.24】 遍历表 -template -void DispList(LNode
* L) // 显示表内容 -{ - LNode
* p; // 1. 设置工作指针 - p = L; // 从首元结点开始遍历 - while (p->next) // 2.依次输出各结点值 - { - p = p->next; cout << p->data << " "; - - - } - cout << endl; -} diff --git a/ExpReportTemplate.dotx b/ExpReportTemplate.dotx new file mode 100644 index 0000000..d92ed53 Binary files /dev/null and b/ExpReportTemplate.dotx differ