Chuyên mục
Python Blog Uncategorized

Dự án “Thử thách sắp xếp”

Các bạn học sinh có còn nhớ dự án ““Nhà thám hiểm và cánh cửa bí mật” hay không? Ở dự án đó, nhà thám hiểm đã phải trải qua hành trình thật khó khăn khi phải lựa chọn 4 căn phòng bí ẩn, thế nhưng bạn ấy đã thành công lấy được kho báu và rời khỏi lâu đài. Trở lại với tòa lâu đài cổ kính đầy rẫy nguy hiểm, các con quái vật sau khi để mất kho báu đã họp bàn với nhau để tìm cách bảo vệ tòa lâu đài tốt hơn. Vậy là, nhân sư đã nâng cấp trò chơi của mình, không còn chỉ là game đoán số thông thường, mà là một thử thách sắp xếp đòi hỏi khả năng tính toán chính xác. 

Lần này, nhà thám hiểm lại quyết định quay trở lại tòa lâu đài bí ẩn. Làm thế nào để các bạn học sinh có thể giúp cho nhà thám hiểm an toàn rời khỏi nơi nguy hiểm đó? Để vượt qua thử thách của nhân sư, nhiệm vụ của chúng ta là sắp xếp các dãy số lộn xộn theo thứ tự từ lớn đến bé hoặc từ bé đến lớn. Chúng ta sẽ được chọn mình sắp xếp bao nhiêu số. Đặc biệt, các số trong dãy số sẽ ở dưới dạng các biểu thức cộng trừ, đòi hỏi sự tính toán thật nhanh và chính xác. Hãy thử sức chơi game với nhân sư ngay nào:

https://s4v.trinket.io/sites/sorting

Kiến thức lập trình 

Một số kiến thức chúng ta đã được học ở  khoá CS 101 sẽ được áp dụng để hoàn thành game nhập vai đơn giản này:

  • Thư viện random để tạo số ngẫu nhiên.
  • Vòng lặp forwhile trong Python.
  • Hàm (function)  trong Python
  • Chuỗi ký tự gồm nhiều dòng (Multi-line String)
  • Mảng trong Python 

Bắt đầu code thôi nào !!!!!

  1. Luật chơi:

Trò chơi bắt đầu khi nhân sư tạo một dãy số ngẫu nhiên dưới dạng các biểu thức cộng, trừ. Nếu sắp xếp theo thứ tự từ bé đến lớn, nhân sư sẽ hỏi người chơi lần lượt từ số bé nhất, số bé thứ hai, số bé thứ ba,… đến số lớn nhất.

Ví dụ: Một dãy số gồm các biểu thức: 3+1, 3-2, 1+1, 2+3. Sau khi tính toán, dãy số đó sẽ là 4, 1, 2, 5. Nhân sư yêu cầu người chơi sắp xếp từ bé đến lớn. Nhân sư sẽ hỏi: Số thứ nhất là số nào? Câu trả lời đúng là số 1. Nếu người chơi trả lời sai, trò chơi sẽ kết thúc. Nếu người chơi trả lời đúng, nhân sư sẽ tiếp tục hỏi: Số thứ hai là số nào? Câu trả lời đúng là 2. Nếu người chơi trả lời sai, trò chơi sẽ kết thúc. Nếu người chơi trả lời đúng, nhân sư sẽ tiếp tục hỏi số thứ ba. Trò chơi tiếp tục như thế đến số cuối cùng. Nếu người chơi trả lời đúng hết thì người chơi sẽ chiến thắng. 

Luật chơi tương tự với trường hợp sắp xếp từ lớn đến bé.

  1. Thuật toán:

Chúng ta sẽ tạo một thuật toán đơn giản để có thể mô phỏng trò chơi này. Chúng ta sẽ sử dụng hai mảng. Một mảng  lưu các biểu thức dưới dạng chuỗi. Mảng còn lại lưu kết quả các biểu thức đó. Ví dụ:  Mảng  lưu dãy các biểu thức: [‘3+1’, ‘3-2’, ‘1+1’, ‘2+3’]. Sau khi tính toán, mảng còn lại sẽ lưu kết quả  dãy số đó sẽ là [4, 1, 2, 5]. Ở đây, mục đích của mảng gồm các chuỗi  là dùng để in ra màn hình cho người chơi. Mảng kết quả gồm các số sẽ dùng để sắp xếp.

Trong luật chơi, nhân sư sẽ hỏi lần lượt các số theo thứ tự từ bé đến lớn (hoặc từ lớn đến bé). Vì vậy, chúng ta có thể tìm số bé nhất (hoặc lớn nhất) trong mảng. Qua mỗi lần nhân sư hỏi, chúng ta sẽ bỏ số bé nhất (hoặc lớn nhất) ra khỏi mảng, và tiếp tục tìm số bé nhất (hoặc lớn nhất) của mảng mới đến khi mảng không còn phần tử nào. 

Ví dụ:  Dãy gồm các biểu thức: 3+1, 3-2, 1+1, 2+3. Sau khi tính toán, dãy kết quả sẽ là 4, 1, 2, 5. Nhân sư yêu cầu người chơi sắp xếp từ bé đến lớn. 

  • Ở lượt thứ nhất, số bé nhất là 1. Sau lượt thứ nhất, chúng ta sẽ bỏ số 1 ra khỏi mảng. Mảng mới sẽ gồm 3 số là 4, 2, 5.
  • Ở lượt thứ hai, số bé nhất là 2. Sau lượt thứ hai, chúng ta sẽ bỏ số 2 ra khỏi mảng. Mảng mới sẽ gồm 2 số là 4, 5.
  • Ở lượt thứ ba, số bé nhất là 4. Sau lượt thứ ba, chúng ta sẽ bỏ số 4 ra khỏi mảng.
  • Mảng mới sẽ còn lại số 5. Số 5 là số cuối cùng. Như vậy, chúng ta đã gián tiếp sắp xếp dãy số ban đầu từ bé đến lớn.

      3. Code:   

Bước 1: Viết hàm giới thiệu game

Trước tiên, chúng ta sẽ tạo một hàm sử dụng câu lệnh print() để in ra màn hình luật chơi cũng như giới thiệu về game:

def intro():
    print('''
    ---
    NUMBER SORTING ++
    ---
    RULE:       Nhiệm vụ của trò chơi là sắp xếp 1 dãy số lộn xộn theo thứ tự từ bé đến lớn hoặc từ lớn đến bé.
                Người chơi sẽ được chọn sắp xếp bao nhiêu số trong dãy số
                Đặc biệt: Các số trong dãy sẽ được cho dưới dạng các biểu thức cộng trừ, đòi hỏi chúng ta cần kĩ năng tính toán cực cao nữa đó!
    ''')

Ở bài số 2, chúng ta đã biết về kiểu dữ liệu chuỗi (string). Từ trước đến nay, ta đều nhận thấy dữ liệu string phải ở trong cùng 1 dòng bắt đầu và kết thúc với dấu “”. Tuy nhiên, nếu ta sử dụng ”’  ”’ (3 dấu ‘), dữ liệu chuỗi có thể gồm nhiều dòng khác nhau (multi-line string).

Bước 2: Viết câu lệnh tương tác với người dùng ở đầu game

Tương tự như dự án “Nhà thám hiểm và cánh cửa bí mật”, chúng ta sẽ tạo một vòng lặp while để hỏi người chơi muốn tiếp tục trò chơi hay dừng lại. Đồng thời chúng ta sẽ in ra luật chơi bằng cách gọi hàm intro đã viết ở bước 1. Chúng ta lưu ý để gọi hàm intro, chúng ta chỉ cần dùng intro() vì hàm không return gì cả. Chúng ta cũng sẽ tạo một biến để hỏi người chơi muốn sắp xếp bao nhiêu số bằng câu lệnh input.

condition = True
while condition == True:                               
  intro()                                             
  number_guest = int(input("Bạn muốn sắp xếp bao nhiêu số nhỉ? >> "))               
        
  again = input('Bạn muốn chơi tiếp không? [Y/N]')                                    
  if again == 'N':
     condition = False

Bước 3: Viết hàm tạo dãy số ngẫu nhiên

Trò chơi sẽ gồm bốn loại biểu thức: a+b, a-b, a+b-c, a-b+c. a, b, c là các số nguyên ngẫu nhiên từ 1 đến 60. Chúng ta sẽ sử dụng câu lệnh random.randint(1,60) tương tự như dự án “Nhà thám hiểm và cánh cửa bí mật”. Mỗi biểu thức trong dãy số sẽ được chọn ngẫu nhiên từ bốn loại biểu thức bằng câu lệnh random.choice tương tự như dự án “Câu chuyện ngẫu nhiên”

Chúng ta sẽ sử dụng hai mảng raw_list1 raw_list2. Mảng raw_list1 lưu biểu thức dưới dạng chuỗi và mảng raw_list2 lưu kết quả của biểu thức. Ở bài số 3, chúng ta đã biết câu lệnh append dùng để lưu dữ liệu vào mảng. Ngoài ra để đổi số thành chuỗi chúng ta sẽ sử dụng hàm str. Để kết nối hai chuỗi, chúng ta sẽ sử dụng phép toán +. Ngoài ra chúng ta cũng không muốn các số trong dãy số lặp lại nên sẽ dùng câu lệnh not in để kiểm tra. “Not in” có nghĩa là không ở trong cái gì đó.   

Chúng ta sẽ tạo hai mảng trống rawlist1 rawlist2. Để dãy số có đủ số mà người chơi muốn sắp xếp, chúng ta sẽ sử dụng vòng lặp while và biến đếm i. Chúng ta sẽ đặt tên cho hàm tạo dãy số ngẫu nhiên là prep. Hàm nhận vào số biểu thức người chơi muốn sắp xếp và trả về hai mảng:

def prep(number_sort):
    rawlist1 = []
    rawlist2 = []                         
    i = 0
    while i < number_sort:                          
        a = random.randint(1,60)                               
        b = random.randint(1,60)
        c = random.randint(1,60)
        options = ["a+b", "a-b", "a+b-c", "a-b+c"]             
        option = random.choice(options)

        if option == 'a+b' and a+b not in rawlist1:
            rawlist1.append(str(a)+ ' + '+ str(b))                         
            rawlist2.append(a+b)                              
        elif option == 'a-b' and a-b not in rawlist2:
            rawlist1.append(str(a)+ ' - '+ str(b))                        
            rawlist2.append(a-b)                               
        elif option == 'a+b-c' and a+b-c not in rawlist2:       
            rawlist1.append(str(a) + "+" + str(b) + "-" + str(c))
            rawlist2.append(a+b-c)
        elif option == 'a-b+c' and a-b+c not in rawlist2:
            rawlist1.append(str(a) + "-" + str(b) + "+" + str(c))
            rawlist2.append(a-b+c)
        i = i + 1
    return rawlist1, rawlist2

Bước 4: Viết hàm trả về số bé nhất (hoặc lớn nhất)

Chúng ta sẽ sử dụng hai hàm có sẵn ở trong Python. Hàm min dùng để tìm số bé nhất trong mảng và hàm max để tìm số lớn nhất trong mảng. Chúng ta sẽ đặt tên hàm cần viết là sorting. Hàm nhận vào mảng (dãy số) và kiểu sắp xếp. Kiểu sắp xếp nhận một trong hai giá trị: 0 (sắp xếp từ bé đến lớn) hoặc 1 (sắp xếp từ lớn đến bé). Hàm trả về số bé nhất (hoặc lớn nhất) tương ứng với cách sắp xếp.

def sorting(arr, sort_type):                 
  
  if sort_type == 0:
     return min(arr)
  else: 
     return max(arr)

Bước 5: Hoàn thiện code

Sau khi hỏi người chơi muốn sắp xếp bao nhiêu số, chúng ta sẽ chọn ngẫu nhiên cách sắp xếp bằng sử dụng câu lệnh random.randint(0,1). Nếu kết quả là 0 thì sắp xếp từ bé đến lớn. Nếu kết quả là 1 thì sắp xếp từ lớn đến bé.

Chúng ta sẽ gọi hàm prep để tạo dãy số ngẫu nhiên đã viết ở bước 2. Chúng ta sẽ in ra màn hình mảng gồm các biểu thức cần sắp xếp và cách thức sắp xếp.  

