クジラの練習帳014(じゃんけんゲーム)

クジラの練習帳014

f:id:whale_86:20210107170034j:plain

じゃんけんの画像が無かったことをここで謝罪させていただきます。

 

技術ブログの更新初めは軽めに、

何も見ずに「じゃんけんができるゲーム」を作り、後で調べて出てきたじゃんけんゲームと比較してみたいと思います。

 

作成したゲーム

f:id:whale_86:20210107172410p:plain

ユーザー(user)の対戦相手をボット(bot)。

botは配列からランダムに手を取得する簡単な仕組みになっていて、userが入力した手とif文で比較し結果を出力している。

出力結果

f:id:whale_86:20210107172455p:plain

個人的不満点

  • コードが長くなっている(確実)
  • グー、チョキ、パーを数字で管理したいが分かりにくのではないか?
  • randメソッドを使いたい
  • 勝ち負けの判断をもっと簡単に出来ないか?

 

検索して書き直し(めっちゃ良くなった)

userに何を出すか入力させる場面

puts "[0]グー\n[1]チョキ\n[2]パー\nの中から選択し数字で入力してください"
user = gets.to_i

これで不満点の2つ目3つ目がクリアできるようになった!

 

botの手を決める

bot = rand(3)

 randメソッドで乱数生成をする。

 

userとbotが何を出したかを表示させる

janken = ["グー", "チョキ", "パー"]
puts "botは#{janken[bot]}"
puts "あなたは#{janken[user]}"

これで数字からグーチョキパーの表示をすることができた。

 

勝ち負け判断

if bot - user == -2 || bot - user == 1
puts "勝ち"
elsif bot == user
puts "あいこ"
else
puts "負け"
end

 こちらは他の方のブログで書かれていた勝ち負け判断の中で一番短く理想だと感じました。

f:id:whale_86:20210107190404j:plain

 

出力結果

f:id:whale_86:20210107190605p:plain

全体

puts "ジャンケンゲーム\n[0]グー\n[1]チョキ\n[2]パー\nの中から選択し数字で入力してください"
user = gets.to_i

bot = rand(3)

janken = ["グー", "チョキ", "パー"]
puts "\nbotは#{janken[bot]}"
puts "あなたは#{janken[user]}\n結果は..."

if bot - user == -2 || bot - user == 1
puts "勝ち"
elsif bot == user
puts "あいこ"
else
puts "負け"
end

何も見ずに作った物と検索した後で作った物との差を縮められるように今年も頑張ります。ありがとうございました。

 

参考にした記事

Rubyでじゃんけんプログラムを作成 - Qiita

Rubyで「じゃんけんゲーム」を試作 - Qiita

 

前回:クジラの練習帳013(カレンダー作成) - whale_86’s blog

 

クジラの練習帳013(カレンダー作成)

練習帳013

f:id:whale_86:20201125190129j:plain

前回に引き続きネットで拾った問題を解きます

問題

カレンダー作成。

 

完成出力結果

f:id:whale_86:20201201202437p:plain

 

解答

f:id:whale_86:20201201225046p:plain

解説

1~5行目は簡単に説明します。

 

require 'date'

head = Date.today.strftime("%B %Y")
year = Date.today.year
mon = Date.today.mon

dateクラスの読み込み(1行目)

今日の西暦、月名、年月を整数で取得(3~5行目)

 

 

 

firstday = Date.new(year,mon,1).wday
lastday = Date.new(year,mon,-1).day

firstdayは今月の1日の曜日を取得します。

lastdayは今月の最終日を取得します。

 

week = %w(日 月 火 水 木 金 土)

week変数に曜日を入れています。0~6を日本語に変換しています。 

 

 

puts head
puts week.join(" ")
print " " * firstday

headは上記にありますが、月名(December)と西暦(2020)を出力。

week.join(" ")は曜日を連続で出力し、(" ")は曜日の間の隙間を表す。

print "   " * firstdayは今月1日の位置合わせを行っています。

 

(1..lastday).each do |date|
print date.to_s.rjust(2) + " "
firstday += 1
if firstday%7==0
print "\n"
end
end

今月1日~最終日までを出力します。

if firstday%7で土曜日までの出力したら改行するように

 

if firstday%7!=0
print "\n"
end

最終日が土曜日出なかった場合、改行されないので記述。

参考

Dateクラス - 日付(Date、DateTime)クラス - Ruby入門

年月日などの日付要素を取得する - 日付(Date、DateTime)クラス - Ruby入門

class Date (Ruby 2.7.0 リファレンスマニュアル)

