クジラの練習帳014(じゃんけんゲーム)
クジラの練習帳014
じゃんけんの画像が無かったことをここで謝罪させていただきます。
技術ブログの更新初めは軽めに、
何も見ずに「じゃんけんができるゲーム」を作り、後で調べて出てきたじゃんけんゲームと比較してみたいと思います。
作成したゲーム
ユーザー(user)の対戦相手をボット(bot)。
botは配列からランダムに手を取得する簡単な仕組みになっていて、userが入力した手とif文で比較し結果を出力している。
出力結果
個人的不満点
- コードが長くなっている(確実)
- グー、チョキ、パーを数字で管理したいが分かりにくのではないか?
- 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
こちらは他の方のブログで書かれていた勝ち負け判断の中で一番短く理想だと感じました。
出力結果
全体
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
何も見ずに作った物と検索した後で作った物との差を縮められるように今年も頑張ります。ありがとうございました。
参考にした記事
前回:クジラの練習帳013(カレンダー作成) - whale_86’s blog
クジラの練習帳013(カレンダー作成)
練習帳013
前回に引き続きネットで拾った問題を解きます
問題
カレンダー作成。
完成出力結果
解答
解説
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
今回は、ネット上で拾った問題を実際に解きながら考えていきます。
問題
「ある駄菓子屋で飲み物を買うと、空き瓶3本で新しい飲み物を1本プレゼントしてくれる。最初に100本購入した場合、トータルで何本飲めるか」
購入した本数 | 飲める本数 |
---|---|
0 | 0 |
1 | 1 |
3 | 4 |
11 | 16 |
100 |
(プログラムで算出する) |
解答
昨日あげた解答は間違いだったため、修正させていただきます。
問題は、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の場合、
問題元↓
前回 クジラの練習帳011 - whale_86’s blog
次回 クジラの練習帳013 - whale_86’s blog
オリジナルアプリに警告文が出た
validatesで警告文
エラー内容
チームメンバーを選択するのに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.
と出力されました。
翻訳してみると、
非推奨の警告:一意性バリデーターは、Rails6.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を追加しました。もし、今後分かったら書きたいと思います。
参考にさせていただいたページ
クジラの練習帳011(二重ハッシュ)
練習帳011(二重ハッシュ)
問題
配列の内部に、複数の有名人の情報をハッシュとして持つ変数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
練習帳010(ハッシュの基礎を復習)
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(処理に名前をつけて作る)
以下のプログラムを実行するとエラーが発生します。
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 メソッド名(受け取った値を入れる変数名)