三国杀2
2024年11月28日大约 4 分钟教学文档模拟
三国杀算法 2
题目描述
假设现在有两个玩家A和B,分别使用孙权和神吕蒙。场上有两张闪电牌,每回合开始时,当前玩家需要进行闪电牌的判定。如果判定结果为黑桃2~9,则当前玩家会受到3点雷电伤害,闪电牌从场上移除。每名玩家的初始手牌中都有一张无懈可击牌,可以在闪电牌判定之前使用,以抵消闪电牌的判定效果,避免受到3点伤害。
请编写一个函数来计算,在双方都采取最优策略的情况下,玩家A和B何时使用无懈可击牌,使得各自受到的伤害最小。返回一个元组 (use_wuxie_A, use_wuxie_B)
,表示玩家A和B分别在哪一回合使用无懈可击牌。
输入格式
health_A
: 孙权的初始血量,范围为[1, 10]。health_B
: 神吕蒙的初始血量,范围为[1, 10]。turns
: 总回合数,范围为[1, 10]。deck
: 牌堆中的牌,包含字符串"black_2"到"black_9"表示黑桃2到9,其他值表示不会触发伤害。
输出格式
返回一个元组 (use_wuxie_A, use_wuxie_B)
,表示玩家A和B分别在哪一回合使用无懈可击牌。
示例
示例1
输入:
health_A = 5
health_B = 6
turns = 5
deck = ["black_2", "black_3", "black_4", "black_5", "black_6", "black_7", "black_8", "black_9", "red_10", "club_10"]
输出:
(1, 2)
解释:
- 第一回合,孙权受到3点伤害,使用无懈可击牌抵消。
- 第二回合,神吕蒙受到3点伤害,使用无懈可击牌抵消。
- 后续回合,双方都不会受到闪电牌的伤害。
示例2
输入:
health_A = 4
health_B = 4
turns = 3
deck = ["black_2", "black_9", "black_3", "red_10", "club_10"]
输出:
(1, 3)
解释:
- 第一回合,孙权受到3点伤害,使用无懈可击牌抵消。
- 第二回合,神吕蒙不受伤害。
- 第三回合,神吕蒙受到3点伤害,使用无懈可击牌抵消。
参考答案
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// 定义牌的结构体
typedef struct {
char suit; // 花色:'S' 黑桃, 'H' 红桃, 'D' 方片, 'C' 梅花
int value; // 牌面值
} Card;
// 判断牌是否为黑桃2~9
int is_black_2_to_9(Card card) {
return card.suit == 'S' && card.value >= 2 && card.value <= 9;
}
// 计算当前牌堆中黑桃2~9的数量
int count_black_2_to_9(Card *deck, int deck_size) {
int count = 0;
for (int i = 0; i < deck_size; i++) {
if (is_black_2_to_9(deck[i])) {
count++;
}
}
return count;
}
// 计算当前回合闪电牌判定为黑桃2~9的概率
double calculate_probability(Card *deck, int deck_size) {
if (deck_size == 0) return 0.0;
int black_2_to_9_count = count_black_2_to_9(deck, deck_size);
return (double)black_2_to_9_count / deck_size;
}
// 主函数
void optimal_wuxie_usage(int health_A, int health_B, int turns, Card *deck, int deck_size) {
int use_wuxie_A = -1;
int use_wuxie_B = -1;
srand(time(NULL)); // 初始化随机数种子
for (int turn = 0; turn < turns; turn++) {
double probability_black_2_to_9 = calculate_probability(deck, deck_size);
if (turn % 2 == 0) { // 当前回合是孙权的回合
if (probability_black_2_to_9 > 0 && use_wuxie_A == -1) {
use_wuxie_A = turn + 1;
continue;
}
} else { // 当前回合是神吕蒙的回合
if (probability_black_2_to_9 > 0 && use_wuxie_B == -1) {
use_wuxie_B = turn + 1;
continue;
}
}
// 进行闪电牌判定
if (probability_black_2_to_9 > 0) {
int index = rand() % deck_size;
if (is_black_2_to_9(deck[index])) {
if (turn % 2 == 0) {
health_A = health_A - 3;
} else {
health_B = health_B - 3;
}
// 移除已使用的闪电牌
for (int i = index; i < deck_size - 1; i++) {
deck[i] = deck[i + 1];
}
deck_size--;
}
}
}
printf("(%d, %d)\n", use_wuxie_A, use_wuxie_B);
}
int main() {
int health_A = 5;
int health_B = 6;
int turns = 5;
Card deck[] = {
{'S', 2}, {'S', 3}, {'S', 4}, {'S', 5}, {'S', 6}, {'S', 7}, {'S', 8}, {'S', 9},
{'H', 10}, {'C', 10}
};
int deck_size = sizeof(deck) / sizeof(deck[0]);
optimal_wuxie_usage(health_A, health_B, turns, deck, deck_size);
return 0;
}
解释
- 定义牌的结构体:
Card
结构体用于表示一张牌,包含花色和牌面值。 - 判断牌是否为黑桃2~9:
is_black_2_to_9
函数用于判断一张牌是否为黑桃2~9。 - 计算当前牌堆中黑桃2~9的数量:
count_black_2_to_9
函数遍历牌堆,统计黑桃2~9的数量。 - 计算当前回合闪电牌判定为黑桃2~9的概率:
calculate_probability
函数计算当前牌堆中黑桃2~9的概率。 - 主函数:
optimal_wuxie_usage
函数模拟每个回合的过程,决定何时使用无懈可击牌。 - 主函数调用:在
main
函数中初始化玩家血量、回合数和牌堆,然后调用optimal_wuxie_usage
函数。