Time#strftime (Ruby 2.7.0 リファレンスマニュアル)

Rubyのjoinメソッドの使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン

 

久しぶりのカレンダー作成、Dateクラスの扱いでした。細かくて覚えるのは難しい(・・;)

 

前回 クジラの練習帳012 - whale_86’s blog

次回 クジラの練習帳014(じゃんけんゲーム) - whale_86’s blog

 

クジラの練習帳012(ボーナスドリンク問題)

練習帳012

f:id:whale_86:20201124020122j:plain

今回は、ネット上で拾った問題を実際に解きながら考えていきます。

問題

「ある駄菓子屋で飲み物を買うと、空き瓶3本で新しい飲み物を1本プレゼントしてくれる。最初に100本購入した場合、トータルで何本飲めるか」

 

購入した本数 飲める本数
0 0
1 1
3 4
11 16
100

(プログラムで算出する)

 解答

昨日あげた解答は間違いだったため、修正させていただきます。

f:id:whale_86:20201125230310p:plain

問題は、100本買ったときに33本のボーナスが貰え、この33本からまた11本ボーナスが貰え、更に..ってやっていくと飲み終わるときに飲んだ飲み物は何本かを求める必要があったようです💦

解説

まず、bonus_drinkメソッドで[買った本数(100)] と [count_bottle(貰える本数)]を足していきます。 全てのボーナスは下記で表す青字の値を合計し、49となり100 + 49で149となります。

今回のウエイトはcount_bottleメソッド(ボーナスで貰える本数)です。

 

count_bottleメソッドはボーナスで貰える本数を求めます。

今回は、ループするような形で作り、num(持っている本数)が3以下になるまで行い、全てを合計し

その時に持っている本数は[交換した本数(num / 3)と交換に余った本数(num % 3)]の合計を求める必要があります。

 

elseでcount_bottle(num / 3 + num % 3)の動き

100の場合、

f:id:whale_86:20201125234924p:plain

 

問題元↓

github.com

 

 

前回 クジラの練習帳011 - whale_86’s blog

次回 クジラの練習帳013 - whale_86’s blog

 

オリジナルアプリに警告文が出た

validatesで警告文

f:id:whale_86:20201111193655j:plain

エラー内容

チームメンバーを選択するのにusersテーブルからuser_name(英数字混合のID)を取得する予定。このuser_nameへのバリデーションでエラーが出てしまっている。

 
テーブル設計
## usersテーブル

| Column    | Type   | Options     |
| --------- | ------ | ----------- |
| nickname  | string | null: false |
| user_name | string | null: false |
| email     | string | null: false |
| password  | string | null: false |

### Association
- has_many: team_users
- has_many: team, through: team_users

## teamsテーブル | Column | Type | Options | | --------- | ------ | ----------- | | team_name | string | null: false | ### Association - has_many: team_users - has_many: user, through: team_users
## team_usersテーブル | Column | Type | Options | | ------- | --------- | ------------------------------ | | user | reference | null: false, foreign_key: true | | team | reference | null: false, foreign_key: true | ### Association - belongs_to: user - belongs_to: team

 

警告文

ターミナル:

DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :user_name attribute in User model, pass `case_sensitive: true` option explicitly to the uniqueness validator.

と出力されました。

翻訳してみると、

非推奨の警告:一意性バリデーターは、R​​ails6.1で大文字と小文字を区別する比較を強制しなくなりました。Userモデルの:user_name属性で大文字と小文字を区別する比較を続行するには、明示的に`case_sensitive:true`オプションを一意性バリデーターに指定してください

 

user_nameに一意性を付けたいと設けた部分

app/models/user.rb

validates :user_name, uniqueness: true

とした部分が警告が出ていました。

Rails 6で、MySQLを使っているときに、uniquenessのvalidationを使うと警告が出るようになっているようです。

 

どんな警告文?

昔々、Rails 5.2以前の仕様では、uniquenessバリデータはデフォルトで大文字小文字を区別する比較をしてくれていました。

つまり、'test'TEST'をデフォルトで区別しているということですが、デメリットがありました。

  • DB上のユニーク制約に一致しないため、バリデーションの結果に信用性が低い。
  • DB上のINDEXが効率よく使えないため、DBの負荷が大きくかかる。

 

現在のRails 6.1からの仕様では、uniquenessバリデータはデフォルトで大文字小文字を区別しなくなり、開発者が選択するように促しているようです。これが警告文の内容です。

 

警告文を消す

翻訳にあるように、`case_sensitive:true`オプションを一意性バリデーターに指定すると警告は消える。

