如何将扑克“程序”的得分保存到json文件中
我在保存分数时遇到了一点问题。我想把所有的分数都保存在一个叫做PokerScores.json的文件里,然后在每场比赛结束时给赢家加分。此外,用户可以在洗牌后重置保存的分数(继续游戏时),但如果他决定保留分数,程序就会从这个json文件中读取保存的数据。不过,问题是程序一直告诉我有错误(肯定是我写的某个函数出了问题,因为其他关于游戏的代码都能正常工作),我不明白我哪里写错了。谢谢大家的帮助!
import random, time, json
from random import shuffle
from collections import Counter
from enum import Enum
class CardSuits(Enum):
Hearts = "Hearts"
Diamonds = "Diamonds"
Clubs = "Clubs"
Spades = "Spades"
class CardValues(Enum):
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = "J"
Queen = "Q"
King = "K"
Ace = "A"
class Card:
_symbols = {"Hearts": "♥️", "Diamonds": "♦️", "Clubs": "♣️", "Spades": "♠"}
def __init__(self, suit: CardSuits, value: CardValues) -> None:
self.suit = suit
self.value = value
def __str__(self) -> str:
return f"{self.value.value}{self._symbols[self.suit.name]}"
def __repr__(self) -> str:
return f"{self.value.value}{self._symbols[self.suit.name]}"
#LOAD SCORE
def load_scores():
try:
with open("PokerScores.json", "r") as file:
json.load(file)
except FileNotFoundError:
return [0, 0, 0]
#SAVING SCORE
def save_scores(scores):
with open("PokerScores.json", "w") as file:
json.dump(scores, file)
#GAME START
def start():
scores = load_scores()
play = input("You wanna play? ")
if play.lower() in ("yes", "sure", "yeah"):
all_cards = [Card(suits, value) for suits in CardSuits for value in CardValues]
shuffle(all_cards)
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
cards = list(unique_cards)
print("Your cards are:", ", ".join(str(card) for card in cards))
time.sleep(4)
#CHANGE PHASE
while True:
change_cards = input("Want to change cards? ")
if change_cards.lower() == "yes":
quantity = input("Which cards? ")
card_input_index = ["first", "second", "third", "fourth", "fifth"]
if quantity.lower() == "none":
break
elif quantity.lower() in card_input_index:
index = card_input_index.index(quantity.lower())
cards[index] = random.choice(all_cards)
print("Your new cards are:", ", ".join(str(card) for card in cards))
break
elif " " in quantity:
change_indices = quantity.lower().split()
if all(index in card_input_index for index in change_indices):
#controlla se tutti gli indici dati dall'utente siano presenti in card_input_index
#in questo modo non si ha più il problema che salta il passaggio del cambio delle
#carte se si scrive una parola a caso con uno spazio
for index in change_indices:
if index in card_input_index:
card_index = card_input_index.index(index)
cards[card_index] = random.choice(all_cards)
print("Your new cards are: ", ", ".join(str(card) for card in cards))
break
else:
print("Invalid cards selected")
elif quantity.lower() == "all":
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
cards = list(unique_cards)
print("Your new cards are:", ", ".join(str(card) for card in cards))
break
else:
print("Invalid cards selected")
elif change_cards.lower() == "no":
break
#OPPONENTS CARD CREATION
# First opponent
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
first_opponent_cards = list(unique_cards)
# Second
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
second_opponent_cards = list(unique_cards)
#CHECKING PHASE
def checking_phase(cards):
# dictionary for card values definition
custom_value_order = {
CardValues.Two : 2,
CardValues.Three : 3,
CardValues.Four : 4,
CardValues.Five : 5,
CardValues.Six : 6,
CardValues.Seven : 7,
CardValues.Eight : 8,
CardValues.Nine : 9,
CardValues.Ten : 10,
CardValues.Jack : 11,
CardValues.Queen : 12,
CardValues.King : 13,
CardValues.Ace : 14
}
#Straight
sorted_card_values = [custom_value_order[card.value] for card in cards]
sorted_card_values.sort()
is_straight = (max(sorted_card_values) - min(sorted_card_values) + 1) == len(cards)
#Flush
is_flush = len(set(card.suit for card in cards)) == 1
#Straight Flush
is_straight_flush = all([is_straight, is_flush]) # La funzione all() richiede un iterabile come argomento, come una lista, una tupla o un altro tipo di sequenza. Tuttavia, is_straight e is_flush sono valori booleani singoli, non un iterabile di valori, quindi bisogna usare le parentesi quadre per prenderli come singoli
#oppure is_straight_flush = is_straight and is_flush
#Royal Flush
max_straight = [CardValues.Ace, CardValues.King, CardValues.Queen, CardValues.Jack, CardValues.Ten]
is_royal_flush = is_straight_flush and all(card.value in max_straight for card in cards)
#Other combinations
cards_values_only = [card.value for card in cards]
cards_count = Counter(cards_values_only)
counts = list(cards_count.values())
counts.sort(reverse=True)
High_Card, Pair, Two_Pair, Three_of_a_Kind, Straight, Flush, Full, Four_of_a_Kind, Straight_Flush, Royal_Flush = ("High Card", "Pair", "Two Pair", "Three of a Kind", "Straight", "Flush", "Full", "Four of a Kind", "Straight Flush", "Royal Flush")
if is_royal_flush:
return Royal_Flush
elif is_straight_flush:
return Straight_Flush
elif counts == [4, 1]:
return Four_of_a_Kind
elif counts == [3, 2]:
return Full
elif is_flush:
return Flush
elif is_straight:
return Straight
elif counts == [3, 1, 1]:
return Three_of_a_Kind
elif counts == [2, 2, 1]:
return Two_Pair
elif counts == [2, 1, 1, 1]:
return Pair
else:
return High_Card
time.sleep(2)
user_hand = checking_phase(cards)
first_opponent_hand = checking_phase(first_opponent_cards)
second_opponent_hand = checking_phase(second_opponent_cards)
#SE AVVERSARI HANNO CARTA ALTA COME COMBINAZIONE, C'È UNA POSSIBILITÀ DEL 50% CHE CAMBINO TUTTE LE CARTE
if first_opponent_hand == "High Card":
change_chance = ["yes", "no"]
yes_or_no = random.choice(change_chance)
if yes_or_no == "yes":
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
first_opponent_cards = list(unique_cards)
first_opponent_hand = checking_phase(first_opponent_cards)
if second_opponent_hand == "High Card":
yes_or_no = random.choice(change_chance)
if yes_or_no == "yes":
unique_cards = set()
while len(unique_cards) <5:
unique_cards.add(random.choice(all_cards))
second_opponent_cards = list(unique_cards)
second_opponent_hand = checking_phase(second_opponent_cards)
print(f"""
Your hand: {user_hand}
1st Opponent hand: {first_opponent_hand} ( {", ".join(str(card) for card in first_opponent_cards)} )
2nd Opponent hand: {second_opponent_hand} ( {", ".join(str(card) for card in second_opponent_cards)} )
""")
#SCORE DASHBOARD
players = [user_hand, first_opponent_hand, second_opponent_hand]
scores = [0, 0, 0]
# Determina il giocatore con la combinazione più alta
max_hand_index = max(range(len(players)), key=lambda i: players[i])
# Incrementa il punteggio del giocatore con la combinazione più alta
scores[max_hand_index] += 1
save_scores(scores)
winning_player = ["You", "First opponent", "Second opponent"]
if winning_player[max_hand_index] == "You":
print("You won!")
else:
print(f"{winning_player[max_hand_index]} won. May you'll be luckier next time")
score_phrase = """
SCORE: User: {} | First opponent: {} | Second opponent: {} """
print(score_phrase.format(scores[0], scores[1], scores[2]))
time.sleep(5)
#CONTINUE PLAYING
while True:
continue_playing = input("You want to keep playing? ")
if continue_playing.lower() == "yes":
wanna_shuffle = input("Wanna shuffle the deck? ")
if wanna_shuffle.lower() == "yes":
shuffle(all_cards)
print("Deck shuffled")
break
elif wanna_shuffle.lower() == "no":
break
else:
continue
elif continue_playing.lower() == "no":
exit()
score_reset = input("Want to maintain the score or reset it? ")
if score_reset.lower() in ("reset", "reset it"):
test_file = open("PokerScores.json", "w")
test_file.write(json.dumps([0, 0, 0]))
test_file.close()
break
elif score_reset.lower() in ("maintain", "maintain it"):
break
start()
else:
exit()
start()
1 个回答
1
下次发帖时,最好把你遇到的错误信息贴出来,而不是整个代码。
你遇到的问题可能是因为第206行的if条件。如果程序在没有先进入前一个if条件的情况下进入了这个代码块,就会出错,因为change_chance这个变量还没有被设置。
解决办法是把这个变量在if-else结构之外设置好,像这样:
...
#SE AVVERSARI HANNO CARTA ALTA COME COMBINAZIONE, C'È UNA POSSIBILITÀ DEL 50% CHE CAMBINO TUTTE LE CARTE
change_chance = ["yes", "no"]
if first_opponent_hand == "High Card":
yes_or_no = random.choice(change_chance)
if yes_or_no == "yes":
unique_cards = set()
while len(unique_cards) < 5:
unique_cards.add(random.choice(all_cards))
first_opponent_cards = list(unique_cards)
first_opponent_hand = checking_phase(first_opponent_cards)
if second_opponent_hand == "High Card":
yes_or_no = random.choice(change_chance)
if yes_or_no == "yes":
unique_cards = set()
while len(unique_cards) <5:
unique_cards.add(random.choice(all_cards))
second_opponent_cards = list(unique_cards)
second_opponent_hand = checking_phase(second_opponent_cards)
...
关于分数系统,你一直在覆盖PokerScores.json文件的内容。我明白你想在用户决定重置之前累积分数,所以你需要先检查这个JSON文件是否存在,如果存在就读取它,计算总分,然后再把结果写回JSON文件。可以这样做:
def save_scores(score):
import os
filename = "PokerScores.json"
old_score = None
# We check if the file exists and if it is empty
if os.path.exists(filename) and os.path.getsize(filename) > 0:
# If it exists, we read the existing score
with open(filename, 'r') as file:
old_score = json.load(file)
if old_score:
# If there are previous scores, we make a sum of the previous and the new
score = [existing + new for existing, new in zip(old_score, score)]
# Write the scores back to the JSON file
with open(filename, 'w') as file:
json.dump(score, file)
如果你愿意,可以在文件顶部添加import os
这一行。记得每次开始游戏时都要使用文件中的分数,这样分数才能正确显示。
另一个问题是你加载了分数,但没有返回它们,所以你应该修改你的load_scores方法,像这样:
#LOAD SCORE
def load_scores():
try:
with open("PokerScores.json", "r") as file:
return json.load(file)
except FileNotFoundError:
return [0, 0, 0]
最后,如果你不想每轮都把分数重置为0,就得把这里设置分数为0的那一行去掉:
#SCORE DASHBOARD
players = [user_hand, first_opponent_hand, second_opponent_hand]
scores = [0, 0, 0]
# Determina il giocatore con la combinazione più alta
max_hand_index = max(range(len(players)), key=lambda i: players[i])
# Incrementa il punteggio del giocatore con la combinazione più alta
scores[max_hand_index] += 1
save_scores(scores)
如果分数变量不存在,你可以把分数设置为[0,0,0],可以用类似这样的代码(只是个建议):
scores = [0, 0, 0] if not scores else scores
不过你可以多尝试,直到找到你想要的效果。