ca61a fall2020 hog

花了3天完成这个project。之后就在看别人的代码,觉得自己写的还是有问题的

"""CS 61A Presents The Game of Hog."""

from dice import six_sided, four_sided, make_test_dice
from ucb import main, trace, interact

GOAL_SCORE = 100  # The goal of Hog is to score 100 points.
FIRST_101_DIGITS_OF_PI = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

######################
# Phase 1: Simulator #
######################


def roll_dice(num_rolls, dice=six_sided):
    """Simulate rolling the DICE exactly NUM_ROLLS > 0 times. Return the sum of
    the outcomes unless any of the outcomes is 1. In that case, return 1.

    num_rolls:  The number of dice rolls that will be made.
    dice:       A function that simulates a single dice roll outcome.
    """
    # These assert statements ensure that num_rolls is a positive integer.
    assert type(num_rolls) == int, 'num_rolls must be an integer.'
    assert num_rolls > 0, 'Must roll at least once.'
    # BEGIN PROBLEM 1
    "*** YOUR CODE HERE ***"

    sum = 0
    flag_Pig_Out = False
    while num_rolls :
        roll = dice()
        if roll == 1 :
            flag_Pig_Out = True
        sum = sum + roll
        num_rolls -= 1
    if flag_Pig_Out == True :
        sum = 1
    return sum
    """
    sum = 1 if flag_Pig_Out else sum
    return sum 
    """

    # END PROBLEM 1


def free_bacon(score):
    """Return the points scored from rolling 0 dice (Free Bacon).

    score:  The opponent's current score.
    """
    assert score < 100, 'The game should be over.'
    pi = FIRST_101_DIGITS_OF_PI

    # Trim pi to only (score + 1) digit(s)
    # BEGIN PROBLEM 2
    "*** YOUR CODE HERE ***"

    a = pow(10 , 100 - score)
    pi = pi // a

    # END PROBLEM 2

    return pi % 10 + 3


def take_turn(num_rolls, opponent_score, dice=six_sided):
    """Simulate a turn rolling NUM_ROLLS dice, which may be 0 (Free Bacon).
    Return the points scored for the turn by the current player.

    num_rolls:       The number of dice rolls that will be made.
    opponent_score:  The total score of the opponent.
    dice:            A function that simulates a single dice roll outcome.
    """
    # Leave these assert statements here; they help check for errors.
    assert type(num_rolls) == int, 'num_rolls must be an integer.'
    assert num_rolls >= 0, 'Cannot roll a negative number of dice in take_turn.'
    assert num_rolls <= 10, 'Cannot roll more than 10 dice.'
    assert opponent_score < 100, 'The game should be over.'
    # BEGIN PROBLEM 3
    "*** YOUR CODE HERE ***"

    points_scored = 0
    if num_rolls :
        points_scored = roll_dice(num_rolls, dice)
    else :
        points_scored = free_bacon(opponent_score)
    return points_scored

    # END PROBLEM 3


def extra_turn(player_score, opponent_score):
    """Return whether the player gets an extra turn."""
    return (pig_pass(player_score, opponent_score) or
            swine_align(player_score, opponent_score))


def swine_align(player_score, opponent_score):
    """Return whether the player gets an extra turn due to Swine Align.

    player_score:   The total score of the current player.
    opponent_score: The total score of the other player.

    >>> swine_align(30, 45)  # The GCD is 15.
    True
    >>> swine_align(35, 45)  # The GCD is 5.
    False
    """
    # BEGIN PROBLEM 4a
    "*** YOUR CODE HERE ***"

    n_CD , n_GCD = 1 , 1
    while n_CD <= min(player_score , opponent_score) :
        if player_score % n_CD == 0 and opponent_score % n_CD == 0 :
            n_GCD = n_CD
        n_CD += 1 

    if n_GCD < 10:
        return False      
    else :
        return True

    # n_GCD = 2
    # flag = False
    # if player_score == 0 or opponent_score == 0 :
    #     return False
    # while n_GCD <= min(player_score , opponent_score) :
    #     if player_score % opponent_score == 0 or opponent_score % player_score == 0 :
    #        n_GCD = min(player_score , opponent_score)
    #        if n_GCD < 10:
    #             return False      
    #        else :
    #             return True
    #     if player_score % n_GCD == 0 and opponent_score % n_GCD == 0 :
    #         if n_GCD < 10:
    #             return False      
    #         else :
    #             return True
    #     n_GCD += 1   
    # return False


    # END PROBLEM 4a


