0

まず、あなたがとても素晴らしいナイスガイでない限り、あなたは私のためにこれをコーディングする必要はありません。しかし、皆さんはプログラミングが得意で、私や他のすべての人よりもはるかによく理解しているので、段落ごとに書いて理解させようとするよりも簡単かもしれません(おそらくコードの行数が多すぎないため)。

だから-私は新しいエントリで自分自身を更新するハイスコアのリストを作成する必要があります。 だからここに行く:

最初のステップ-完了

プレーヤーが入力した入力があります。これは、いくつかの計算のデータとして使用されています。

import time
import datetime

print "Current time:", time1.strftime("%d.%m.%Y, %H:%M")
time1 = datetime.datetime.now()
a = raw_input("Enter weight: ")    
b = raw_input("Enter height: ")
c = a/b

2番目のステップ-ハイスコアリストを作成する

ここでは、ある種の辞書か、前のエントリを読み取って、スコア(c)が「ハイスコア」の最後のスコアよりも(少なくとも)優れているかどうかを確認するものが必要になります。名前の入力を求められます。

あなたがあなたの名前を入力した後、それはあなたの名前、あなたの、、、、aそしてb時間cをハイスコアリストに投稿します。

これは私が思いついたものであり、それは間違いなく機能しません:

list = [("CPU", 200, 100, 2, time1)]
player = "CPU"
a = 200
b = 100
c = 2
time1 = "20.12.2012, 21:38"
list.append((player, a, b, c, time1))
list.sort()

import pickle
scores = open("scores", "w")
pickle.dump(list[-5:], scores)
scores.close()

scores = open("scores", "r")
oldscores = pickle.load(scores)
scores.close()
print oldscores()

私はひどく愚かなことをしたことを知っていますが、とにかく、これを読んでくれてありがとう、そしてあなたがこれで私を助けてくれることを願っています。:-)

4

4 に答える 4

4

listまず、変数名として使用しないでください。組み込みlistオブジェクトをシャドウします。datetime次に、適切な比較と簡単な変換をサポートするオブジェクトの操作がはるかに簡単になるため、単純な日付文字列の使用は避けてください。

これは、ステップを分割するのに役立つ個々の関数を含む、コードの完全な例です。あなたは明らかに学習しているだけなので、私はこれ以上高度なモジュールや機能を使用しないようにしています。

import os
import datetime
import cPickle

# just a constants we can use to define our score file location
SCORES_FILE = "scores.pickle"

def get_user_data():
    time1 = datetime.datetime.now()
    print "Current time:", time1.strftime("%d.%m.%Y, %H:%M")

    a = None
    while True:
        a = raw_input("Enter weight: ")    
        try:
            a = float(a)
        except:
            continue
        else:
            break

    b = None
    while True:
        b = raw_input("Enter height: ")    
        try:
            b = float(b)
        except:
            continue
        else:
            break

    c = a/b

    return ['', a, b, c, time1]

def read_high_scores():
    # initialize an empty score file if it does
    # not exist already, and return an empty list
    if not os.path.isfile(SCORES_FILE):
        write_high_scores([])
        return []

    with open(SCORES_FILE, 'r') as f:
        scores = cPickle.load(f)
    return scores

def write_high_scores(scores):
    with open(SCORES_FILE, 'w') as f:
        cPickle.dump(scores, f)

def update_scores(newScore, highScores):
    # reuse an anonymous function for looking
    # up the `c` (4th item) score from the object
    key = lambda item: item[3]

    # make a local copy of the scores
    highScores = highScores[:]

    lowest = None
    if highScores:
        lowest = min(highScores, key=key)

    # only add the new score if the high scores
    # are empty, or it beats the lowest one
    if lowest is None or (newScore[3] > lowest[3]):
        newScore[0] = raw_input("Enter name: ")
        highScores.append(newScore)

    # take only the highest 5 scores and return them
    highScores.sort(key=key, reverse=True)
    return highScores[:5]

