Project1-hog
规则
目标:达成GOAL(默认100),双方轮流投骰子,本回合得分是骰子结果总和
- Sow Sad: 有任意一骰子为1,则总和为1
- Boar Brawl: 选择投骰子0个,获得对手得分十位数与自己得分个位数之差的绝对值的三倍,或1,取二者之间较大的
- Sus Fuss: 如果一个数字恰好有¾个因数,被称为可疑数。如果当前得分是可疑数,则增大到大于当前得分的最小质数
Phase1: Rules of the Game
| Python |
|---|
| # problem0: 阅读dice.py,理解骰子的行为
"""Functions that simulate dice rolls.
A dice function takes no arguments and returns a number from 1 to n
(inclusive), where n is the number of sides on the dice.
Fair dice produce each possible outcome with equal probability.
Two fair dice are already defined, four_sided and six_sided,
and are generated by the make_fair_dice function.
Test dice are deterministic: they always cycles through a fixed
sequence of values that are passed as arguments.
Test dice are generated by the make_test_dice function.
"""
from random import randint
def make_fair_dice(sides):
"""Return a die that returns 1 to SIDES with equal chance."""
assert type(sides) == int and sides >= 1, 'Illegal value for sides'
def dice():
return randint(1,sides)
return dice
four_sided = make_fair_dice(4)
six_sided = make_fair_dice(6)
def make_test_dice(*outcomes):
"""Return a die that cycles deterministically through OUTCOMES.
>>> dice = make_test_dice(1, 2, 3)
>>> dice()
1
>>> dice()
2
>>> dice()
3
>>> dice()
1
>>> dice()
2
This function uses Python syntax/techniques not yet covered in this course.
The best way to understand it is by reading the documentation and examples.
"""
assert len(outcomes) > 0, 'You must supply outcomes to make_test_dice'
for o in outcomes:
assert type(o) == int and o >= 1, 'Outcome is not a positive integer'
index = len(outcomes) - 1
def dice():
nonlocal index #使用了nonlocal,这是说明里面提到的non-pure的原因,The `dice.py` file represents dice using non-pure zero-argument functions. These functions are non-pure because they may have different return values each time they are called, and so a side-effect of calling the function is changing what will be returned when the function is called again.
index = (index + 1) % len(outcomes)
return outcomes[index]
return dice
|
| Python |
|---|
| # problem1: 实现函数roll_dice: 接受num_rolls指定投骰子次数,接受dice函数(怎么样的骰子),返回投骰子获得分数。在roll_dice中恰好调用dice()函数num_rolls次。
def rool_dice(num_rolls, dice = six_sided):
exist_one = 0
total = 0
while num_rolls > 0:
a_dice_num = dice()
total, num_rolls = total + a_dice_num, num_rolls - 1
if a_dice_num == 1:
exist_one = 1
if exist_one:
return 1
return total
|
| Python |
|---|
| # problem2: 实现boar_brawl函数,接受当前得分和对手得分,返回boar_brawl的得分
def boar_brawl(player_score, opponent_score):
total = 3 * abs(opponent_score%100//10 - player_score%10)
return max(1, total)
|
| Python |
|---|
| # problem3: 实现take_turn函数,返回通过给定dice和num_rolls的得分
def take_turn(num_rolls, player_score, opponent_score, dice=six_sided):
if num_rolls == 0:
return boar_brawl(player_score, opponent_score)
else:
return roll_dice(num_rolls, dice)
|
| Python |
|---|
| # problem4: num_factors,返回n的因子数量;sus_points,返回玩家在经过sus fuss;sus_update,返回玩家投掷num_rolls个骰子的总分数,同时考虑sus fuss和boar brawl规则
def is_prime(n):
"""Return whether N is prime."""
if n == 1:
return False
k = 2
while k < n:
if n % k == 0:
return False
k += 1
return True
def num_factors(n):
"""Return the number of factors of N, including 1 and N itself."""
# BEGIN PROBLEM 4
num = 0
for i in range(1, n+1):
if n % i == 0:
num += 1
return num
# END PROBLEM 4
def sus_points(score):
"""Return the new score of a player taking into account the Sus Fuss rule."""
# BEGIN PROBLEM 4
if num_factors(score) == 3 or num_factors(score) == 4:
while not is_prime(score):
score += 1
return score
# END PROBLEM 4
def sus_update(num_rolls, player_score, opponent_score, dice=six_sided):
"""Return the total score of a player who starts their turn with
PLAYER_SCORE and then rolls NUM_ROLLS DICE, *including* Sus Fuss.
"""
# BEGIN PROBLEM 4
score = simple_update(num_rolls, player_score, opponent_score, dice)
return sus_points(score)
# END PROBLEM 4
|
| Python |
|---|
| # problem5: play函数:模拟一局完整的hog游戏
def play(strategy0, strategy1, update, score0=0, score1=0, dice=six_sided, goal=GOAL):
who = 0
while score0 < goal and score1 < goal:
if who == 0:
num_rolls = strategy0(score0, score1)
score0 = update(num_rolls, score0, score1, dice)
who = 1 - who
else:
num_rolls = strategy1(score1, score0)
score1 = update(num_rolls, score1, score0, dice)
who = 1 - who
return score0, score1
|
Interlude: User Interfaces
1. Printing Game Events
可以使用高阶函数,在不对原有代码作出太多改动的情况下实现这点。阅读hog_ui.py
interactive_strategy函数返回一个通过调用input函数让玩家决定num_rolls的策略
3. Graphical User Interface
图形化界面
Phase2: Strategies
策略函数接受当前玩家分数和对手分数,返回要投的骰子的数量
| Python |
|---|
| # problem 6: always_roll, 接受一个n,返回一个总是投骰子n次的策略
def always_roll(n):
def always_roll_n(score, opponent_score):
return n
return always_roll_n
|
| Python |
|---|
| # problem 7: is_always_roll,检测一个策略是否一直都是在roll相同的次数
def is_always_roll(strategy, goal=GOAL):
num_rolls = strategy(0, 0)
for i in range(0, goal):
for j in range(0, goal):
if strategy(i, j) != num_rolls:
return False
return True
|
| Python |
|---|
| # problem 8: make_ageraged,调用一个original_function for times_called time,返回一个返回均值的函数
def make_averaged(original_function, times_called=1000):
def averaged(*args): #为了让averaged和original_function接受相同参数
result = 0
for _ in range(times_called):
result += original_function(*args)
return result / times_called
return averaged
|
| Python |
|---|
| # problem 9: max_scoring_num_rolls,使用make_averaged和roll_dice实现,使用固定面数的骰子实验,确定在1-10次的投掷中,能使单会平均得分最高的投掷次数
def max_scoring_num_rolls(dice=six_sided, times_called=1000):
max_n = 0
max_agerage = 0
for i in range(1, 11):
current = make_averaged(roll_dice, times_called)(i, dice)
if current > max_agerage:
max_agerage = current
max_n = i
return max_n
|
| Python |
|---|
| # problem 10: boar_strategy,滚动0次时最少能获得threshold分数,则返回0,否则返回num_rolls,不考虑sus fuss
def boar_strategy(score, opponent_score, threshold=11, num_rolls=6):
if boar_brawl(score, opponent_score) >= threshold:
return 0
return num_rolls
|
| Python |
|---|
| # problem 11: sus_stragety,在boar_strategy的基础上考虑sus
def sus_strategy(score, opponent_score, threshold=11, num_rolls=6):
if sus_update(0, score, opponent_score) - score >= threshold:
return 0
return num_rolls
|