validates :user_name, uniqueness: { case_sensitive: true }

しかし、

  • DB上のユニーク制約に一致しないため、バリデーションの結果に信用性が低い。
  • DB上のINDEXが効率よく使えないため、DBの負荷が大きくかかる。

のデメリットが有効になるそうです。このデメリットを解消する場合は、モデルのコードをいじるのではなくDB側のcollectionオプションにutf8_binを追加して「大文字小文字を区別するcollection」に変更する必要があるそうですが、手順が調べても分からなかったため上記のcase_sensetiveを追加しました。もし、今後分かったら書きたいと思います。

 

参考にさせていただいたページ

Rails 6.0で"Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1."という警告が出たときの対処法 - Qiita

 

Rails6 のちょい足しな新機能を試す81(case_sensitive編) - Qiita

クジラの練習帳011(二重ハッシュ)

練習帳011(二重ハッシュ)

f:id:whale_86:20201116192657j:plain

問題

配列の内部に、複数の有名人の情報をハッシュとして持つ変数star_dateがあります。

 

star_data = [
{star: {profile: {name: 'ヒカキン'}}},
{star: {profile: {name: 'ダウンタウン'}}},
{star: {profile: {name: '尾田栄一郎'}}},
]

 star_dateを利用して、全てのユーザーの名前だけが出力されるようにRubyでコーティングしてください。

 

出力結果は以下

ヒカキン 
ダウンタウン
尾田栄一郎

 

以下は解答

 

 

 

 

解答
star_data.each do |u|
puts u[:star][:profile][:name]
end

 ハッシュが複数重なっている場合は、取得したいキーまで連続して指定すると取得できます。

ハッシュ[取得したい値のキー][取得したい値のキー]

 またハッシュに格納されているため、each文で取り出す必要があります。

 

前回 クジラの練習帳010 - whale_86’s blog

次回 クジラの練習帳012 - whale_86’s blog

クジラの練習帳010

練習帳010(ハッシュの基礎を復習)

f:id:whale_86:20201116192657j:plain

puts hash.keys
puts hash.values

 上記のコマンドを実行した際に、

one
two
three
みかん
りんご ぶどう

とターミナルで表示されるような変数hashを作成するためのコードをシンボルを使って記述しましょう。

 

以下は解答になります

余談ですが、秋は果物の季節です。

私の住んでいる長野県はりんご🍎の産地で、長野県民はりんごを食べたら、品種がわかるという噂を聞いたので自分と家族で実験してみたところ8割強で的中しまして、自分でも驚きでしたが家族は当然のような顔でした(・・;)もしかしたら、りんご王者の青森県さんは余裕だったりして...。

 

家族それぞれ推しリンゴがありまして、私はシナノゴールドという品種が一番オススメでーす。

シナノゴールド | りんご大学

 

 

 

解答
hash = { one: "みかん", two: "りんご", three: "ぶどう" }

 シンボルを使用したキーの記述方法は、キーの後にをつけて定義します。

 例↓

hash = { キー: 値}

 

keysメソッドとvaluesメソッド

オブジェクト.keysで、ハッシュに含まれるキーの取得

オブジェクト.valuesで、ハッシュに含まれる値の取得

 

keyとvalueとは

valueとは格納したいデータのことで、keyはそれに対応するデータの名前のことです。

 

衣替えする時に、夏服Tシャツ(value)を[夏用A](key)、水着(value)[夏用B](key)と分けてボックスにしまうのと同じですよ☺️

 

 

前回 クジラの練習帳009 - whale_86’s blog

 

次回 クジラの練習帳011 - whale_86’s blog

 

クジラの練習帳009

練習帳009(処理に名前をつけて作る)

f:id:whale_86:20201111193655j:plain

以下のプログラムを実行するとエラーが発生します。

price = 300

def calculate_price_with_tax
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax

エラーが発生した理由と正しいコードを答えましょう。

 

以下は解答になります

 

 

 

 

解答

エラー理由

メソッド外で定義した変数(price)がメソッド内で使えていない。

正しいコード

price = 300

def calculate_price_with_tax(price)
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax(price)

 使えるようにするには、「引数」を使います。

引数は、メソッドの外から中に値を渡す役割を担います。

使い方は、2ステップ

メソッドの呼出、メソッド名(渡したい値)

メソッドの定義、def メソッド名(受け取った値を入れる変数名)

 

前回 クジラの練習帳008 - whale_86’s blog

次回 クジラの練習帳010 - whale_86’s blog