def pig_pass(player_score, opponent_score):
    """Return whether the player gets an extra turn due to Pig Pass.

    player_score:   The total score of the current player.
    opponent_score: The total score of the other player.

    >>> pig_pass(9, 12)
    False
    >>> pig_pass(10, 12)
    True
    >>> pig_pass(11, 12)
    True
    >>> pig_pass(12, 12)
    False
    >>> pig_pass(13, 12)
    False
    """
    # BEGIN PROBLEM 4b
    "*** YOUR CODE HERE ***"

    if player_score < opponent_score :
        if opponent_score - player_score < 3:
            return  True
    return False


    # END PROBLEM 4b


def other(who):
    """Return the other player, for a player WHO numbered 0 or 1.

    >>> other(0)
    1
    >>> other(1)
    0
    """
    return 1 - who


def silence(score0, score1):
    """Announce nothing (see Phase 2)."""
    return silence


def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
         goal=GOAL_SCORE, say=silence):
    """Simulate a game and return the final scores of both players, with Player
    0's score first, and Player 1's score second.

    A strategy is a function that takes two total scores as arguments (the
    current player's score, and the opponent's score), and returns a number of
    dice that the current player will roll this turn.

    strategy0:  The strategy function for Player 0, who plays first.
    strategy1:  The strategy function for Player 1, who plays second.
    score0:     Starting score for Player 0
    score1:     Starting score for Player 1
    dice:       A function of zero arguments that simulates a dice roll.
    goal:       The game ends and someone wins when this score is reached.
    say:        The commentary function to call at the end of the first turn.
    """
    who = 0  # Who is about to take a turn, 0 (first) or 1 (second)
    # BEGIN PROBLEM 5
    "*** YOUR CODE HERE ***"

    while score0 < goal and score1 < goal :
        if who == 0 :
            num_rolls_0 = strategy0(score0 , score1)
            score = take_turn(num_rolls_0, score1, dice)
            score0 = score0 + score
            say = say(score0, score1)
            if score0 >= goal :
                break
            else :
              while extra_turn(score0, score1) :
                num_rolls_0 = strategy0(score0, score1)
                score = take_turn(num_rolls_0, score1, dice)
                score0 = score0 + score
                say = say(score0, score1)
                if not (score0 < goal):
                    return score0, score1
            who = other(who)
        if who == 1 :
            num_rolls_1 = strategy1(score1 , score0)
            score = take_turn(num_rolls_1, score0, dice)
            score1 = score1 + score
            say = say(score0, score1)
            if not (score1 < goal):
                break   
            while extra_turn(score1, score0) :
                num_rolls_1 = strategy1(score1, score0)
                score = take_turn(num_rolls_1, score0, dice)
                score1 = score1 + score
                say = say(score0, score1)
                if not (score1 < goal):
                    return score0, score1
            who = other(who)

            
        """
          >>> #
          >>> s0, s1 = play(always_roll(3), always_roll(3), dice=make_test_dice(1, 2, 3, 3), goal=8, say=both(say_scores, announce_lead_changes()))
          Player 0 now has 1 and Player 1 now has 0
          Player 0 takes the lead by 1
          Player 0 now has 1 and Player 1 now has 1
          Player 0 now has 2 and Player 1 now has 1
          Player 0 takes the lead by 1
          Player 0 now has 2 and Player 1 now has 9
          Player 1 takes the lead by 7
        """

    # END PROBLEM 5
    # (note that the indentation for the problem 6 prompt (***YOUR CODE HERE***) might be misleading)
    # BEGIN PROBLEM 6
    "*** YOUR CODE HERE ***"
    # END PROBLEM 6
    return score0, score1


#######################
# Phase 2: Commentary #
#######################


def say_scores(score0, score1):
    """A commentary function that announces the score for each player."""
    print("Player 0 now has", score0, "and Player 1 now has", score1)
    return say_scores


def announce_lead_changes(last_leader=None):
    """Return a commentary function that announces lead changes.

    >>> f0 = announce_lead_changes()
    >>> f1 = f0(5, 0)
    Player 0 takes the lead by 5
    >>> f2 = f1(5, 12)
    Player 1 takes the lead by 7
    >>> f3 = f2(8, 12)
    >>> f4 = f3(8, 13)
    >>> f5 = f4(15, 13)
    Player 0 takes the lead by 2
    """
    def say(score0, score1):
        if score0 > score1:
            leader = 0
        elif score1 > score0:
            leader = 1
        else:
            leader = None
        if leader != None and leader != last_leader:
            print('Player', leader, 'takes the lead by', abs(score0 - score1))
        return announce_lead_changes(leader)
    return say