import random
condition = True
while condition == True:
    intro()
    number_guest = int(input('Bạn muốn sắp xếp bao nhiêu số ? >>'))
    sort_type = random.randint(0,1)

    raw_list1, raw_list2 = prep(number_guest)
    if sort_type == 0:
        print('Sắp xếp dãy số theo thứ tự từ bé đến lớn: ' + str(raw_list1))
    else:
        print('Sắp xếp dãy số theo thứ tự từ lớn đến bé: ' + str(raw_list1))

 	again = input('Bạn có muốn chơi tiếp không? [Y/N]')
    	if again == 'N':
         condition = False

Chúng ta sẽ tạo một vòng lặp while với biến đếm counter để đi qua số lượt nhân sư sẽ hỏi người chơi (bằng với số phần tử của mảng). Với mỗi lượt hỏi, chúng ta sẽ thực hiện ba công việc: 

  • Tìm số bé nhất (hoặc lớn nhất) trong mảng.
  • Hỏi người chơi xem số tiếp theo trong dãy sau khi được sắp xếp là số nào. Kiểm tra đúng hay sai. Nếu đúng thực hiện bước tiếp theo. Nếu sai thoát khỏi vòng lặp.
  • Bỏ số tìm được ở công việc đầu tiên ra khỏi mảng. 

Để tìm số lớn nhất (bé nhất), chúng ta sử dụng hàm đã viết ở bước 3. Chúng ta sử dụng câu lệnh điều kiện giống như thuật toán Cánh cửa bí mật ở bài số 2 để kiểm tra người chơi có nhập đúng số không. Để bỏ một số ra khỏi mảng, chúng ta sẽ sử dụng hàm remove:

  turn = len(raw_list2)
  counter = 0
  while counter < turn:
number = sorting(raw_list2, sort_type)
guess = int(input('Sau khi sắp xếp, số ở vị trí số '+        str(counter + 1) + ' là: >>'))
        
if guess == int(number):
  if counter == turn - 1:
    print('Chúc mừng chiến thắng')
  else:
    print('Đúng rồi! Tiếp tục nào!')
else:
    print('Bạn đã thua, câu trả lời là ' + str(number))
    break
raw_list2.remove(number)
counter = counter + 1

4.  Tada!!! 

Như vậy chúng ta đã hoàn thành xong một game rất thú vị đúng không nào. Các bạn học sinh đã thành công áp dụng kiến thức về hàm đã học ở bài số 4 để viết một thuật toán sắp xếp một dãy số. Ngoài ra, chúng ta cũng biết thêm một số hàm mới có sẵn trong Python giúp chúng ta code thuận tiện hơn  

Chương trình Python hoàn chỉnh của game sẽ là:

# -*- coding: utf-8 -*-

import random

def intro():
  print('''
  ---
  NUMBER SORTING ++
  ---
  RULE:   Nhiệm vụ của trò chơi là sắp xếp 1 dãy số lộn xộn theo thứ tự từ bé đến lớn hoặc từ lớn đến bé.
          Người chơi sẽ được chọn sắp xếp bao nhiêu số trong dãy số
          Đặc biệt: Các số trong dãy sẽ được cho dưới dạng các biểu thức cộng trừ, đòi hỏi chúng ta cần kĩ năng tính toán cực cao nữa đó!
    ''')

def prep(number_sort):
  rawlist1 = []
  rawlist2 = []                         
  i = 0
  while i < number_sort:                          
    a = random.randint(1,60)                               
    b = random.randint(1,60)
    c = random.randint(1,60)
    options = ["a+b", "a-b", "a+b-c", "a-b+c"]             
    option = random.choice(options)

    if option == 'a+b' and a+b not in rawlist1:
       rawlist1.append(str(a)+ ' + '+ str(b))                         
       rawlist2.append(a+b)                              
    elif option == 'a-b' and a-b not in rawlist2:
       rawlist1.append(str(a)+ ' - '+ str(b))                        
       rawlist2.append(a-b)                               
    elif option == 'a+b-c' and a+b-c not in rawlist2:       
       rawlist1.append(str(a) + "+" + str(b) + "-" + str(c))
       rawlist2.append(a+b-c)
    elif option == 'a-b+c' and a-b+c not in rawlist2:
       rawlist1.append(str(a) + "-" + str(b) + "+" + str(c))
       rawlist2.append(a-b+c)
        i = i + 1
    return rawlist1, rawlist2

def sorting(arr, sort_type):                 
  
    if sort_type == 0:
       return min(arr)
    else: 
       return max(arr)	

condition = True
while condition == True:
  intro()
  number_guest = int(input('Bạn muốn sắp xếp bao nhiêu số ? >>'))
  sort_type = random.randint(0,1)

  raw_list1, raw_list2 = prep(number_guest)
  if sort_type == 0:
     print('Sắp xếp dãy số theo thứ tự từ bé đến lớn: ' + str(raw_list1))
  else:
     print('Sắp xếp dãy số theo thứ tự từ lớn đến bé: ' + str(raw_list1))
    
  turn = len(raw_list2)
  counter = 0
  while counter < turn:
    number = sorting(raw_list2, sort_type)
     guess = int(input('Sau khi sắp xếp, số ở vị trí số '+        str(counter + 1) + ' là: >>'))
        
    if guess == int(number):
     if counter == turn - 1:
        print('Chúc mừng chiến thắng')
     else:
        print('Đúng rồi! Tiếp tục nào!')
     else:
        print('Bạn đã thua, câu trả lời là ' + str(number))
        break
     raw_list2.remove(number)
     counter = counter + 1
   again = input('Bạn có muốn chơi tiếp không? [Y/N]')
   if again == 'N':
      condition = False

Các bạn học sinh hãy tự do sáng tạo theo những ý tưởng của riêng mình. Chúng ta có rất nhiều cách để cải tiến game khác lạ hơn. Thầy cô gợi ý các bạn có thể sắp xếp dãy số bằng hàm có sẵn trong Python là sorted. Sắp xếp dãy số trước khi hỏi người chơi sẽ giúp chương trình chúng ta chạy nhanh hơn. Ngoài ra, các bạn có thể thêm vào những loại biểu thức khác nhau, và thêm phép tính nhân, chia. Các bạn học sinh hãy thử tạo nên dự án của riêng mình và chia sẻ game của mình trên STEAMese Profile nhé!

