大家好,欢迎来到IT知识分享网。
(封面图片来源于网络侵权删)
关于灵感
小学时不知道同学从哪里带回来的游戏,规则是这样的:
两个玩家首先比出两个1的手势,情况是这样的:
a玩家:左手:1,右手:1
b玩家:左手:1,右手:1
然后决定先后顺序,依次在每个自己的回合做出一下行动:使用自己的左手或右手碰一下对方的左手或右手,然后将碰到的两只手所表示的数值相加,自己碰的那只手就变为该数值。如:
原局面:
a玩家:左手:1,右手:1
b玩家:左手:1,右手:1
a玩家使用左手碰了对方的右手后:
a玩家:左手:1+1=2,右手:1
b玩家:左手:1,右手:1
到b玩家时,b玩家可以用左手碰对方的右手:
a玩家:左手:2,右手:1
b玩家:左手:3,右手:1
谁先将两只手都到达目标数字(一般是10)就赢了
我在一次某讲座上和同学玩这个游戏时突然想到,这个游戏有没有必胜的策略?遂作此程序。(不知道这算不算博弈论了反正先当标题党写上吧)
思路
那当然是!dfs直接打爆力求解!
这部分没什么好说的,不会的可以去我的专栏或B站
于是我们得到以下代码:
#include "bits/stdc++.h" #include <conio.h> #include <windows.h> using namespace std; bool handMarker[20][20][20][20]; int endNumber, aLeftHand, aRightHand, bLeftHand, bRightHand; int aMayWin = 0, bMayWin = 0; void color(int m) { HANDLE consolehend; consolehend = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(consolehend, m); } void dfs(int aLeftHand, int aRightHand, int bLeftHand, int bRightHand, int step) { // 成功后输出 if ((aLeftHand == endNumber && aRightHand == endNumber) || (bLeftHand == endNumber && bRightHand == endNumber)) { if ((step - 1) % 2 == 0) { aMayWin++; } else { bMayWin++; } // color(0x02); for (int i = 1; i <= step - 1; i++) { printf(u8"│ "); } printf(u8"├─"); printf(u8"%c:Win!:)\n", (step - 1) % 2 + 'a'); for (int i = 1; i <= step - 1; i++) { printf(u8"│ "); } printf(u8"└─"); printf(u8"Used Step: %d.\n", step); // color(0x0F); return ; } handMarker[aLeftHand][aRightHand][bLeftHand][bRightHand] = 1; // 输出 if (step >= 1) { for (int i = 1; i <= step - 1; i++) { printf(u8"│ "); } printf(u8"├─"); printf(u8"%c:My turn!\n", (step + 1) % 2 + 'a'); for (int i = 1; i <= step - 1; i++) { printf(u8"│ "); } printf(u8"├─"); printf(u8"back:a:%d %d b:%d %d\n", aLeftHand, aRightHand, bLeftHand, bRightHand); } int newHand; if (step % 2 == 0) { if (aLeftHand != endNumber) { if (bLeftHand != endNumber) { newHand = (aLeftHand + bLeftHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[newHand][aRightHand][bLeftHand][bRightHand]) { dfs(newHand, aRightHand, bLeftHand, bRightHand, step + 1); } } if (bRightHand != endNumber) { newHand = (aLeftHand + bRightHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[newHand][aRightHand][bLeftHand][bRightHand]) { dfs(newHand, aRightHand, bLeftHand, bRightHand, step + 1); } } } if (aRightHand != endNumber) { if (bLeftHand != endNumber) { newHand = (aRightHand + bLeftHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][newHand][bLeftHand][bRightHand]) { dfs(aLeftHand, newHand, bLeftHand, bRightHand, step + 1); } } if (bRightHand != endNumber) { newHand = (aRightHand + bRightHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][newHand][bLeftHand][bRightHand]) { dfs(aLeftHand, newHand, bLeftHand, bRightHand, step + 1); } } } } if (step % 2 == 1) { if (bLeftHand != endNumber) { if (aLeftHand != endNumber) { newHand = (bLeftHand + aLeftHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][aRightHand][newHand][bRightHand]) { dfs(aLeftHand, aRightHand, newHand, bRightHand, step + 1); } } if (aRightHand != endNumber) { newHand = (bLeftHand + aRightHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][aRightHand][newHand][bRightHand]) { dfs(aLeftHand, aRightHand, newHand, bRightHand, step + 1); } } } if (bRightHand != endNumber) { if (aLeftHand != endNumber) { newHand = (bRightHand + aLeftHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][aRightHand][bLeftHand][newHand]) { dfs(aLeftHand, aRightHand, bLeftHand, newHand, step + 1); } } if (aRightHand != endNumber) { newHand = (bRightHand + aRightHand) % (endNumber + 1); if (newHand == 0) { newHand = 1; } if (!handMarker[aLeftHand][aRightHand][bLeftHand][newHand]) { dfs(aLeftHand, aRightHand, bLeftHand, newHand, step + 1); } } } } } int main() { printf("Change to which number will win?"); scanf("%d", &endNumber); // 输入 printf("Beginning number?"); scanf("%d%d%d%d", &aLeftHand, &aRightHand, &bLeftHand, &bRightHand); freopen("out.txt", "w", stdout); printf(u8"back:a:%d %d b:%d %d\n", aLeftHand, aRightHand, bLeftHand, bRightHand); dfs(aLeftHand, aRightHand, bLeftHand, bRightHand, 0); printf(u8"Total Win: a:%d b:%d\n", aMayWin, bMayWin); printf(u8"The possibility of a's winning: %.2f%%\n", 1.0 * aMayWin / (aMayWin + bMayWin) * 100); printf(u8"The possibility of b's winning: %.2f%%\n", 1.0 * bMayWin / (aMayWin + bMayWin) * 100); return 0; }
(做了一点输出优化)
如果你想要在控制台看的话就把main()里的freopen注释掉再把dfs里的color函数取消注释。
结果
很神奇
似乎是一个区间一个区间来的
首先,如果目标数是2的话,a玩家完胜:
Total Win: a:4 b:0 The possibility of a's winning: 100.00% The possibility of b's winning: 0.00%
目标数在3到7的区间里(含3和7)的话,b玩家的胜率先是一下提高,然后缓降:
3: Total Win: a:8 b:11 The possibility of a's winning: 42.11% The possibility of b's winning: 57.89% 4: Total Win: a:21 b:22 The possibility of a's winning: 48.84% The possibility of b's winning: 51.16% 5: Total Win: a:32 b:32 The possibility of a's winning: 50.00% The possibility of b's winning: 50.00% 6: Total Win: a:48 b:42 The possibility of a's winning: 53.33% The possibility of b's winning: 46.67% 7: Total Win: a:86 b:67 The possibility of a's winning: 56.21% The possibility of b's winning: 43.79%
随后在8到11的区间内又缓升:
8: Total Win: a:107 b:98 The possibility of a's winning: 52.20% The possibility of b's winning: 47.80% 9: Total Win: a:140 b:136 The possibility of a's winning: 50.72% The possibility of b's winning: 49.28% 10: Total Win: a:163 b:169 The possibility of a's winning: 49.10% The possibility of b's winning: 50.90% 11: Total Win: a:197 b:211 The possibility of a's winning: 48.28% The possibility of b's winning: 51.72%
而后又降:
12: Total Win: a:244 b:248 The possibility of a's winning: 49.59% The possibility of b's winning: 50.41%
(后面没算了有人跑出来的话发一下评论区谢谢了)
(我猜会不会到后面双方胜率无限接近于50%)
(所以这个游戏最好去重玩,保证不会出现重复局面)
总结
我真无聊,写这个破玩意写到现在,明天还要月考(啊我靠1点了???
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/153095.html