def both(f, g):
    """Return a commentary function that says what f says, then what g says.

    NOTE: the following game is not possible under the rules, it's just
    an example for the sake of the doctest

    >>> h0 = both(say_scores, announce_lead_changes())
    >>> h1 = h0(10, 0)
    Player 0 now has 10 and Player 1 now has 0
    Player 0 takes the lead by 10
    >>> h2 = h1(10, 8)
    Player 0 now has 10 and Player 1 now has 8
    >>> h3 = h2(10, 17)
    Player 0 now has 10 and Player 1 now has 17
    Player 1 takes the lead by 7
    """
    def say(score0, score1):
        return both(f(score0, score1), g(score0, score1))
    return say


def announce_highest(who, last_score=0, running_high=0):
    """Return a commentary function that announces when WHO's score
    increases by more than ever before in the game.

    NOTE: the following game is not possible under the rules, it's just
    an example for the sake of the doctest

    >>> f0 = announce_highest(1) # Only announce Player 1 score gains
    >>> f1 = f0(12, 0)
    >>> f2 = f1(12, 9)
    9 point(s)! The most yet for Player 1
    >>> f3 = f2(20, 9)
    >>> f4 = f3(20, 30)
    21 point(s)! The most yet for Player 1
    >>> f5 = f4(20, 47) # Player 1 gets 17 points; not enough for a new high
    >>> f6 = f5(21, 47)
    >>> f7 = f6(21, 77)
    30 point(s)! The most yet for Player 1
    """
    assert who == 0 or who == 1, 'The who argument should indicate a player.'
    # BEGIN PROBLEM 7
    "*** YOUR CODE HERE ***"
        # the score from last turn (last_score)
        # the highest gain for the player so far, which is store as running_high.
        # Hint: The announce_lead_changes function provided to you is an example of how to keep track of information using commentary functions.
    def say(scores0, scores1) :
        # something
        if who == 0 :
            last_score_0 = last_score
            running_high_0 = scores0 - last_score_0
            running_high_0_max = running_high
            if running_high_0_max < running_high_0 :
                running_high_0_max = running_high_0
                print(running_high_0_max,'point(s)! The most yet for Player 0')
            last_score_0 = scores0
            #something
            return announce_highest(who, last_score_0, running_high_0_max)

        elif who == 1:
            last_score_1 = last_score
            running_high_1 = scores1 - last_score_1
            running_high_1_max = running_high
            if running_high_1_max < running_high_1 :
                running_high_1_max = running_high_1
                print(running_high_1_max,'point(s)! The most yet for Player 1')
            last_score_1 = scores1
            return announce_highest(who, last_score_1, running_high_1_max)
            #something 
        #return announce_highest(who, last_score, running_high)
    return  say
        

    # END PROBLEM 7


#######################
# Phase 3: Strategies #
#######################


def always_roll(n):
    """Return a strategy that always rolls N dice.

    A strategy is a function that takes two total scores as arguments (the
    current player's score, and the opponent's score), and returns a number of
    dice that the current player will roll this turn.

    >>> strategy = always_roll(5)
    >>> strategy(0, 0)
    5
    >>> strategy(99, 99)
    5
    """
    def strategy(score, opponent_score):
        return n
    return strategy


def make_averaged(original_function, trials_count=1000):
    """Return a function that returns the average value of ORIGINAL_FUNCTION
    when called.

    To implement this function, you will have to use *args syntax, a new Python
    feature introduced in this project.  See the project description.

    >>> dice = make_test_dice(4, 2, 5, 1)
    >>> averaged_dice = make_averaged(dice, 1000)
    >>> averaged_dice()
    3.0
    """
    # BEGIN PROBLEM 8
    "*** YOUR CODE HERE ***"
    def new_fun(*arg):
        sum = 0
        count = trials_count
        while count:
            num =  original_function(*arg)
            sum = sum + num 
            count -= 1
        average = sum / trials_count
        return average
    return new_fun
    # END PROBLEM 8


