CS61A 2021 Spring, Project 1: The Game of Hog (Phase 1)
项目说明: https://inst.eecs.berkeley.edu/~cs61a/sp21/proj/hog/#phase-1-simulator
Phase2: https://www.cnblogs.com/ikventure/p/14885436.html
Phase3: https://www.cnblogs.com/ikventure/p/14887555.html
Project 1: The Game of Hog (Phase 1)
- 成品:https://hog.cs61a.org/
- 任务:完成hog.py文件
- 针对每个problem,写代码前
python ok -q 00 -u --local
确认对问题的理解,理解正确即可解锁代码测试部分python ok -q 00 --local
。 - 注意:及时保存!!!尤其是代码测试前!!!(不然找不到代码问题又得不到正确结果,持续几次怀疑人生)
规则及示例
- Sow Sad,每轮可以投多个骰子,得分为各骰子分数的和,例外:只要其中一个骰子为1,该轮得分为1
- Piggy Points,选择不投骰子的得分为k+3,k为对手得分平方值的最小数字
- More Boar,再来一轮的情况:左一数字<对手左一,左二数字<对手左二,小于10在前补0
Phase 1: Simulator
Problem 0
dice.py 文件,定义了骰子类型
- fair dice:各面等概率的骰子
- test dice:测试用骰子,循环投出一系列指定值
Problem 1
roll_dice 函数,传入骰子数量 num_rolls 和骰子类型 dice,返回此次投骰子结果(考虑 Sow Sad 规则)。
Problem 2
piggy_points 函数,传入对手分数 score,返回投0次骰子的得分(piggy points 规则)。
Problem 3
take_turn 函数,传入骰子数量 num_rolls, 对手得分 opponent_score, 骰子类型 dice=six_sided, 目标得分 goal=GOAL_SCORE,返回该轮得分。
take_turn 函数,在骰子数量为0时,调用 piggy_points 函数;在骰子数量不为0时,调用 roll_dice 函数。
Problem 4
more_boar 函数,传入选手得分player_score, 对手得分opponent_score,返回布尔值,判断该选手是否再来一轮(more_boar 规则)。
Problem 5
play 函数,传入选手0的骰子策略 strategy0, 选手1的骰子策略s trategy1, 初始得分 score0=0, 初始得分 score1=0, 骰子类型 dice=six_sided, 目标得分 goal=GOAL_SCORE, 注释函数 say=silence,返回游戏结束时的两位选手得分。
分析:
strategy是决定选手的骰子数量的函数,传入选手得分和对手得分;
选手得分score = 初始得分 + 本轮得分,本轮得分由 take_turn 函数返回;
选手得分score达到目标值goal时,本轮结束,游戏结束,返回两选手得分;
选手得分score未达到目标值,more_boar 函数判断是否再来一局;
next_player 函数,判断下一位选手是谁,注意赋值给who。
Phase 1 完成
python hog_gui.py
附 Phase 1 代码
"""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.
######################
# 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 ***"
total = 0
k = 0
d = []
while k < num_rolls:
d.append(dice())
k += 1
if 1 in d:
return 1
return sum(d)
# END PROBLEM 1
def piggy_points(score):
"""Return the points scored from rolling 0 dice.
score: The opponent's current score.
"""
# BEGIN PROBLEM 2
"*** YOUR CODE HERE ***"
return 3 + int(min(str(score ** 2)))
# END PROBLEM 2
def take_turn(num_rolls, opponent_score, dice=six_sided, goal=GOAL_SCORE):
"""Simulate a turn rolling NUM_ROLLS dice, which may be 0 in the case
of a player using Piggy Points.
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.
goal: The goal score of the game.
"""
# 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 < goal, 'The game should be over.'
# BEGIN PROBLEM 3
"*** YOUR CODE HERE ***"
if num_rolls == 0:
return piggy_points(opponent_score)
return roll_dice(num_rolls, dice)
# END PROBLEM 3
def more_boar(player_score, opponent_score):
"""Return whether the player gets an extra turn.
player_score: The total score of the current player.
opponent_score: The total score of the other player.
>>> more_boar(21, 43)
True
>>> more_boar(22, 43)
True
>>> more_boar(43, 21)
False
>>> more_boar(12, 12)
False
>>> more_boar(7, 8)
False
"""
# BEGIN PROBLEM 4
"*** YOUR CODE HERE ***"
ps = str(player_score) if player_score >= 10 else '0' + str(player_score)
os = str(opponent_score) if opponent_score >= 10 else '0' + str(opponent_score)
if ps[0] < os[0] and ps[1] < os[1]:
return True
else:
return False
# END PROBLEM 4
def next_player(who):
"""Return the other player, for a player WHO numbered 0 or 1.
>>> next_player(0)
1
>>> next_player(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:
score0 += take_turn(strategy0(score0,score1), score1, dice, goal)
if not more_boar(score0, score1):
who = next_player(who)
else:
score1 += take_turn(strategy1(score1,score0), score0, dice, goal)
if not more_boar(score1, score0):
who = next_player(who)
# END PROBLEM 5
# (note that the indentation for the problem 6 prompt (***YOUR CODE HERE***) might be misleading)
# BEGIN PROBLEM 6
"*** YOUR CODE HERE ***"
say = say(score0, score1)
# END PROBLEM 6
return score0, score1