注釈

こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ!Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。

参加する理由は?

  • エキスパートサポート:コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。

  • 学び&共有:ヒントやチュートリアルを交換してスキルを向上させましょう。

  • 独占的なプレビュー:新製品の発表や先行プレビューに早期アクセスしましょう。

  • 特別割引:最新製品の独占割引をお楽しみください。

  • 祭りのプロモーションとギフト:ギフトや祝日のプロモーションに参加しましょう。

👉 私たちと一緒に探索し、創造する準備はできていますか?[ここ]をクリックして今すぐ参加しましょう!

4.1.17 ゲーム – 数字当て

はじめに

数字当ては、楽しいパーティゲームです。あなたと友人は、数字(0〜99)をRaspberry Piに入力し、それがモールスコードとして表示されるようにします。数字を入力するたびに範囲が狭くなり、誰かが正しく答えるとそのプレイヤーが負けて罰されます。例えば、プレイヤーが見ることができない運の数字が51の場合、プレイヤー①が50を入力すると、数字の範囲のヒントが50〜99に変わります。プレイヤー②が70を入力すると、数字の範囲は50〜70となります。プレイヤー③が51を入力すると、このプレイヤーが不運なものとなります。このプロジェクトでは、数字を入力するためのキーパッドと結果を出力するためのLCDを使用します。

必要な部品

このプロジェクトでは、以下のコンポーネントが必要です。

../_images/list_GAME_Guess_Number.png

キット全体を購入することは非常に便利です。リンクは以下のとおりです:

名前

このキットのアイテム

リンク

Raphael Kit

337

Raphael Kit

以下のリンクから別々に購入することもできます。

コンポーネントの紹介

購入リンク

GPIO拡張ボード

BUY

ブレッドボード

BUY

ジャンパーワイヤー

BUY

抵抗器

BUY

キーパッド

-

I2C LCD1602

BUY

回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SPIMOSI

Pin 19

12

10

GPIO22

Pin 15

3

22

GPIO27

Pin 13

2

27

GPIO17

Pin 11

0

17

SDA1

Pin 3

SDA1(8)

SDA1(2)

SCL1

Pin 5

SCL1(9)

SDA1(3)

../_images/Schematic_three_one12.png

実験の手順

ステップ1: 回路を組み立てます。

../_images/image273.png

ステップ2: I2Cを設定します( I2C設定 を参照してください。)

ステップ3: ディレクトリを変更します。

cd ~/raphael-kit/python/

ステップ4: 実行します。

sudo python3 4.1.17_GAME_GuessNumber.py

プログラムが実行された後、LCDに初期ページが表示されます:

Welcome!
Press A to go!

‘A’を押すと、ゲームが開始され、ゲームページがLCDに表示されます。

Enter number:
0 ‹point‹ 99

ゲームが始まると、ランダムな数値「 point 」が生成されますが、LCDには表示されません。あなたのタスクはそれを推測することです。入力した数字は、最終計算が完了するまでの第一行の末尾に表示されます。(「D」を押して比較を開始し、入力数が 10 より大きい場合、自動的な比較が開始されます。)

「point」の数字範囲は2行目に表示されます。そして、あなたはその範囲内の数字を入力する必要があります。数字を入力すると、範囲が狭まります。もしあなたが運よく、または不運にもラッキーナンバーを手に入れた場合、"当たり!"と表示されます。

注釈

  • FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' というエラーが出た場合は、 I2C設定 を参照してI2Cを有効にする必要があります。

  • ModuleNotFoundError: No module named 'smbus2' エラーが発生した場合は、 sudo pip3 install smbus2 を実行してください。

  • エラー OSError: [Errno 121] Remote I/O error が表示された場合、モジュールが間違って配線されているか、モジュールが壊れている可能性があります。

  • コードと配線が正しく、LCDがまだ内容を表示しない場合、背面の可変抵抗を回してコントラストを上げることができます。

コード

注釈

下のコードを 変更/リセット/コピー/実行/停止 することができます。しかし、それを行う前に、ソースコードのパス(例: raphael-kit/python )に移動する必要があります。コードを変更した後、それを直接実行して効果を確認することができます。

#!/usr/bin/env python3

import RPi.GPIO as GPIO
import time
import LCD1602
import random

##################### HERE IS THE KEYPAD LIBRARY TRANSPLANTED FROM Arduino ############
#class Key:Define some of the properties of Key
class Keypad():

   def __init__(self, rowsPins, colsPins, keys):
      self.rowsPins = rowsPins
      self.colsPins = colsPins
      self.keys = keys
      GPIO.setwarnings(False)
      GPIO.setmode(GPIO.BCM)
      GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
      GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

   def read(self):
      pressed_keys = []
      for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
               index = i * len(self.colsPins) + j
               if (GPIO.input(col) == 1):
                  pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
      return pressed_keys

################ EXAMPLE CODE START HERE ################

count = 0
pointValue = 0
upper=99
lower=0