def max_scoring_num_rolls(dice=six_sided, trials_count=1000):
    """Return the number of dice (1 to 10) that gives the highest average turn
    score by calling roll_dice with the provided DICE over TRIALS_COUNT times.
    Assume that the dice always return positive outcomes.

    >>> dice = make_test_dice(1, 6)
    >>> max_scoring_num_rolls(dice)
    1
    """

    # BEGIN PROBLEM 9
    "*** YOUR CODE HERE ***"
    """
    def roll_dice(num_rolls, dice=six_sided): return sum ,don't consider 0 dice rolls each turn 
    def make_averaged(original_function, trials_count=1000):Return a function that returns the average value of ORIGINAL_FUNCTION
    when called.
    If two numbers of rolls are tied for the maximum average score, 
        return the lower number. For example, 
        if both 3 and 6 achieve a maximum average score, return 3.

    >>> dice = make_test_dice(4, 2, 5, 1)
    >>> averaged_dice = make_averaged(dice, 1000)
    >>> averaged_dice()
    3.0

    >>> dice = make_test_dice(3, 1, 5, 6)
    >>> averaged_roll_dice = make_averaged(roll_dice, 5)
    >>> averaged_roll_dice(2, dice)
    5.0

    >>> dice = make_test_dice(1, 2, 2, 2, 2, 2, 2, 2)
    >>> max_scoring_num_rolls(dice, trials_count=1000)
    4
    >>> dice = make_test_dice(1, 2, 3, 4, 5)  # dice sweeps from 1 through 5
    >>> max_scoring_num_rolls(dice, trials_count=1000)
    3
    """
    """
    网上看到的:
    max_roll = 0
    num_of_dice = 10
    max_number_of_dice = 0
    while num_of_dice > 0:
        current_rool = make_averaged(roll_dice, trials_count)(num_of_dice, dice)
        if current_rool > max_roll:
            max_roll = current_rool
            max_number_of_dice = num_of_dice
        num_of_dice -= 1
    return max_number_of_dice
        ————————————————
        版权声明:本文为CSDN博主「hiccgoal」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
        原文链接:https://blog.csdn.net/qq_42103298/article/details/108855216

    我觉得:要是3,6都返回同一个average的话,应该返回的是3,但是这个返回6


    自己写一下:
    """
    max_average = 0 #最大的平均数
    current_average = 0 #当前求的平均数
    loop_num_roll = 1 #循环的色子数,从1,开始找最大平均值,
    max_average_of_min_num_rolls = 0
    while loop_num_roll < 11:
        current_average = make_averaged(roll_dice,trials_count)(loop_num_roll,dice)
        if current_average > max_average :
            max_average = current_average
            max_average_of_min_num_rolls = loop_num_roll
        loop_num_roll += 1 
    return max_average_of_min_num_rolls 

    # """
    # if now num_rolls = 1
    # averages[11] = 0 
    # n = 1
    max_average_num_rolls = 0
    temp = make_averaged(roll_dice, trials_count)
    # while not (n > 11):
    #     averages[n] = temp(1, dice)
    average_1 = temp(1, dice)
    average_2 = temp(2, dice) 
    average_3 = temp(3, dice)
    average_4 = temp(4, dice)
    average_5 = temp(5, dice)
    average_6 = temp(6, dice)
    average_7 = temp(7, dice)
    average_8 = temp(8, dice)
    average_9 = temp(9, dice)
    average_10 = temp(10, dice)
    # 从1到10 10个average 找到最大的 average 返回对应的 num_rolls
    # temp = make_averaged(roll_dice, trials_count)
    # average_1 = 0
    # average_2 = 0
    # average_3 = 0
    # average_4 = 0
    # average_5 = 0
    # average_6 = 0
    # average_7 = 0
    # average_8 = 0
    # average_9 = 0
    # average_10 = 0
    max_average = max(average_1,average_2,average_3,average_4,average_5,average_6,average_7,average_8,average_9,average_10)
    if  average_1 ==  max_average :
        max_average_num_rolls = 1
    elif  average_2 ==  max_average :
        max_average_num_rolls = 2
    elif  average_3 ==  max_average :
        max_average_num_rolls = 3
    elif  average_4 ==  max_average :
        max_average_num_rolls = 4                                                                
    elif  average_5 ==  max_average :
        max_average_num_rolls = 5
    elif  average_6 ==  max_average :
        max_average_num_rolls = 6
    elif  average_7 ==  max_average :
        max_average_num_rolls = 7
    elif  average_8 ==  max_average :
        max_average_num_rolls = 8
    elif  average_9 ==  max_average :
        max_average_num_rolls = 9      
    elif  average_10 ==  max_average :
        max_average_num_rolls = 10

    return max_average_num_rolls #能达到最大平均数的最小色子数
    # END PROBLEM 9