— — —

STEAM for Vietnam Foundation là tổ chức phi lợi nhuận 501(c)(3) được thành lập tại Hoa Kỳ với sứ mệnh thúc đẩy các hoạt động liên quan tới giáo dục STEAM (Science — Khoa học, Technology — Công nghệ, Engineering — Kỹ thuật, Arts — Nghệ thuật, Mathematics — Toán học) tại Việt nam. STEAM for Vietnam được thành lập và vận hành bởi đội ngũ tình nguyện viên là du học sinh và chuyên gia người Việt trên khắp thế giới.

— — —

📧Email: hello@steamforvietnam.org

🌐Website: www.steamforvietnam.org

🌐Fanpage: STEAM for Vietnam

📺YouTube:  http://bit.ly/S4V_YT

🌐Zalo: Zalo Official       

Chuyên mục
Python Blog Uncategorized

Dự án “Mã hóa Caesar”

  1. Mã hóa Caesar là gì?

Mã hoá là phương pháp để biến thông tin (hình ảnh, văn bản) từ định dạng bình thường sang dạng thông tin mà chúng ta không thể hiểu được nếu không có phương tiện giải mã. Đồng thời, mã hoá có vai trò quan trọng trong giao dịch điện tử để đảm bảo độ bảo mật, toàn vẹn của thông tin khi truyền trên mạng. Thông thường, mã hóa được áp dụng nhiều trong các ví điện tử quen thuộc với chúng ta như Momo, Zalopay, Shopee Pay….Trái lại, giải mã là quá trình ngược của mã hoá, biến thông tin từ dạng được mã hoá về dạng thông tin ban đầu. 

Mật mã Caesar là một dạng mật mã thay thế, trong đó mỗi ký tự ở văn bản ban đầu sẽ được thay thế bằng một ký tự khác, có vị trí cách nó một khoảng xác định trong bảng chữ cái. Cũng giống như các loại mật mã thay thế khác, mật mã Caesar rất dễ bị phá giải. Tuy nhiên đây là một bài toán hay để chúng ta áp dụng kiến thức đã học về “vòng lặp” và “mảng” ở bài 3 của khoá CS 101. Hãy thử tưởng tượng các bạn muốn kể một câu chuyện bí mật cho người bạn thân của mình. Để bảo mật câu chuyện riêng tư không bị lộ ra ngoài, chúng ta cần mã hóa câu chuyện và gửi cho bạn mình kèm với phương pháp giải mã. Cách làm này hết sức thú vị phải không nào!

Người đã sáng chế ra cách mã hóa Caesar thú vị là vị hoàng đế Julius Caesar. Kỹ thuật này đã được phát triển vào khoảng năm 100 Trước Công nguyên. Hoàng đế Caesar đã dùng nó để gửi những mệnh lệnh quan trọng cho những tướng sĩ trên chiến trường. Do đó, nếu bọn giặc có bắt được người truyền tin thì cũng không thể đọc và hiểu được nội dung của bức thư mã hóa đó. Kiến thức này thật sự rất hữu ích và được áp dụng cho tới ngày hôm nay. 

  1. Kiến thức lập trình:

Một số kiến thức chúng ta đã được học ở bài 3 của khoá CS 101 sẽ được áp dụng để hoàn thành chương trình mã hoá này: 

  • Mảng và cách lấy phần tử của mảng trong Python.
  • Vòng lặp forwhile trong Python.
  • Câu lệnh input() để nhập dữ liệu trong Python.
  • Câu lệnh print() để in thông báo ra màn hình.
  • Kiểu dữ liệu boolean trong Python với so sánh ==.
  1. Bài toán:

Chúng ta sẽ sử dụng Thonny để xây dựng một chương trình vừa giúp mã hoá, vừa giúp giải mã Caesar. Chương trình sẽ cho người dùng nhập một câu muốn mã hoá và số ký tự muốn dịch chuyển trong bảng chữ cái (k). Số k dương sẽ dịch chuyển văn bản sang phải (theo thứ tự từ A sang Z). Số k âm sẽ dịch chuyển văn bản sang trái (theo thứ tự từ Z sang A). 

Ví dụ 1:

Văn bản gốc (Văn bản chưa mã hóa): ABCDEF

Văn bản mã hóa: CDEFGH

Trong ví dụ trên, các kí tự trong văn bản gốc được mã hóa bằng cách dịch sang phải 2 kí tự. k=2

GốcABCDEFXYZ
Mã hóaCDEFGHZAB

Vì được dịch sang phải 2 ký tự nên A được mã hóa thành C, B mã hóa thành D… Đặc biệt, Y được mã hóa thành A, Z được mã hóa thành B, quay lại các ký tự đầu tiên.

Ví dụ 2:

Văn bản gốc (Văn bản chưa mã hóa): ABCDEF

Văn bản mã hóa: YZABCD

Trong ví dụ trên, các kí tự trong văn bản gốc được mã hóa bằng cách dịch sang trái 2 kí tự. k=-2

GốcABCDEFXYZ
Mã hóaYZABCDUVX

Vì được dịch sang trái 2 ký tự nên C được mã hóa thành A, D mã hóa thành B… Đặc biệt, A được mã hóa thành Y, B được mã hóa thành Z, quay lại các ký tự cuối cùng.

Chúng ta có thể thấy rằng k âm là phương pháp giải mã cho mã hoá với k dương và ngược lại.

Trước khi bắt tay vào lập trình, chúng ta có thể thử chương trình để mã hoá và giải mã Caesar: https://s4v.trinket.io/sites/caesar    

  1. Bắt tay vào lập trình thôi nào!!!

a. Thuật toán

Trước khi bắt tay vào viết code, chúng ta sẽ cùng suy nghĩ một thuật toán để giải quyết bài toán này nhé. Chúng ta có thể biểu diễn tất cả các ký tự trong bảng chữ cái bằng một mảng trong Python.

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']