def setup():
   global keypad, last_key_pressed,keys
   rowsPins = [18,23,24,25]
   colsPins = [10,22,27,17]
   keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
   keypad = Keypad(rowsPins, colsPins, keys)
   last_key_pressed = []
   LCD1602.init(0x27, 1)    # init(slave address, background light)
   LCD1602.clear()
   LCD1602.write(0, 0, 'Welcome!')
   LCD1602.write(0, 1, 'Press A to Start!')

def init_new_value():
   global pointValue,upper,count,lower
   pointValue = random.randint(0,99)
   upper = 99
   lower = 0
   count = 0
   print('point is %d' %(pointValue))

def detect_point():
   global count,upper,lower
   if count > pointValue:
      if count < upper:
            upper = count
   elif count < pointValue:
      if count > lower:
            lower = count
   elif count == pointValue:
      count = 0
      return 1
   count = 0
   return 0

def lcd_show_input(result):
   LCD1602.clear()
   if result == 1:
      LCD1602.write(0,1,'You have got it!')
      time.sleep(5)
      init_new_value()
      lcd_show_input(0)
      return
   LCD1602.write(0,0,'Enter number:')
   LCD1602.write(13,0,str(count))
   LCD1602.write(0,1,str(lower))
   LCD1602.write(3,1,' < Point < ')
   LCD1602.write(13,1,str(upper))

def loop():
   global keypad, last_key_pressed,count
   while(True):
      result = 0
      pressed_keys = keypad.read()
      if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            if pressed_keys == ["A"]:
               init_new_value()
               lcd_show_input(0)
            elif pressed_keys == ["D"]:
               result = detect_point()
               lcd_show_input(result)
            elif pressed_keys[0] in keys:
               if pressed_keys[0] in list(["A","B","C","D","#","*"]):
                  continue
               count = count * 10
               count += int(pressed_keys[0])
               if count >= 10:
                  result = detect_point()
               lcd_show_input(result)
            print(pressed_keys)
      last_key_pressed = pressed_keys
      time.sleep(0.1)

# Define a destroy function for clean up everything after the script finished
def destroy():
   # Release resource
   GPIO.cleanup()
   LCD1602.clear()

if __name__ == '__main__':     # Program start from here
   try:
      setup()
      while True:
            loop()
   except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the program destroy() will be executed.
      destroy()

コードの説明

コードの冒頭部分には、 keypadI2C LCD1602 の機能関数があります。詳細については、 1.1.7 I2C LCD1602 および 2.1.8 キーパッド で学ぶことができます。

以下に、私たちが知る必要がある内容を示します:

def init_new_value():
    global pointValue,upper,count,lower
    pointValue = random.randint(0,99)
    upper = 99
    lower = 0
    count = 0
    print('point is %d' %(pointValue))

この関数はランダムな数値「 point 」を生成し、pointの範囲のヒントをリセットします。

def detect_point():
    global count,upper,lower
    if count > pointValue:
        if count < upper:
            upper = count
    elif count < pointValue:
        if count > lower:
            lower = count
    elif count == pointValue:
        count = 0
        return 1
    count = 0
    return 0

detect_point() は、入力された数値 (count) と生成された “point” を比較します。比較の結果、2つの値が異なる場合、 countupperlower に値を割り当て、‘0’を返します。逆に、2つの値が同じである場合、‘1’を返します。

def lcd_show_input(result):
    LCD1602.clear()
    if result == 1:
        LCD1602.write(0,1,'You have got it!')
        time.sleep(5)
        init_new_value()
        lcd_show_input(0)
        return
    LCD1602.write(0,0,'Enter number:')
    LCD1602.write(13,0,str(count))
    LCD1602.write(0,1,str(lower))
    LCD1602.write(3,1,' < Point < ')
    LCD1602.write(13,1,str(upper))

この関数はゲームページの表示のためのものです。

str(count): write() はデータタイプとして string のみをサポートしているため、 numberstring に変換するために str() が必要です。

def loop():
    global keypad, last_key_pressed,count
    while(True):
        result = 0
        pressed_keys = keypad.read()
        if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            if pressed_keys == ["A"]:
                init_new_value()
                lcd_show_input(0)
            elif pressed_keys == ["D"]:
                result = detect_point()
                lcd_show_input(result)
            elif pressed_keys[0] in keys:
                if pressed_keys[0] in list(["A","B","C","D","#","*"]):
                    continue
                count = count * 10
                count += int(pressed_keys[0])
                if count >= 10:
                    result = detect_point()
                lcd_show_input(result)
            print(pressed_keys)
        last_key_pressed = pressed_keys
        time.sleep(0.1)

main() はプログラムの全体のプロセスを含んでおり、以下のように表示されます:

  1. I2C LCD1602Keypad を初期化します。

  2. ボタンが押されたかどうかを判定し、ボタンの読み取りを取得します。

  3. ボタン‘A’が押された場合、ランダムな数字 0-99 が表示され、ゲームが開始されます。

  4. ボタン‘D’が押されたと検出された場合、プログラムは結果の判定に入ります。

  5. ボタン 0-9 が押された場合、 count の値が変更されます。 count10 より大きい場合、判定が開始されます。

  6. ゲームの変更とその値は LCD1602 に表示されます。

現象の画像

../_images/image274.jpeg