def winner(strategy0, strategy1):
    """Return 0 if strategy0 wins against strategy1, and 1 otherwise."""
    score0, score1 = play(strategy0, strategy1)
    if score0 > score1:
        return 0
    else:
        return 1


def average_win_rate(strategy, baseline=always_roll(6)):
    """Return the average win rate of STRATEGY against BASELINE. Averages the
    winrate when starting the game as player 0 and as player 1.
    """
    win_rate_as_player_0 = 1 - make_averaged(winner)(strategy, baseline)
    win_rate_as_player_1 = make_averaged(winner)(baseline, strategy)

    return (win_rate_as_player_0 + win_rate_as_player_1) / 2


def run_experiments():
    """Run a series of strategy experiments and report results."""
    if True:  # Change to False when done finding max_scoring_num_rolls
        six_sided_max = max_scoring_num_rolls(six_sided)
        print('Max scoring num rolls for six-sided dice:', six_sided_max)

    if True : #False:  # Change to True to test always_roll(8)
        print('always_roll(8) win rate:', average_win_rate(always_roll(8)))
    
    if True : #False:  # Change to True to test always_roll(4) 这是我自己复制的
        print('always_roll(4) win rate:', average_win_rate(always_roll(4)))

    if True : #False: # Change to True to test bacon_strategy
        print('bacon_strategy win rate:', average_win_rate(bacon_strategy))

    if True : #False:  # Change to True to test extra_turn_strategy
        print('extra_turn_strategy win rate:', average_win_rate(extra_turn_strategy))

    if True : #False:  # Change to True to test final_strategy
        print('final_strategy win rate:', average_win_rate(final_strategy))

    "*** You may add additional experiments as you wish ***"



def bacon_strategy(score, opponent_score, cutoff=8, num_rolls=6):
    """This strategy rolls 0 dice if that gives at least CUTOFF points, and
    rolls NUM_ROLLS otherwise.
    """
    # BEGIN PROBLEM 10
    """
    bacon_strategy() ,returns 0 whenever rolling 0 would give at least cutoff points and returns num_rolls otherwise.
    def free_bacon(oppent_score):return somevalue + 3
    """
    score_now = free_bacon(opponent_score)
    if score_now < cutoff :
        return num_rolls
    else :
        return 0
    return 6  # Replace this statement
    # END PROBLEM 10


def extra_turn_strategy(score, opponent_score, cutoff=8, num_rolls=6):
    """This strategy rolls 0 dice when it triggers an extra turn. It also
    rolls 0 dice if it gives at least CUTOFF points and does not give an extra turn.
    Otherwise, it rolls NUM_ROLLS.
    """
    # BEGIN PROBLEM 11
    """
    def extra_turn(player_score, opponent_score): #Return whether the player gets an extra turn.
        return (pig_pass(player_score, opponent_score) or
            swine_align(player_score, opponent_score))
    FIRST_101_DIGITS_OF_PI = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
    """ 
    now_scored = free_bacon(opponent_score) + score
    if extra_turn(now_scored, opponent_score):
        return 0 
    else :
        return bacon_strategy(score, opponent_score, cutoff, num_rolls)
    
    return 6  # Replace this statement
    # END PROBLEM 11


def final_strategy(score, opponent_score):
    """Write a brief description of your final strategy.

    *** YOUR DESCRIPTION HERE ***
    """
    # BEGIN PROBLEM 12


    return extra_turn_strategy(score, opponent_score)
    return 6  # Replace this statement
    # END PROBLEM 12

##########################
# Command Line Interface #
##########################

# NOTE: Functions in this section do not need to be changed. They use features
# of Python not yet covered in the course.


@main
def run(*args):
    """Read in the command-line argument and calls corresponding functions."""
    import argparse
    parser = argparse.ArgumentParser(description="Play Hog")
    parser.add_argument('--run_experiments', '-r', action='store_true',
                        help='Runs strategy experiments')

    args = parser.parse_args()

    if args.run_experiments:
        run_experiments()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值