NEA Computing Task 2 Zar Oyunu
Aşağıda görüldüğü gibi son zamanlarda Görev 2 set ve birinin cevabını bu sitede soru gerçekleştirmek oldu burada ama taze bir görüş istedi
GÖREV 2:
- İki oyuncunun ayrıntılarını girmesine izin verir ve bunlar daha sonra yetkili oyuncular olduklarından emin olmak için doğrulanır.
- Her oyuncunun 6 taraflı iki zar atmasına izin verir.
- Her tur için puanları ve her oyuncunun toplam puanını hesaplar ve çıkarır.
- Oyuncuların 5 tur oynamasına izin verir.
- Her iki oyuncu da 5 turdan sonra aynı puana sahipse, her oyuncunun biri kazanana kadar her biri 1 ölmesine izin verin.
- 5 tur sonunda kazanan çıktılar.
- Kazananın puanını ve adını harici bir dosyada saklar.
- Harici dosyadan en çok kazanan 5 skorun skorunu ve oyuncu adını görüntüler.
try: File = open("Users.txt","r")
except FileNotFoundError:
raise SystemExit("User file not found")
File = open("Users.txt", "r")
def Login(Username, Player):
File.seek(0)
for Line in File:
ValidUsername = Line.split(",")[0]
ValidPassword = Line.split(",")[1].replace("\n", "")
if Username == ValidUsername:
Password = input("Password: ")
if Password == ValidPassword:
print("Player",Player,"logged in")
print("")
return True
else: print("Invalid Details")
return False
try:
while True:
print("Player 1 Login")
Username1 = input("Username: ")
if Login(Username1, 1): break
print("")
while True:
print("Player 2 Login")
Username2 = input("Username: ")
if Username1 == Username2:
print("Double login detected")
elif Login(Username2, 2): break
print("")
except KeyboardInterrupt:
raise SystemExit("Exiting...")
finally:
File.close()
import random
Player1Score = 0
Player2Score = 0
def Roll():
Dice1 = random.randint(1, 6)
Dice2 = random.randint(1, 6)
print("You rolled a",Dice1,"and a",Dice2)
Change = Dice1 + Dice2
Change += 10 if (Dice1 + Dice2) % 2 == 0 else -5
if Change < 0: Change = 0
if Dice1 == Dice2:
Dice3 = random.randint(1, 6)
print("Your third roll is a",Dice3)
Change += Dice3
print("")
return Change
for X in range(5):
print("Play:",X + 1,"starting")
input("Player 1, press enter to roll: ")
Player1Score += Roll()
input("Player 2, press enter to roll: ")
Player2Score += Roll()
print("Player 1 now has a score of",Player1Score)
print("Player 2 now has a score of",Player2Score)
print("")
if Player1Score > Player2Score: Winner = 1
if Player1Score < Player2Score: Winner = 2
if Player1Score == Player2Score:
print("You both got the same score")
def SameScore():
input("Press enter to roll dice: ")
print("")
Dice1 = random.randint(1, 6)
Dice2 = random.randint(1, 6)
print("Player 1 rolled:",Dice1)
print("Player 2 rolled:",Dice2)
if Dice1 == Dice2: return False
if Dice1 > Dice2: return 1
if Dice1 < Dice2: return 2
Winner = False
while not Winner:
Winner = SameScore()
if Winner == 1:
Winner = Username1 + ": " + str(Player1Score)
print(Username1,"won with",Player1Score,"points")
print(Username2,"lost with",Player2Score,"points")
if Winner == 2:
Winner = Username2 + ": " + str(Player2Score)
print(Username2,"won with",Player2Score,"points")
print(Username1,"lost with",Player1Score,"points")
WinnerScore = int(Winner.split(": ")[1])
FileWritten = False
try:
File = open("Scores.txt", "r")
Data = File.readlines();File.close()
for X in range(len(Data)):
if WinnerScore > int(Data[X].split(": ")[1]):
Data.insert(X, Winner + "\n")
if len(Data) > 5: Data.pop(5)
FileWritten = True; break
if len(Data) < 5:
if not FileWritten: Data.append(Winner + "\n")
File = open("Scores.txt","w")
for X in Data:
File.write(X.replace("\n","") + "\n")
except FileNotFoundError:
File = open("Scores.txt","w")
File.write(Winner + "\n")
File.close()
print("")
File = open("Scores.txt","r")
print("Highscores:")
for Line in File:
if Line != "": print(Line.replace("\n", ""))
File.close()
Herhangi bir düşünce / optimizasyon çok takdir edilecektir.
Yanıtlar
Kod İncelemesine Hoş Geldiniz!
BEP-8
Python'da temiz, sürdürülebilir ve tutarlı kod yazmak için PEP-8 stil kılavuzunu takip etmek yaygındır (ve önerilir).
Fonksiyonlar ve değişkenler a lower_snake_case, sınıflar as UpperCamelCaseve sabitler olarak adlandırılmalıdır UPPER_SNAKE_CASE.
f dizeleri
Python 3'te yeni tanıtılan f-string; yani yapabilmeniz yerine print("string", variable, "string"):
print(f"string {variable} string")
aynı etki için.
Fonksiyonlar
Tekil görevler yaparak kodunuzu daha küçük işlevlere bölün. Birkaç örnek, kullanıcı / şifreyi almak users.txt, kullanıcı bilgilerini doğrulamak, kullanıcı kimlik bilgilerini okumak vb. Olabilir.
if __name__ blok
Komut dosyaları için, çalıştırılabilir özelliğinizi if __name__ == "__main__"cümlenin içine koymak iyi bir uygulamadır .
Kontrol akışı
Kullanıcı dosyasını iki kez açmaya çalışırsınız (aynısı puan dosyası için de geçerlidir). Bunun ardından bir işlev tanımı ve ardından kullanıcıların oturum açmasını sağlayan bir kod gelir. Ardından, ilk import ifadenizi, ardından başka bir fonksiyon tanımını ve daha sonra tekrar kodu alırsınız.
Blokları birlikte gruplamayı deneyin. Python'da (ve neredeyse tüm programlama dillerinde), içe aktarmalar (shebang'dan sonra) ilk şeydir. Daha sonra global sabitler, fonksiyonlar / sınıf tanımları ve ardından kodun kendisi.
with ifadeler
Açılmış dosya tanımlayıcılarını yönetmek ve daha sonra bunların kapanmasını kontrol etmek yerine, python bunu withsizin için saran bir ifadeye sahiptir:
with open(your_file, mode) as f:
something = f.read()
# f.write(something)
bu otomatik olarak dosya tanımlayıcısını kapatır (ve kapsam dahilinde tutar).
İlişkili öznitelikler
Username, player_id, score gibi ilişkili özelliklere sahip oyuncu öğeniz var. Bu, her oyuncu için 10 farklı değişken sağlamak yerine bir sınıfa yerleştirilebilir.
Dahili yöntemler
Kodunuzun birçok yerinde bir .replace("\n", ""). Python'daki dizge nesnelerinin .strip()tüm boşlukları (ve satırsonları) temizleyen bir yöntemi olduğundan, buna gerçekten gerek yoktur .
Benzer şekilde, FileNotFoundErroraynı nedenden dolayı başka bir hatayı ortaya çıkarmak için yalnızca a yakalamaya çalışırsınız . İş için özel olarak tanımlanan hatanın bunu yapmasına izin verin. Yine de eksik dosya durumunda programın başarısız olmasını istiyorsanız yakalamaya gerek yoktur.
Yeniden yazmak
from operator import itemgetter
import random
USERS_FILE: str = "Users.txt"
SCORES_FILE: str = "Scores.txt"
NUM_PLAYERS: int = 2
NUM_ROUNDS: int = 5
def roll_die() -> int:
return random.randint(1, 6)
class Player:
def __init__(self, _id: int, name: str):
self._id = _id
self.name = name
self.score = 0
def add_score(self, value: int):
self.score += value
if self.score < 0:
self.score = 0
def turn(self):
input(f"{self.name}'s turn. Press enter to roll.")
dice_1 = roll_die()
dice_2 = roll_die()
print(f"{self.name} rolled {dice_1} and {dice_2}.")
change = dice_1 + dice_2
change += 10 if change % 2 == 0 else -5
if change < 0:
change = 0
if dice_1 == dice_2:
dice_3 = roll_die()
print(f"Third roll is {dice_3}")
change += dice_3
self.add_score(change)
def __str__(self) -> str:
return f"Player({self.name}): {self.score}"
def fetch_users() -> dict:
users = {}
with open(USERS_FILE, "r") as f:
users = dict([line.strip().split(",") for line in f])
return users
def authenticate(users: dict, name: str, password: str) -> bool:
return users.get(name) == password
def show_highscores() -> None:
with open(SCORES_FILE, "r") as f:
print(f.read())
def fetch_highscores() -> list:
scores = []
with open(SCORES_FILE, "r") as f:
for line in f:
name, score = line.strip().split(": ")
score = int(score)
scores.append((name, score))
return scores
def write_score(player: Player, limit: int = 5):
current_highscores = fetch_highscores()
current_highscores.append((player.name, player.score))
sorted_scores = sorted(current_highscores, key=itemgetter(1), reverse=True)
with open(SCORES_FILE, "w") as f:
for name, score in sorted_scores[:limit]:
f.write(f"{name}: {score}\n")
def get_player(_id: int, users: dict) -> Player:
print(f"Players {_id} login")
while True:
name = input("username: ")
password = input("password: ")
if authenticate(users, name, password):
return Player(_id, name)
print("Invalid details. Try again!")
def get_winning_player(players: list) -> Player:
def filter_winning_players(player_dices: list, value: int):
filtered = []
for player, dice in player_dices:
print(f"{player.name} rolled {dice}.")
if dice == value:
filtered.append(player)
return filtered
max_score = max([player.score for player in players])
winners = [player for player in players if player.score == max_score]
if len(winners) == 1:
return winners[0]
print(f"{len(winners)} players have the same score. Trying to determine single winning player.")
while True:
input("Press enter to roll dice: ")
dices = [roll_die() for _ in range(len(winners))]
max_dice = max(dices)
winners = filter_winning_players(zip(winners, dices), max_dice)
if len(winners) == 1:
return winners[0]
def game():
users = fetch_users()
players = [get_player(count + 1, users) for count in range(NUM_PLAYERS)]
for round in range(1, NUM_ROUNDS + 1):
for player in players:
player.turn()
print(f"Player scores at end of round {round}:")
for player in players:
print(str(player))
winner = get_winning_player(players)
print(f"Winner is {winner}.")
write_score(winner)
print("Highscores: ")
show_highscores()
if __name__ == "__main__":
game()
NOT
Yeniden yazma, birden çok raund ( NUM_PLAYERSve NUM_ROUNDS) ayarlama seçeneğiyle birlikte birden fazla oyuncuya izin verir .
Orada refactored edilebilir Kodunuzdaki çok fazla ama hadi biraz Python styleguides (diğer adıyla birlikte baştan başlamak PEP8 )
İthalat
Tüm içe aktarımları dosyanızın en üstüne yazmanız önerilir.
Adlandırma
Python'da, işlevlerin ve değişkenlerin adı snake_case d olmalıdır . Yani, def Roll()sizin yerine sahip olmanız gerekir def roll(), yerine sahip Player1Scoreolmanız gerekir player1_scorevb. Anladın. Burada daha fazlasını okuyun
Python'da `; 'ye HAYIR deyin!
;Python'da kullanmayın . Buna gerek yok ve C / C ++ kullandığım zor zamanları hatırlamamı sağlıyor. Üzülmemi istemiyorsun, değil mi? :(
Genel
Satır içi kod bloklarından kaçınmaya çalışmak genellikle iyi bir uygulamadır. Takip etmesi zor ve hiçbir faydası yok. Bu:
if Player1Score > Player2Score: Winner = 1
Şu şekilde yazılmalıdır:
if Player1Score > Player2Score:
Winner = 1
Bununla birlikte, yukarıdaki tavsiyeleri dikkate alarak şimdiye kadarki kodunuz şöyle görünecektir:
import random
try:
file = open("Users.txt", "r")
except FileNotFoundError:
raise SystemExit("User file not found")
file = open("Users.txt", "r")
def same_score():
input("Press enter to roll dice: ")
print("")
dice_1 = random.randint(1, 6)
dice_2 = random.randint(1, 6)
print("player 1 rolled:", dice_1)
print("player 2 rolled:", dice_2)
if dice_1 == dice_2:
return False
if dice_1 > dice_2:
return 1
if dice_1 < dice_2:
return 2
def login(username, player):
file.seek(0)
for line in file:
valid_username = line.split(",")[0]
valid_password = line.split(",")[1].replace("\n", "")
if username == valid_username:
password = input("password: ")
if password == valid_password:
print("player", player, "logged in")
print("")
return True
else:
print("Invalid Details")
return False
def roll():
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
print("You rolled a", dice1, "and a", dice2)
change = dice1 + dice2
change += 10 if (dice1 + dice2) % 2 == 0 else -5
if change < 0:
change = 0
if dice1 == dice2:
dice3 = random.randint(1, 6)
print("Your third roll is a",dice3)
change += dice3
print("")
return change
try:
while True:
print("player 1 login")
username1 = input("username: ")
if login(username1, 1):
break
print("")
while True:
print("player 2 login")
username2 = input("username: ")
if username1 == username2:
print("Double login detected")
elif login(username2, 2):
break
print("")
except KeyboardInterrupt:
raise SystemExit("Exiting...")
finally:
file.close()
player1_score = 0
player2_score = 0
for x in range(5):
print("Play:", x + 1, "starting")
input("player 1, press enter to roll: ")
player1_score += roll()
input("player 2, press enter to roll: ")
player2_score += roll()
print("player 1 now has a score of", player1_score)
print("player 2 now has a score of", player2_score)
print("")
if player1_score > player2_score:
winner = 1
if player1_score < player2_score:
winner = 2
if player1_score == player2_score:
print("You both got the same score")
winner = False
while not winner:
winner = same_score()
if winner == 1:
winner = username1 + ": " + str(player1_score)
print(username1, "won with", player1_score, "points")
print(username2, "lost with", player2_score, "points")
if winner == 2:
winner = username2 + ": " + str(player2_score)
print(username2, "won with", player2_score, "points")
print(username1, "lost with", player1_score, "points")
winner_score = int(winner.split(": ")[1])
file_written = False
try:
file = open("Scores.txt", "r")
data = file.readlines()
file.close()
for x in range(len(data)):
if winner_score > int(data[x].split(": ")[1]):
data.insert(x, winner + "\n")
if len(data) > 5:
data.pop(5)
file_written = True
break
if len(data) < 5:
if not file_written:
data.append(winner + "\n")
file = open("Scores.txt", "w")
for x in data:
file.write(x.replace("\n", "") + "\n")
except FileNotFoundError:
file = open("Scores.txt", "w")
file.write(winner + "\n")
file.close()
print("")
file = open("Scores.txt", "r")
print("Highscores:")
for line in file:
if line != "":
print(line.replace("\n", ""))
file.close()
Şimdi, bu biraz daha iyi. Şimdi gerçek uygulamayı tartışalım.
Buraya:
try:
file = open("Users.txt", "r")
except FileNotFoundError:
raise SystemExit("User file not found")
file = open("Users.txt", "r")
Bir dosyayı açmaya çalışıyorsunuz ve mevcut değilse, yükseltir ve istisna yaparsınız. Bunda mutlaka yanlış bir şey yok, ancak herhangi bir istisna yoksa dosyayı iki kez nasıl açtığınıza dikkat edin. Bir dosyanın var olup olmadığını kontrol etmek istiyorsanız, bir dosya osyolunun var olup olmadığını onaylamak için modülü kullanabilir ve bunu yapan bir işlev oluşturabilirsiniz. Ayrıca, dosya yolunu sabit yapın ve betiğinizin en üstüne koyun:
import os
USERS_FILEPATH = '/path/to/Users.txt'
def check_file(filepath):
"""Verify if a filepath exists.
Return True if a filepath exists. Otherwise raise an exception.
Arguments:
filepath (str): Path to a file
Returns:
True or raise an exception
"""
if not os.path.exists(filepath):
raise OSError('User filepath {} not found.'.format(filepath))
return True
İşlevi çağırmak için şunları yapabilirsiniz:
if check_path(USERS_FILEPATH):
# do things here
Burada birkaç yeni şey var. Öncelikle, bu işleve nasıl bir docstring eklediğime ve gerçekte ne yaptığını söylemenin ne kadar kolay olduğuna dikkat edin. İkinci olarak, bu işlevi oyununuzun kullanabileceği diğer dosyalarda kullanmanın ne kadar kolay olduğuna dikkat edin. Üçüncü olarak, bir istisna oluşturduğumda dizenin nasıl biçimlendirildiğine bakın. Sen biçimlendirme Python'un dizeleri hakkında daha fazla bilgi bulabilirsiniz burada .
// şimdilik gitmeliyim