def print_high_scores(scores):
    # loop over scores using enumerate to also
    # get an int counter for printing
    for i, score in enumerate(scores):
        name, a, b, c, time1 = score
        # #1    50.0    jdi    (20.12.2012, 15:02)
        print "#%d\t%s\t%s\t(%s)" % \
            (i+1, c, name, time1.strftime("%d.%m.%Y, %H:%M"))


def main():
    score = get_user_data()
    highScores = read_high_scores()

    highScores = update_scores(score, highScores)

    write_high_scores(highScores)
    print_high_scores(highScores)

if __name__ == "__main__":
    main()

現在のところ、新しいスコアを追加するのは、高いスコアがなかった場合、または最低のスコアを上回った場合のみです。以前のスコアが5未満の場合は、最低のスコアを上回るように要求するのではなく、常に新しいスコアを追加するように変更できます。そして、ハイスコアのサイズが5以上になった後、最低のチェックを実行します。

于 2012-12-20T22:58:59.003 に答える
2

list.sort()私が最初に気付いたのは、並べ替えが各エントリの最後の要素に基づくべきであるとあなたが言わなかったことです。デフォルトでlist.sort()は、Pythonのデフォルトの並べ替え順序を使用します。これにより、各エントリの最初の要素(つまり名前)に基づいてエントリが並べ替えられ、次に2番目の要素、3番目の要素などにモードが変更されます。したがって、list.sort()並べ替えに使用するアイテムを指定する必要があります。

from operator import itemgetter
[...]
list.sort(key=itemgetter(3))

これにより、各タプルのインデックス3のアイテム、つまり4番目のアイテムに基づいてエントリが並べ替えられます。

また、print oldscores()は関数ではないため、絶対に機能しません。したがって、演算子oldscoresで呼び出すことはできません。おそらくより良いです。()print oldscores

于 2012-12-20T21:48:53.497 に答える
1

ここに辞書は絶対に必要ありません。辞書の要点は、ソートせずにキーを値にマップできることです。必要なのはソートされたリストです。そして、あなたはすでにそれを持っています。

タマスが指摘しているように、実際にはスコアではなく、プレーヤー名でソートされたリストがあります。その上、上向きではなく下向きに並べ替えます。装飾-並べ替え-装飾解除パターン、キー関数などを使用できますが、何かを行う必要があります。また、それをという名前の変数に入れましたがlist、これはすでに型の名前であるため、非常に悪い考えlistです。

とにかく、標準ライブラリのモジュールを使用して、ソートされたに何かを追加するかどうかlist、および追加する場合はどこに挿入するかを確認できます。ただし、またはbisectのようなものを使用する方がおそらく簡単です。SortedCollectionblist

次に例を示します。

highscores = SortedCollection(scores, key=lambda x: -x[3])

さて、ゲームを終了すると:

highscores.insert_right((player, a, b, newscore, time1))
del highscores[-1]

それでおしまい。実際にトップ10に入っていなかった場合は、#11に追加されてから、削除されます。トップ10に入っていた場合は追加され、古い#10は#11になり、削除されます。

古いアーケードゲームのように10個の偽のスコアをリストに事前入力したくない場合は、次のように変更します。

highscores.insert_right((player, a, b, newscore, time1))
del highscores[10:]

さて、すでに10点ある場合は、追加すると#11が削除されますが、3点しかない場合は何も削除されず、4点になります。

その間、なぜ新しいスコアをpickleファイルに書き込んでから同じものを読み戻すのかわかりません。リストにハイスコアを追加する前に読み取りを行い、その後に書き込みを行うことをお勧めします。それを追加します。

また、「リストを美しくする」方法についても質問しました。それには3つの側面があります。

