# Blackjack in Python

## Mở đầu

Blackjack, còn được gọi là 21, là một trong những trò chơi bài phổ biến nhất trên thế giới. Trò chơi này không chỉ mang đến sự thú vị và hồi hộp mà còn có yếu tố chiến thuật. Trong bài viết này, chúng ta sẽ cùng nhau khám phá cách xây dựng một trò chơi Blackjack đơn giản bằng Python. Qua từng bước, bạn sẽ hiểu rõ hơn về cấu trúc của trò chơi cũng như cách lập trình một game đúng nghĩa.

## 1. Giới thiệu về Blackjack

### 1.1. Quy tắc cơ bản

Blackjack là trò chơi giữa người chơi và nhà cái (dealer). Mục tiêu của người chơi là có được tổng điểm gần 21 nhất, nhưng không vượt quá 21. Mỗi lá bài có giá trị như sau:

- Các lá bài số từ 2 đến 10 có giá trị tương ứng.

- Các lá bài mặt (J, Q, K) có giá trị 10.

- Lá Át (A) có thể có giá trị 1 hoặc 11, tùy thuộc vào tình huống.

Người chơi và dealer lần lượt rút bài. Người chơi có thể chọn "hit" (rút thêm bài) hoặc "stand" (ngừng lại). Nếu tổng điểm vượt quá 21, người chơi sẽ "bust" và thua cuộc.

### 1.2. Cách chơi

Ban đầu, mỗi người nhận hai lá bài. Sau khi người chơi thực hiện các lựa chọn của mình, dealer cũng sẽ lần lượt rút bài cho đến khi có tổng điểm từ 17 trở lên.

Nếu người chơi có tổng điểm cao hơn dealer mà không vượt qua 21, người chơi thắng. Ngược lại, nếu dealer có tổng điểm cao hơn hoặc người chơi bust, thì dealer thắng.

## 2. Cấu trúc chương trình

### 2.1. Các thành phần chính

Để viết chương trình Blackjack, chúng ta cần những thành phần chính sau:

1. **Bộ bài**: Chứa 52 lá bài với các giá trị và chất liệu khác nhau.

2. **Người chơi**: Có thể rút bài hoặc dừng, với tổng điểm được tính toán.

3. **Dealer**: Cũng sẽ rút bài với quy tắc riêng.

4. **Quy trình chơi**: Điều khiển lượt chơi và quản lý các quyết định của người chơi và dealer.

### 2.2. Sử dụng lớp (class) trong Python

Chúng ta sẽ sử dụng các lớp để tổ chức mã nguồn của mình. Một số lớp quan trọng bao gồm:

- `Card`: đại diện cho một lá bài.

- `Deck`: đại diện cho bộ bài.

- `Player`: đại diện cho người chơi và dealer.

## 3. Cài đặt lớp Card

```python

class Card:

def __init__(self, suit, rank):

self.suit = suit

self.rank = rank

def value(self):

if self.rank in ['J', 'Q', 'K']:

return 10

elif self.rank == 'A':

return 11 # Tạm thời gán giá trị 11

else:

return int(self.rank)

def __str__(self):

return f"{self.rank} of {self.suit}"

```

### 3.1. Giải thích mã nguồn

- Lớp `Card` có hai thuộc tính chính là `suit` (chất liệu) và `rank` (giá trị).

- Hàm `value()` trả về giá trị của lá bài dựa trên quy tắc của trò chơi.

- Phương thức `__str__()` giúp hiển thị thông tin của lá bài.

## 4. Cài đặt lớp Deck

```python

import random

class Deck:

def __init__(self):

self.cards = [Card(suit, rank) for suit in ['Hearts', 'Diamonds', 'Clubs', 'Spades']

for rank in [str(num) for num in range(2, 11)] + ['J', 'Q', 'K', 'A']]

random.shuffle(self.cards)

def deal(self):

return self.cards.pop() if self.cards else None

```

### 4.1. Giải thích mã nguồn

- Lớp `Deck` tạo bộ bài với 52 lá và trộn ngẫu nhiên.

- Phương thức `deal()` dùng để rút một lá bài từ bộ bài.

## 5. Cài đặt lớp Player

```python

class Player:

def __init__(self, name):

self.name = name

self.hand = []

def add_card(self, card):

self.hand.append(card)

def total_value(self):

total = sum(card.value() for card in self.hand)

# Tính lại giá trị nếu có Át và tổng > 21

num_aces = sum(1 for card in self.hand if card.rank == 'A')

while total > 21 and num_aces:

total -= 10

num_aces -= 1

return total

```

### 5.1. Giải thích mã nguồn

- Lớp `Player` chứa tên người chơi và tay bài.

- Hàm `total_value()` tính toán tổng giá trị của tay bài, điều chỉnh giá trị của Át khi cần.

## 6. Thực thi trò chơi

```python

def play_blackjack():

print("Welcome to Blackjack!")

deck = Deck()

player = Player("Player")

dealer = Player("Dealer")

# Phát bài

for _ in range(2):

player.add_card(deck.deal())

dealer.add_card(deck.deal())

# Hiển thị tay bài của người chơi

print(f"{player.name}'s hand: {[str(card) for card in player.hand]}")

while True:

choice = input("Do you want to hit (h) or stand (s)? ").lower()

if choice == 'h':

player.add_card(deck.deal())

print(f"{player.name}'s hand: {[str(card) for card in player.hand]}")

if player.total_value() > 21:

print("Bust! You lose.")

return

else:

break

# Dealer chơi

while dealer.total_value()

dealer.add_card(deck.deal())

# So sánh kết quả

print(f"{dealer.name}'s hand: {[str(card) for card in dealer.hand]}")

player_total = player.total_value()

dealer_total = dealer.total_value()

if dealer_total > 21 or player_total > dealer_total:

print("You win!")

elif player_total

print("Dealer wins!")

else:

print("It's a tie!")

```

### 6.1. Giải thích mã nguồn

- Hàm `play_blackjack()` điều khiển toàn bộ quy trình chơi.

- Người chơi có thể chọn rút bài hoặc dừng lại.

- Dealer tự động chơi cho đến khi có tổng điểm tối thiểu là 17.

- Kết quả sẽ được so sánh và hiển thị cho người chơi.

## 7. Kết luận

Trò chơi Blackjack không chỉ là một trò giải trí mà còn là một bài học tuyệt vời về lập trình trong Python. Qua bài viết này, bạn đã nắm bắt được nền tảng căn bản để phát triển một game Blackjack đơn giản. Hy vọng rằng bạn sẽ tiếp tục khám phá và mở rộng trò chơi này với những tính năng mới để làm phong phú thêm trải nghiệm chơi game của mình!