Mảng arr 26 phần tử. Với một ký tự bất kỳ, chúng ta có thể tìm được vị trí (index) i của nó trong mảng. Do đó khi dịch chuyển ký tự đó sang phải k kí tự, vị trí mới sẽ là i + k. Nếu dịch chuyển ký tự đó sang trái k kí tự thì khi đó k < 0 nên vị trí mới vẫn sẽ là i + k.

Trong trường hợp chúng ta dịch chuyển qua hai đầu của bảng chữ cái thì sao nhỉ? Ví dụ: Ký tự ‘X’ ở vị trí 23 trong mảng. Khi dịch chuyển sang phải 3 ký tự, vị trí mới sẽ là 23 + 3 = 26. Tuy nhiên vị trí cuối cùng của mảng arr 25. Do đó, chúng ta phải quay lại vị trí đầu tiên (0) của ký tự ‘A’. Trong trường hợp này, khi dịch chuyển, chúng ta đã đi hết 1 lượt mảng arr. Chúng ta có thể thấy công thức tính vị trí sau khi dịch chuyển là 23 + 3 – 26 * 1 = 0

Lấy một ví dụ khác: Ký tự ‘X’ ở vị trí 23 trong mảng. Khi dịch chuyển sang trái 80 ký tự, vị trí mới sẽ là 23 – 80 = -57. Từ vị trí ký tự ‘X’,  nếu dịch sang trái 23 ký tự, chúng ta sẽ đến vị trí của ký tự ‘A’. Như vậy, chúng ta đã đi hết 1 lượt mảng arr. Từ vị trí ký tự ‘A’, dịch tiếp sang trái 26 ký tự, chúng ta sẽ đi hết một lượt nữa mảng arr và quay lại vị trí ký tự ‘A’. Tiếp tục dịch sang trái 26 ký tự, chúng ta sẽ tiếp tục đi hết một lượt nữa mảng arr và quay lại vị trí ký tự ‘A’. Chúng ta còn phải dịch sang trái 5 ký tự nữa. Như vậy chúng ta sẽ đến vị trí ký tự ‘V’. Tóm lại, chúng ta đã đi hết 3 lượt mảng arr. Chúng ta có thể thấy công thức tính vị trí sau khi dịch chuyển là 23 – 80 + 26 * 3 = 21

Để tính xem phải đi qua mảng arr bao nhiêu lần, chúng ta có thể sử dụng phép toán floor division trong Python. Floor division trong Python là //. Floor division sẽ trả về số nguyên lớn nhất bé hơn kết quả của phép chia thông thường. Ví dụ: Với phép chia thông thường, chúng ta có 3 / 2 = 1,5. Tuy nhiên với floor division, 3 // 2 = 1, bởi vì 1 là số nguyên lớn nhất bé hơn 1,5. Lấy một ví dụ khác: Với phép chia thông thường, -57 / 26 = -2,19. Tuy nhiên với floor division, -57 // 26 = -3, bởi vì -3 là số nguyên lớn nhất bé hơn -2,19.       

