Pyscript game version

This commit is contained in:
Mr Finchum 2025-03-16 23:22:14 +00:00
parent 433984bfb2
commit 54cd9d838b
5 changed files with 257 additions and 79 deletions

View file

@ -1,7 +1,9 @@
# Rock Paper Scissors Card Game # Rock Paper Scissors Card Game
Play [now](https://codebymrfinchum.pyscriptapps.com/rock-paper-scissors-card-game/latest/).
A little game to play the classic Rock Paper Scissors game with a twist. A little game to play the classic Rock Paper Scissors game with a twist.
Instead of freely selecting between Rock, Paper, and Scissors, you get a hand of three cards, potentially with only rocks. Instead of freely selecting between Rock, Paper, and Scissors, you get a hand of three cards, potentially with only rocks.
It is a semi-random 52-card deck with an unbalanced distribution of cards, meaning some cards are less likely to occur. For example, only 5 out of 52 cards are stones, so it is very unlikely the other player has a stone. Selecting scissors gives a higher chance of winning. It is a semi-random 52-card deck with an unbalanced distribution of cards, meaning some cards are less likely to occur. For example, only 5 out of 52 cards are stones, so it is very unlikely the other player has a stone. Selecting scissors gives a higher chance of winning.
This project is in its early stages. Some features are planned, but currently, it just runs in the terminal, and you can select cards. The *AI* selects a card completely at random. If there is a draw, you continue with the cards you started with. If one player wins, new cards are dealt. At the moment, there are two versions: a Python version for local usage (terminal), `local.py`, and a PyScript version, `main.py`.
The PyScript version can actually be accessed and played [online](https://codebymrfinchum.pyscriptapps.com/rock-paper-scissors-card-game/) on my [PyScript profile](https://pyscript.com/@codebymrfinchum).

44
src/index.html Normal file
View file

@ -0,0 +1,44 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Rock Paper Scissors Card Game</title>
<link
rel="stylesheet"
href="https://pyscript.net/releases/2025.3.1/core.css"
/>
<script
type="module"
src="https://pyscript.net/releases/2025.3.1/core.js"
></script>
</head>
<body>
<h1>Rock Paper Scissors Card Game</h1>
<p>
Play Rock Paper Scissors with a twist! Use a 52-card deck with an
uneven distribution of cards. Both you and the AI get three cards,
and the AI selects randomly. The rules follow the classic game, but
with an added element of chance!
</p>
<p>Select a card to play against the AI! Best out of 5 game mode.</p>
<h3>Score</h3>
<p>
You: <span id="user-score">0</span> - AI:
<span id="ai-score">0</span>
</p>
<h3 id="result">Waiting for your move...</h3>
<div id="card-buttons">
<button id="card-0" index="0" py-click="game.play_card">?</button>
<button id="card-1" index="1" py-click="game.play_card">?</button>
<button id="card-2" index="2" py-click="game.play_card">?</button>
</div>
<p></p>
<button id="reset-game" py-click="game.reset_game">Reset Game</button>
<script type="py" src="./main.py"></script>
</body>
</html>

98
src/local.py Normal file
View file

@ -0,0 +1,98 @@
import random
class RPSGame:
def __init__(self, best_of = 3):
self.deck = self.build_deck()
self.user_score = 0
self.ai_score = 0
self.rounds_to_win = (best_of // 2) + 1
def build_deck(self):
cards = [self.rock, self.paper, self.scissors]
deck = []
random.shuffle(cards)
for i in range(2):
n = random.randint(5, 20)
deck = cards[i](deck, n)
missing_cards = 52 - len(deck)
deck = cards[2](deck, missing_cards)
random.shuffle(deck)
return deck
def rock(self, lst, n):
lst.extend(["Rock"] * n)
return lst
def paper(self, lst, n):
lst.extend(["Paper"] * n)
return lst
def scissors(self, lst, n):
lst.extend(["Scissors"] * n)
return lst
def give_cards(self):
return [self.deck.pop(0) for _ in range(3)], [self.deck.pop(0) for _ in range(3)]
def battle(self, user_card, ai_card):
if user_card == ai_card:
return 0
if (user_card == "Rock" and ai_card == "Scissors") or \
(user_card == "Paper" and ai_card == "Rock") or \
(user_card == "Scissors" and ai_card == "Paper"):
return 1
return -1
def play_cards(self, user_hand, ai_hand):
while user_hand and ai_hand:
print(f"\nYour cards: {user_hand}")
while True:
try:
user_choice = int(input(f"Select a card (1-{len(user_hand)}): ")) - 1
if 0 <= user_choice < len(user_hand):
break
except ValueError:
pass
print("Invalid choice. Try again.")
user_card = user_hand.pop(user_choice)
ai_card = ai_hand.pop(random.randint(0, len(ai_hand) - 1))
print(f"You played: {user_card}, AI played: {ai_card}")
result = self.battle(user_card, ai_card)
if result == 1:
print("You win this round!")
return 1
elif result == -1:
print("AI wins this round!")
return -1
else:
print("It's a tie! Play again with remaining cards.")
print("No cards left, this round is a draw.")
return 0
def play_game(self):
while self.user_score < self.rounds_to_win and self.ai_score < self.rounds_to_win and len(self.deck) >= 6:
user_hand, ai_hand = self.give_cards()
round_result = self.play_cards(user_hand, ai_hand)
if round_result == 1:
self.user_score += 1
elif round_result == -1:
self.ai_score += 1
print(f"Score - You: {self.user_score}, AI: {self.ai_score}")
if self.user_score > self.ai_score:
print("\n🎉 You won the match!")
else:
print("\n🤖 AI won the match!")
if __name__ == "__main__":
game = RPSGame(best_of = 3)
game.play_game()

View file

@ -1,103 +1,136 @@
import random import random
from pyscript import document
def rock(lst, n): class RPSGame:
for _ in range(n): def __init__(self, best_of = 3):
lst.append("Rock") self.user_score = 0
return lst self.ai_score = 0
self.deck = self.build_deck()
self.user_hand, self.ai_hand = self.give_cards()
self.rounds_to_win = (best_of // 2) + 1
self.update_ui()
def paper(lst, n): def build_deck(self):
for _ in range(n): cards = [self.rock, self.paper, self.scissors]
lst.append("Paper") deck = []
return lst
def scissors(lst, n): random.shuffle(cards)
for _ in range(n): for i in range(2):
lst.append("Scissors") n = random.randint(5, 20)
return lst deck = cards[i](deck, n)
def build_deck(): missing_cards = 52 - len(deck)
cards = [rock, paper, scissors] deck = cards[2](deck, missing_cards)
deck = [] random.shuffle(deck)
return deck
random.shuffle(cards) def rock(self, lst, n):
for i in range(2): lst.extend(["Rock"] * n)
n = random.randint(5, 20) return lst
deck = cards[i](deck, n)
missing_cards = 52 - len(deck) def paper(self, lst, n):
deck = cards[2](deck, missing_cards) lst.extend(["Paper"] * n)
random.shuffle(deck) return lst
return deck
def give_cards(deck): def scissors(self, lst, n):
"""Give 3 cards to both player and AI, removing them from the deck.""" lst.extend(["Scissors"] * n)
return [deck.pop(0) for _ in range(3)], [deck.pop(0) for _ in range(3)] return lst
def battle(user_card, ai_card): def give_cards(self):
"""Returns 1 if user wins, -1 if AI wins, 0 for a tie.""" return [self.deck.pop(0) for _ in range(3)], [self.deck.pop(0) for _ in range(3)]
if user_card == ai_card:
return 0
if (user_card == "Rock" and ai_card == "Scissors") or \
(user_card == "Paper" and ai_card == "Rock") or \
(user_card == "Scissors" and ai_card == "Paper"):
return 1
return -1
def play_cards(user_hand, ai_hand): def battle(self, user_card, ai_card):
"""Handles playing cards until a winner is determined or cards run out.""" if user_card == ai_card:
while user_hand and ai_hand: # Keep playing until hands are empty return 0
print(f"\nYour cards: {user_hand}") if (user_card == "Rock" and ai_card == "Scissors") or \
(user_card == "Paper" and ai_card == "Rock") or \
(user_card == "Scissors" and ai_card == "Paper"):
return 1
return -1
while True: def refresh_hand(self):
try: self.user_hand, self.ai_hand = self.give_cards()
user_choice = int(input(f"Select a card (1-{len(user_hand)}): ")) - 1 print("New cards")
if 0 <= user_choice < len(user_hand): print(f"AI cards: {self.ai_hand}")
break
except ValueError:
pass
print("Invalid choice. Try again.")
user_card = user_hand.pop(user_choice) def play_card(self, event):
ai_choice = random.randint(0, len(ai_hand) - 1) index = int(event.target.getAttribute("index"))
ai_card = ai_hand.pop(ai_choice) #print(f"Button {index} clicked!") # Debugging
if index >= len(self.user_hand):
return
print(f"You played: {user_card}, AI played: {ai_card}") user_card = self.user_hand.pop(index)
ai_card = self.ai_hand.pop(random.randint(0, len(self.ai_hand) - 1))
result = battle(user_card, ai_card) result = self.battle(user_card, ai_card)
if result == 1: if result == 1:
print("You win this round!") self.user_score += 1
return 1 # User wins round_result = f"You win! {user_card} beats {ai_card}."
self.refresh_hand()
elif result == -1: elif result == -1:
print("AI wins this round!") self.ai_score += 1
return -1 # AI wins round_result = f"AI wins! {ai_card} beats {user_card}."
self.refresh_hand()
else: else:
print("It's a tie! Play again with remaining cards.") round_result = "It's a tie! Try again"
print("No cards left, this round is a draw.") if not self.user_hand or not self.ai_hand:
return 0 # Round is a draw self.refresh_hand()
if self.user_score < self.rounds_to_win and self.ai_score < self.rounds_to_win:
pass
else:
if self.user_score < self.ai_score:
round_result = "You lost noob D:"
self.update_ui(round_result)
self.disable_buttons()
#self.reset_game()
return
else:
round_result = "You won great :D"
self.update_ui(round_result)
self.disable_buttons()
#self.reset_game()
return
def play_game(best_of = 3): self.update_ui(round_result)
"""Main game loop."""
my_deck = build_deck()
user_score, ai_score = 0, 0
rounds_to_win = (best_of // 2) + 1
while user_score < rounds_to_win and ai_score < rounds_to_win and len(my_deck) >= 6: def update_ui(self, result_text="Waiting for your move..."):
user_hand, ai_hand = give_cards(my_deck) print("Update UI")
document.querySelector("#user-score").innerText = str(self.user_score)
document.querySelector("#ai-score").innerText = str(self.ai_score)
document.querySelector("#result").innerText = result_text
document.querySelector("#reset-game").disabled = False
for i in range(3):
btn = document.querySelector(f"#card-{i}")
if i < len(self.user_hand):
btn.innerText = self.user_hand[i]
btn.disabled = False
else:
btn.innerText = "?"
btn.disabled = True
round_result = play_cards(user_hand, ai_hand) def disable_buttons(self):
for i in range(3):
btn = document.querySelector(f"#card-{i}")
btn.innerText = "?"
btn.disabled = True
if round_result == 1: def reset_game(self, event=None):
user_score += 1 print("Game Reset")
elif round_result == -1: self.user_score = 0
ai_score += 1 self.ai_score = 0
self.deck = self.build_deck()
self.user_hand, self.ai_hand = self.give_cards()
self.deck_overview()
self.update_ui("Game reset! Pick a card to start.")
print(f"Score - You: {user_score}, AI: {ai_score}")
if user_score > ai_score: def deck_overview(self):
print("\n🎉 You won the match!") #print(f"{len(self.deck)} Cards left")
else: print(f"{self.deck.count('Rock')} Rock cards")
print("\n🤖 AI won the match!") print(f"{self.deck.count('Paper')} Paper cards")
print(f"{self.deck.count('Scissors')} Scissors cards")
# Run the game # Start the game
play_game(best_of = 5) game = RPSGame(5)
game.deck_overview()

1
src/pyscript.toml Normal file
View file

@ -0,0 +1 @@
name = "Rock Paper Scissors"