Principle of Computing (Python)学习笔记(2) Cookie Clicker

这个Principle of Computing 是Rice U在coursera上的Python课系列的第二门课。这个课的每个mini-project都是有一些小小的挑战的。

第二个mini project是实现游戏cookie clicker。这个游戏本身很无聊。
这次的Project完全没有算法难度,估计这次的Project的用意是让人体会将实际问题建模为类和翻译为代码。

1 数学知识准备

1.1 求和相关的数学公式(略)

log运算 https://class.coursera.org/principlescomputing-001/wiki/view?page=log_and_exp

数学表达式 https://class.coursera.org/principlescomputing-001/wiki/view?page=math_expressions


1.2 Log 和Plotting

通过Log和plotting来判断多项式的维度。

log(y)=log(axn) 

log(y)=log(a)+nlog(x)

If the data points (xi,yi) lie on y=axn, then they must satisfy the equation

log(yi)=log(a)+nlog(xi)

where log(a) and n are constants. This observation suggests a strategy for determining whether the data points lie close to a polynomial function. Plot the data points (log(xi),log(yi)) and check whether these data points lie near a straight line. If they do, the original data points (xi,yi) lie near a polynomial function. Moreover, the degree of this polynomial is simply the slope of this line.

Many plotting packages support this kind of analysis by offering a log/log plotting option. Under this option, the axes are labelled with the various values of the x and y. However, these labels and the plotted data are positioned at the locationslog(x) and log(y). For example, plots with axes labeled 1,10,100,1000,... are usually log/log plots. 


2 Higher-Order Functions

2.1 把函数作为另外一个函数的参数

def double(val):
    return 2 * val

def square(val):
    return val ** 2

def twice(func, val):
    return func(func(val));

print twice(double,3)
print twice(square,3)

2.2 demo: area under curve

def area(func, low, high, stepsize):
    total = 0;
    loc = low;
    while loc<high:
        total += func(loc) * stepsize;
        loc +=stepsize;
    return total
def g(x):
    return x;
def h(x):
    return x **2;
print area(g, 0, 10, 0.01)
print area(h, 0, 10, 0.01)

3 使用map

把函数作为map的参数

list1 = [1,3,6,8,9]
list2 = [x*2 for x in list1]
print list2

def double(val):
    return 2 * val
 
list3 = map(double, list1)
print list3

4 使用filter

把函数作为filter的参数

def even(val):
    if val % 2 == 0:
        return True
    else:
        return False
list4 = filter(even, list3)
print list4


4 mini-project

Note that simulate_clicker is a higher-order function: it takes a strategy function as an argument!

5 我的代码:

"""
Cookie Clicker Simulator 最后提交测试的时候,有一个case中的一个数字有些小问题,得到98分,还没有找到问题原因。
"""

import simpleplot
import math

# Used to increase the timeout, if necessary
import codeskulptor
codeskulptor.set_timeout(20)

import poc_clicker_provided as provided

# Constants
SIM_TIME = 10000000000.0

class ClickerState:
    """
    Simple class to keep track of the game state.
    """
    
    def __init__(self):
        self._total_game_cookies = 0.0
        self._current_cookies= 0.0
        self._current_time = 0.0
        self._current_cps = 1.0
        self._history_list = [(0.0, None, 0.0, 0.0)] 
        
    def __str__(self):
        """
        Return human readable state
        """
#        res = ""
#        for each_item in self.history_list:
#            res += str(each_item) + "\n"
#        return res
        return "\nmy total cookies: "+str(self._total_game_cookies) + "\ncurrent cookies: " + str(self._current_cookies) + "\ncurrent time: " + str(self._current_time) + "\ncurrent CPS: " +str(self._current_cps)
        
    def get_cookies(self):
        """
        Return current number of cookies 
        (not total number of cookies)
        
        Should return a float
        """
        return self._current_cookies
    
    def get_cps(self):
        """
        Get current CPS

        Should return a float
        """
        return self._current_cps
    
    def get_time(self):
        """
        Get current time

        Should return a float
        """
        return self._current_time
    
    def get_history(self):
        """
        Return history list

        History list should be a list of tuples of the form:
        (time, item, cost of item, total cookies)

        For example: (0.0, None, 0.0, 0.0)
        """
        return self._history_list

    def time_until(self, cookies):
        """
        Return time until you have the given number of cookies
        (could be 0 if you already have enough cookies)

        Should return a float with no fractional part
        """
        if cookies <= self.get_cookies():
            return 0.0
        else:
            return float(math.ceil((cookies-self.get_cookies())/self.get_cps()))
   
    def wait(self, time):
        """
        Wait for given amount of time and update state

        Should do nothing if time <= 0
        """
        if time<=0:
            return
        # 如何真正模拟How to simulate waiting for the given amout of time?
        self._current_time += time
        self._current_cookies += time * self._current_cps
        self._total_game_cookies += time * self._current_cps;
         
    def buy_item(self, item_name, cost, additional_cps):
        """
        Buy an item and update state

        Should do nothing if you cannot afford the item
        """
        if self._current_cookies < cost:
            return
        self._history_list.append((self._current_time, item_name, cost, self._total_game_cookies))
        self._current_cookies -= cost;
        self._current_cps += additional_cps