Tổng kết lại, nếu chúng ta ở vị trí i trong mảng arr và chúng ta dịch k ký tự, công thức tính vị trí sau khi dịch chuyển là i + k – 26 * ((i + k) // 26).                       

b. Code:

Bước 1: Viết các câu lệnh khai báo cần thiết   

Chúng ta sử dụng câu lệnh input() để hỏi người dùng khi nào muốn dừng trò chơi và vòng lặp while để tiếp tục trò chơi tương tự như trò chơi Nhà thám hiểm và cánh cửa bí mật ở bài 2. Chúng ta cũng tạo mảng arr để lưu bảng chữ cái:

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
tiep = 'y'
while tiep == 'y':
    tiep = input('Nhập y để tiếp tục hoặc n để thoát: ')

Trong vòng lặp while, chúng ta sẽ sử dụng câu lệnh input()để yêu cầu người dùng nhập câu cần mã hóa và số ký tự muốn dịch chuyển. Chúng ta cần tạo biến để lưu chuỗi sau khi được mã hoá:

plaintext = str(input("Bạn hãy nhập câu muốn mã hoá: ")).upper()
jump = int(input("Bạn muốn dịch sang mấy ký tự? "))
t = '' 

Để đơn giản, chúng ta sẽ sử dụng câu lệnh .upper() để in hoa tất cả các ký tự trong câu người dùng nhập vào. Code hoàn chỉnh sẽ là:

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
tiep = 'y'
while tiep == 'y':
    plaintext = str(input("Bạn hãy nhập câu muốn mã hoá: ")).upper()
    jump = int(input("Bạn muốn dịch sang mấy ký tự? "))
    t = ''
    tiep = input('Nhập y để tiếp tục hoặc n để thoát: ') 

 Bước 2: Xác định vị trí của ký tự trong mảng arr: 

Một câu được biểu diễn bằng kiểu dữ liệu chuỗi (string) trong Python. Chúng ta đã được học ở bài 3, một chuỗi là một mảng mà phần tử là các ký tự trong chuỗi. Ví dụ: chuỗi “STEAM” là một mảng gồm 5 phần tử  “S”, “T”, “E”, “A”, “M”. Như vậy để lấy các ký tự từ chuỗi, chúng ta có thể sử dụng vòng lặp for:

for character in plaintext:
    print(character)

Chúng ta có thể sử dụng câu lệnh print để debug. Trong vòng lặp for, để lấy ra vị trí của ký tự ở trong mảng arr, chúng ta sử dụng thêm vòng lặp while với biến i để lưu vị trí của ký tự trong mảng. Biến i bắt đầu từ 0 và sẽ được cập nhật trong vòng lặp để đi đến vị trí mới trong mảng arr. Chúng ta sử dụng câu lệnh if để kiểm tra xem phần tử ở vị trí i trong mảng arr có giống với ký tự trong chuỗi không. Nếu giống, chúng ta sẽ break. Chúng ta vẫn có thể sử dụng câu lệnh print để debug:

i = 0
while i < len(arr):
    if character == arr[i]:
        print('Giống')
        break          
    i = i + 1

Code hoàn chỉnh sẽ là:

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
tiep = 'y'
while tiep == 'y':
    plaintext = str(input("Bạn hãy nhập câu muốn mã hoá: ")).upper()
    jump = int(input("Bạn muốn dịch sang mấy ký tự? "))
    t = ''

    for character in plaintext:
        i = 0
        while i < len(arr):
            if character == arr[i]:
                print('Giống')
                break          
            i = i + 1

    tiep = input('Nhập y để tiếp tục hoặc n để thoát: ')

 Bước 3: Mã hoá ký tự:

Sau khi xác định được vị trí i của một ký tự trong chuỗi, chúng ta sẽ sử dụng công thức tìm vị trí mới ở trong phần thuật toán để xác định ký tự sau khi mã hoá:

character_code = arr[i + jump - len(arr) * ((i + jump) // len(arr))]

Ngoài ra, chúng ta sẽ thêm một trường hợp. Nếu ký tự là khoảng trắng thì ký tự sau khi mã hoá cũng sẽ là khoảng trắng:

 elif character == ' ':
    character_code = ' '

Code hoàn chỉnh sẽ là:

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
tiep = 'y'
while tiep == 'y':
    plaintext = str(input("Bạn hãy nhập câu muốn mã hoá: ")).upper()
    jump = int(input("Bạn muốn dịch sang mấy ký tự? "))
    t = ''

    for character in plaintext:
        i = 0
        while i < len(arr):
            if character == arr[i]:
               character_code = arr[i + jump - len(arr) * ((i + jump) // len(arr))]
               break
            elif character == ' ':
               character_code = ' '          
            i = i + 1

    tiep = input('Nhập y để tiếp tục hoặc n để thoát: ')

 Bước 4: Kết nối các ký tự sau khi mã hoá thành chuỗi:

Các ký tự trong chuỗi có thể được xem như một chuỗi con. Để kết nối hai chuỗi thành một chuỗi, chúng ta sử dụng +:

t = t + character_code

Ở bước 1, chúng ta đã sử dụng biến t để lưu câu sau khi được mã hoá. Cuối cùng, chúng ta sẽ in ra câu sau khi được mã hoá:

print('Câu sau khi được mã hoá là: %s' % t)

Chúng ta sử dụng %s để thêm vào một biến có kiểu dữ liệu chuỗi vào câu lệnh print. Ngoài ra chúng ta sẽ thêm %  cùng với tên biến.

5.  Tada!!! 

Như vậy, các bạn học sinh đã hoàn thành xong game giúp mã hoá và giải mã Caesar nhanh chóng rồi đấy. Tuy quá trình làm game không ít khó khăn nhưng chắc chắn thành quả của các bạn rất hữu ích để áp dụng ngay trong cuộc sống. Chúng ta hoàn toàn có thể sử dụng chương trình này để mã hoá ngay một câu đố và đem cho mọi người đau đầu giải mã.  

Chương trình Python hoàn chỉnh của game sẽ là:

# -*- coding: utf-8 -*-

arr = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
tiep = 'y'
while tiep == 'y':
    plaintext = str(input("Bạn hãy nhập câu muốn mã hoá: ")).upper()
    jump = int(input("Bạn muốn dịch sang mấy ký tự? "))
    t = ''

    for character in plaintext:
        i = 0
        while i < len(arr):
            if character == arr[i]:
               character_code = arr[i + jump - len(arr) * ((i + jump) // len(arr))]
               break
             elif character == ' ':
                character_code = ' '          
            i = i + 1

        t = t + character_code

    print('Câu sau khi được mã hoá là: %s' % t)

    tiep = input('Nhập y để tiếp tục hoặc n để thoát: ')

Có rất nhiều cách chúng ta có thể cải tiến game này. Các bạn hãy nghĩ một cách nào đó chúng ta có thể loại bỏ vòng lặp while sử dụng để đi qua các phần tử trong mảng arr. Ngoài ra, các bạn có thể cải tiến game bằng cách mã hoá cả chữ hoa và chữ thường, chứ không cần phải chuyển hết sang chữ hoa. 

Không chỉ vậy, thầy Harry và thầy Đức có một gợi ý hữu ích cho các bạn học sinh. Nếu chúng ta còn nhớ trong bài Vui học cùng thầy cô 1, thầy Đức đã giới thiệu cho chúng ta bảng mã ASCII. Trong bảng mã ASCII cũng có hai bảng chữ cái in hoa và in thường đấy. Chúng ta có thể chuyển một ký tự sang mã ASCII bằng câu lệnh ord() và chuyển từ mã ASCII về lại ký tự bằng câu lệnh chr(). Sau đó, chúng ta có thể chuyển từ số trong bảng mã ASCII thành vị trí của một phần tử trong mảng arr. Các bạn hãy cùng thử nhé!

Một gợi ý nữa để cải tiến game đó là chúng ta có thể sử dụng phép toán % trong Python để tính số lần chúng ta đi hết mảng arr. Phép toán này giúp chúng ta tìm số dư trong một phép chia. Ví dụ: 3 % 2 = 1.

Nhờ áp dụng ngay kiến thức của bài 3 khoá CS 101, bạn Đức Hoàng đã tạo ra được game “Mã hóa Caesar” hết sức thú vị và thực tế. Các bạn học sinh cũng hãy thử bắt tay vào sáng tạo một game cho riêng mình nhé! Sau khi hoàn thành game, các bạn có thể chia sẻ game của mình trên STEAMese Profile. 

— — —

STEAM for Vietnam Foundation là tổ chức phi lợi nhuận 501(c)(3) được thành lập tại Hoa Kỳ với sứ mệnh thúc đẩy các hoạt động liên quan tới giáo dục STEAM (Science — Khoa học, Technology — Công nghệ, Engineering — Kỹ thuật, Arts — Nghệ thuật, Mathematics — Toán học) tại Việt nam. STEAM for Vietnam được thành lập và vận hành bởi đội ngũ tình nguyện viên là du học sinh và chuyên gia người Việt trên khắp thế giới.

— — —

📧Email: hello@steamforvietnam.org

🌐Website: www.steamforvietnam.org

🌐Fanpage: STEAM for Vietnam

📺YouTube:  http://bit.ly/S4V_YT

🌐Zalo: Zalo Official       

Chuyên mục
Học kỳ Mùa thu 2021 Khám phá Python Blog

Dự án “Câu chuyện ngẫu nhiên”

  1. Kiến thức lập trình

Một số kiến thức chúng ta đã được học ở bài 3 của khoá CS 101 sẽ được áp dụng để hoàn thành trò chơi này:

  • Mảng trong Python. 
  • Cách lấy phần tử ngẫu nhiên trong mảng bằng thư viện random.
  • Vòng lặp while trong Python.
  • Câu lệnh input() để nhập dữ liệu trong Python.
  • Câu lệnh print() để in thông báo ra màn hình.
  1. Câu chuyện về dự án

Các bạn học sinh hãy thử tưởng tượng mình hóa thân vào vai một vị đạo diễn tài năng đang làm phim. Trong phim có hai nhân vật chính: một nam, một nữ. Ý tưởng về lời thoại và trang phục phù hợp cho hai nhân vật đã có trong kịch bản trên tay đạo diễn. Thế nhưng, có quá nhiều kịch bản hay nên các bạn chưa biết phải lựa ra kịch bản nào làm một bộ phim hoàn chỉnh. Các bạn học sinh đã có những ý tưởng khắc phục vấn đề này hay chưa? STEAM for Vietnam gợi ý thư viện random trong Python có thể giúp chúng ta kết hợp các lời thoại, trang phục khác nhau để tạo nên những câu chuyện đa dạng đấy!

 Chúng ta có thể chơi thử trò chơi ở đây nhé: https://s4v.trinket.io/sites/random 

  1. Bắt tay vào lập trình thôi nào!

Thư viện random:

Trong Python, thư viện random để thực hiện ngẫu nhiên một việc gì đó. Ở trò chơi Nhà thám hiểm và cánh cửa bí mật, chúng ta đã sử dụng một câu lệnh trong thư viện này để tạo số ngẫu nhiên cho nhân sư: random.randint(1,10). 

Ngoài ra, thư viện random còn có một câu lệnh để lấy ngẫu nhiên một phần tử trong mảng: random.choice(). Chúng ta sẽ dùng câu lệnh này để tạo ra game. 

      Code:

a)   Bước 1: Tạo danh sách các nhân vật, lời thoại, trang phục, và diễn biến câu chuyện:

Chúng ta sử dụng mảng để lưu trữ danh sách các nhân vật, lời thoại, trang phục, và diễn biến câu chuyện. Mảng sẽ được khai báo bằng [], các phần tử trong mảng được ngăn cách với nhau bởi dấu phẩy:

women = ["Một nữ hoàng", "Một bà già", "Bà Granny", "Một con chim", "Một nhà quý tộc", "Một bác sĩ", "Một diễn viên", "Trẩu"]

men = ["một sĩ quan", "một bá tước", 'một vị vua', 'một rô bốt sát thủ', 'một nghệ sĩ', 'một ông già', 'một nhà hoá học', 'William']

place = ['dưới biển', 'trên sao Hoả', 'ở siêu thị', 'trong một toà lâu đài', 'trong nhà bạn', 'trên mái nhà', 'phòng thí nghiệm']

women_wear = ['một cái váy', 'một cái túi giấy', 'một bộ đồ lặn', 'một cánh tiên', 'một bao ni lông']
men_wear = ['một bộ vest tím', 'một bộ đồ hoá trang con gấu', "một cái áo sơ mi"]

happens = ['sập nhà', 'cãi lộn', 'đánh nhau', 'một bàn chân lớn nghiền nát họ','núi lửa phun trào', 'động đất', 'Trái đất nổ tung']

women_say = ['Ngươi là ai?', 'Xin chào', 'đưa tiền đây', 'hello']

men_say = ["Ai đó", 'bíp bíp', 'ngươi là đứa nào', 'giết người', 'hello', 'Chả hiểu nói gì']

b)   Bước 2: Tạo câu chuyện ngẫu nhiên:

Bộ phim của chúng ta sẽ bắt đầu khi nhân vật nam gặp nhân vật nữ tại một địa điểm nào đó. Hai người nói chuyện với nhau và sự việc tiếp theo xảy ra.

Tương tự như trò chơi “Nhà thám hiểm và cánh cửa bí mật”, chúng ta sử dụng câu lệnh input() để hỏi người dùng khi nào muốn dừng trò chơi và vòng lặp while để tiếp tục trò chơi. Chúng ta sử dụng câu lệnh print để in ra câu chuyện.

Để lấy ngẫu nhiên một phần tử trong mảng, chúng ta sử dụng câu lệnh: random.choice(). Trong dấu ngoặc sẽ là tên của mảng. Ví dụ, để lấy ngẫu nhiên một nhân vật nữ trong mảng women, chúng ta sử dụng câu lệnh: random.choice(women)

Code hoàn chỉnh sẽ là:

import random

tiep = "y"
while tiep == "y":
    print(random.choice(women),"gặp", random.choice(men),random.choice(place))
    print("Cô ấy mặc", random.choice(women_wear))
    print("Anh ấy mặc", random.choice(men_wear))
    print("Cô ấy nói", random.choice(women_say))
    print("Anh ấy nói", random.choice(men_say))
    print("Điều đó dẫn đến", random.choice(happens))
    print()
    tiep = input("Nhấn y để tiếp tục hoặc n để thoát: ")
    print()

4.  Tada!!!

Như vậy chúng ta đã hoàn thành trò chơi rồi đấy. Thật đơn giản đúng không nào. 

Code hoàn chỉnh sẽ là:

# -*- coding: utf-8 -*-

women = ["Một nữ hoàng", "Một bà già", "Bà Granny", "Một con chim", "Một nhà quý tộc", "Một bác sĩ", "Một diễn viên"]

men = ["một sĩ quan", "một bá tước", 'một vị vua', 'một rô bốt sát thủ', 'một nghệ sĩ', 'một ông già', 'một nhà hoá học']

place = ['dưới biển', 'trên sao Hoả', 'ở siêu thị', 'trong một toà lâu đài', 'trong nhà bạn', 'trên mái nhà']

women_wear = ['một cái váy', 'một cái túi giấy', 'một bộ đồ lặn', 'một cánh tiên', 'một bao ni lông']
men_wear = ['một bộ vest tím', 'một bộ đồ hoá trang con gấu', "một cái áo sơ mi"]

happens = ['sập nhà', 'cãi lộn', 'đánh nhau', 'một bàn chân lớn nghiền nát họ','núi lửa phun trào', 'động đất', 'Trái đất nổ tung']

women_say = ['Ngươi là ai?', 'Xin chào', 'đưa tiền đây', 'hello']

men_say = ["Ai đó", 'bíp bíp', 'ngươi là đứa nào', 'giết người', 'hello', 'Chả hiểu nói gì']

import random

tiep = "y"
while tiep == "y":
    print(random.choice(women),"gặp", random.choice(men),random.choice(place))
    print("Cô ấy mặc", random.choice(women_wear))
    print("Anh ấy mặc", random.choice(men_wear))
    print("Cô ấy nói", random.choice(women_say))
    print("Anh ấy nói", random.choice(men_say))
    print("Điều đó dẫn đến", random.choice(happens))
    print()
    tiep = input("Nhấn y để tiếp tục hoặc n để thoát: ")
    print()

Quá trình hoàn thành dự án “Câu chuyện ngẫu nhiên” thật thú vị đúng không? Các bạn học sinh hãy tự sáng tạo cho mình những cốt truyện phim khác nhau từ nhân vật, trang phục tới nơi chốn, sự việc để hoàn thành một bộ phim của riêng mình nhé! Sau khi hoàn thành game, các bạn có thể chia sẻ game của mình trên STEAMese Profile để khoe cùng mọi người.

— — —

STEAM for Vietnam Foundation là tổ chức phi lợi nhuận 501(c)(3) được thành lập tại Hoa Kỳ với sứ mệnh thúc đẩy các hoạt động liên quan tới giáo dục STEAM (Science — Khoa học, Technology — Công nghệ, Engineering — Kỹ thuật, Arts — Nghệ thuật, Mathematics — Toán học) tại Việt nam. STEAM for Vietnam được thành lập và vận hành bởi đội ngũ tình nguyện viên là du học sinh và chuyên gia người Việt trên khắp thế giới.

— — —

📧Email: hello@steamforvietnam.org

🌐Website: www.steamforvietnam.org

🌐Fanpage: STEAM for Vietnam

📺YouTube:  http://bit.ly/S4V_YT

🌐Zalo: Zalo Official

Chuyên mục
Nhật ký Lập trình Về Chúng tôi

“Hôm nay, bố mẹ cùng học với con nữa nhé!”

“Sáng thứ bảy nào, cả gia đình cũng có mặt đầy đủ và hào hứng nghe giảng các buổi học lập trình cùng thầy cô trong STEAM for Vietnam. Bởi vì cả bố và mẹ đều không biết nhiều về lập trình nên những buổi học lập trình của con cũng là những cơ hội để bố mẹ mở mang kiến thức ở mảng này. Khi đó, chị cảm thấy khoảng cách thế hệ dường như được rút ngắn lại, bố mẹ trở thành những người bạn thân thiết, đồng hành và phát triển cùng con. Cả gia đình chị còn dành thời gian cùng nhau ôn bài và làm game mới mỗi cuối tuần. Điều này vừa giúp con vững kiến thức hơn và vừa tạo cho con không gian để giải trí một cách bổ ích. Nói chung, nhờ STEAM for Vietnam mà nhà chị đã “sưu tầm” được rất nhiều kỷ niệm dễ thương, đồng thời có cơ hội gắn kết tình cảm giữa con với ba mẹ nhiều hơn nữa. 

bé Minh

Nhờ cách giảng bài rất cặn kẽ của các thầy cô trong STEAM for Vietnam, con chị đã có thể thực hành bài tập ngay sau buổi học. Ngoài ra, chị luôn mong muốn con có thể áp dụng những kiến thức đã được học vào đời sống một cách thật sáng tạo bằng khả năng suy luận và tư duy của mình Vì thế, chị đã luôn động viên và hỗ trợ con trong quá trình phát triển game dựa trên các ý tưởng lấy từ đời sống thường ngày. Đó chính là lý do mà game “Miu đi siêu thị” ra đời. Đây là chủ đề thú vị mà chị đã gợi ý cho con khi cả nhà cùng nhau đi mua sắm. Chị rất tự hào khi thấy con hăng say lên nội dung chi tiết cho game và cặm cụi quên giờ giấc để hoàn thành dự án đầy tâm huyết của mình. 

Chị cảm thấy khóa học lập trình này là một trải nghiệm hết sức thú vị của con và cả gia đình. Nhờ có các buổi học lập trình trực tiếp cùng STEAM for Vietnam mỗi thứ bảy mà cả gia đình có thêm một hoạt động sinh hoạt cùng nhau. Một điều chị muốn nhắn nhủ với các phụ huynh còn đang e ngại chưa dám cho con học lập trình đó là các con đang ở độ tuổi mà khả năng tư duy và tiếp thu rất nhạy bén, vì vậy bố mẹ hãy tự tin cho con được tiếp xúc với lập trình từ sớm nhé!

– Chia sẻ từ chị Dương Minh Phương – phụ huynh bé Minh Sơn (7 tuổi), đang theo học khóa CS 001 – Nhập môn Tư duy máy tính và Lập trình Scratch tại STEAM for Vietnam-

— — —

“Nhật ký Lập trình” là series thuật lại những câu chuyện mà phụ huynh, học sinh, và các thầy cô chia sẻ về chặng đường theo học các khoá lập trình cùng STEAM for Vietnam.

Đọc thêm về series Nhật ký Lập trình tại đây.

— — —

STEAM for Vietnam Foundation là tổ chức phi lợi nhuận 501(c)(3) được thành lập tại Hoa Kỳ với sứ mệnh thúc đẩy các hoạt động liên quan tới giáo dục STEAM (Science — Khoa học, Technology — Công nghệ, Engineering — Kỹ thuật, Arts — Nghệ thuật, Mathematics — Toán học) tại Việt nam. STEAM for Vietnam được thành lập và vận hành bởi đội ngũ tình nguyện viên là du học sinh và chuyên gia người Việt trên khắp thế giới.

— — —

📧Email: hello@steamforvietnam.org

🌐Website: www.steamforvietnam.org

🌐Fanpage: STEAM for Vietnam

📺YouTube:  http://bit.ly/S4V_YT

🌐Zalo: Zalo Official