まず第一に、コードで(player, a, b, c, time1)は、あまり意味がありません。もちろん、変数に適切な名前を付けると役立ちますが、最終的には、リストにアクセスするときにentry[3]、スコアentry[4]を取得するか、時間を取得するために実行する必要があるという事実にたどり着きます。

これを解決するには、少なくとも3つの方法があります。

  • sの代わりにsのlist(またはSortedCollection)を格納します。コードはもう少し冗長になりますが、はるかに読みやすくなります。を記述し、リストにアクセスするときに、の代わりに記述します。dicttuple{'player': player, 'height': a, 'weight': b, 'score': c, 'time': time1}entry['score']entry[3]
  • のコレクションを使用しnamedtupleます。これで、実際に挿入するScoreEntry(player, a, b, c, time1)か、挿入することができますScoreEntry(player=player, height=a, weight=b, score=c, time=time1)。どちらかが特定の場合に読みやすく、どちらも同じように機能します。また、読みやすい方を使用して、entry.scoreまたはとしてアクセスできます。entry[3]
  • スコアエントリの明示的なクラスを記述します。これは前のものと非常に似ていますが、記述するコードが多く、インデックス付きアクセスを実行できなくなりますが、プラス面として理解する必要はありませんnamedtuple

第二に、あなたprintがエントリだけの場合、それらは混乱のように見えます。これに対処する方法は、文字列のフォーマットです。の代わりにprint scores、次のようにします。

print'\ n'.join( "{}:height {}、weight {}、score {} at {}"。format(entry)for entry in highscores)

だけでなくclassまたはを使用している場合は、位置ではなく名前でフォーマットすることもできるため、コードがはるかに読みやすくなります。namedtupletuple

最後に、ハイスコアファイル自体は、pickle人間が消費するためのものではないため、読み取り不能な混乱です。人間が読める形式にする場合は、形式を選択し、その形式をシリアル化するコードを記述する必要があります。幸い、CSV形式は人間が読める形式であり、ほとんどのコードはcsvモジュールで既に記述されています。(特にヘッダー行を記述したい場合は、クラスDictReaderDictWriterクラスを確認することをお勧めします。繰り返しになりますが、コードを少し増やして読みやすくするというトレードオフがあります。)

于 2012-12-20T22:26:20.190 に答える
1

これが私が気づいたことです。

これらの行は間違った順序になっているようです。

print "Current time:", time1.strftime("%d.%m.%Y, %H:%M")
time1 = datetime.datetime.now()

ユーザーが身長と体重を入力すると、整数ではなく文字列として読み込まれるため、次の行にTypeErrorが表示されます。

c = a/b

aとbをキャストして次のようにフロートさせることでこれを解決できます。

a = float(raw_input("Enter weight: "))

ただし、ユーザーがゴミを入れた場合に備えて、これをtry / catchブロックでラップする必要があります。基本的に、フロートにキャストできないものはすべてです。彼らがそれを正しくするまで、全体をしばらくの間ブロックしてください。

だから、このようなもの:

b = None
while b == None:
    try:
        b = float(raw_input("Enter height: "))
    except:
        print "Weight should be entered using only digits, like '187'"

したがって、2番目の部分ではlist、変数名として使用しないでください。これは組み込みであるため、を使用しますhigh_scores

# Add one default entry to the list
high_scores = [("CPU", 200, 100, 2, "20.12.2012, 4:20")]

プレーヤーのスコアをハイスコアと照合して、それが最高かどうかを確認したいとしますが、そうであれば、なぜリストを作成するのでしょうか。なぜ単一のエントリだけではないのですか?とにかく、それは私を混乱させます、あなたが本当にハイスコアリストが欲しいのか、それともただ1つのハイスコアが欲しいのかわかりません。

それでは、何があってもスコアを追加しましょう。

nameそれらの名前を変数に入れたと仮定します。

high_score.append((name, a, b, c, time1))

次に、@Tamásからの他の回答を適用します

于 2012-12-20T22:26:56.840 に答える