#        print str(item_name) + "--" + str(self._current_time) + "--"  + str(self._current_cookies) + "--" + str(self._current_cps) + "--" + str(self._total_game_cookies)
        
        
   
def simulate_clicker(build_info, duration, strategy):
    """
    Function to run a Cookie Clicker game for the given
    duration with the given strategy.  Returns a ClickerState
    object corresponding to game.
    """

    # Replace with your code
    build_info_clone = build_info.clone()
    new_clikcer_state = ClickerState()
    while new_clikcer_state.get_time()<duration:
#        print "A-1"
        if new_clikcer_state.get_time()>duration: #本句可省略?
            break
        suggested_item = strategy(new_clikcer_state.get_cookies(), new_clikcer_state.get_cps(),duration - new_clikcer_state.get_time(), build_info_clone)
#        print "A-2"
        if suggested_item == None: 
            new_clikcer_state.wait(duration - new_clikcer_state.get_time())
#        print "A-3"            
        else:
            cookies_needed = build_info_clone.get_cost(suggested_item)
            cps_added      = build_info_clone.get_cps(suggested_item)
            time_needed    = new_clikcer_state.time_until(cookies_needed)
#            print "A-4"        
            if time_needed + new_clikcer_state.get_time() > duration:
                new_clikcer_state.wait(duration - new_clikcer_state.get_time())
#            print "A-5"            
            else:
                new_clikcer_state.wait(time_needed)
                new_clikcer_state.buy_item(suggested_item, cookies_needed, cps_added)
                build_info_clone.update_item(suggested_item)
#                print "A-6"        
#            print "A-7"
    if  new_clikcer_state.get_time()==duration:
        suggested_item = strategy(new_clikcer_state.get_cookies(), new_clikcer_state.get_cps(),duration - new_clikcer_state.get_time(), build_info_clone)
    if suggested_item != None: 
        cookies_needed = build_info_clone.get_cost(suggested_item)
        cps_added      = build_info_clone.get_cps(suggested_item)
        if cookies_needed<=new_clikcer_state.get_cookies():
            new_clikcer_state.buy_item(suggested_item, cookies_needed, cps_added)
            build_info_clone.update_item(suggested_item)        
    return  new_clikcer_state
    #return ClickerState()


def strategy_cursor(cookies, cps, time_left, build_info):
    """
    Always pick Cursor!

    Note that this simplistic strategy does not properly check whether
    it can actually buy a Cursor in the time left.  Your strategy
    functions must do this and return None rather than an item you
    can't buy in the time left.
    """
    return "Cursor"

def strategy_none(cookies, cps, time_left, build_info):
    """
    Always return None

    This is a pointless strategy that you can use to help debug
    your simulate_clicker function.
    """
    return None

def strategy_cheap(cookies, cps, time_left, build_info):
    """cheap Strategy"""
    pricelist = {}
    funding = cookies + cps * time_left
    for item in build_info.build_items():
        if build_info.get_cost(item) <= funding:
            pricelist[build_info.get_cost(item)] = item
    if len(pricelist) > 0:
        return pricelist[min(pricelist)]
    else:
        return None

def strategy_expensive(cookies, cps, time_left, build_info):
    """Expensive Strategy"""
    pricelist = {}
    funding = cookies + cps * time_left
    for item in build_info.build_items():
        if build_info.get_cost(item) <= funding:
            pricelist[build_info.get_cost(item)] = item
    if len(pricelist) > 0:
        return pricelist[max(pricelist)]
    else:
        return None

def strategy_best(cookies, cps, time_left, build_info):
    """Best Strategy"""
    pricelist = {}
    funding = cookies + cps * time_left
    for item in build_info.build_items():
        if build_info.get_cost(item) <= funding:
            pricelist[build_info.get_cps(item)/build_info.get_cost(item)] = item
    if len(pricelist) > 0:
        return pricelist[max(pricelist)]
    elif len(pricelist) == 0: 
        return None
        
def run_strategy(strategy_name, time, strategy):
    """
    Run a simulation with one strategy
    """
    state = simulate_clicker(provided.BuildInfo({"Cursor":[15.0,50.0]},1.15), time, strategy)
#    state = simulate_clicker(provided.BuildInfo(), time, strategy)
    print strategy_name, ":", state

    # Plot total cookies over time

    # Uncomment out the lines below to see a plot of total cookies vs. time
    # Be sure to allow popups, if you do want to see it

#    history = state.get_history()
#    history = [(item[0], item[3]) for item in history]
#    simpleplot.plot_lines(strategy_name, 1000, 400, 'Time', 'Total Cookies', [history], True)

def run():
    """
    Run the simulator.
    """    
    run_strategy("Cursor", SIM_TIME, strategy_cursor)
#    run_strategy("Cursor", 16, strategy_cursor)

    # Add calls to run_strategy to run additional strategies
    #run_strategy("Cheap", SIM_TIME, strategy_cheap)
    #run_strategy("Expensive", SIM_TIME, strategy_expensive)
    #run_strategy("Best", SIM_TIME, strategy_best)
    
run()
    



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值