最高スコアを取れる確率
前章でゲーム作りは完成しました。
ここでは番外編としてこのゲームで最高スコアを獲得しようと試みた結果を書いていきます。
将棋ポーカーのリンクはこちら
https://shogipoker.net
ゲームの性質からして最高スコアは30点になります。
獲得駒が角、金、銀、桂、香、歩の状態です。
こうなるにはComが飛の時には歩で負けて、それ以外はComより一つ強い駒で勝てれば達成できます。
この確率がどれくらいか計算してみます。
こちらはこの順番で駒を選択するとします。
歩、香、桂、銀、金、角、飛
するとComはこの順番で選択される必要があります。
飛、歩、香、桂、銀、金、角
この確率を計算すると5040分の1になります。
1/7 * 1/6 * 1/5 * 1/4 * 1/3 * 1/2 = 1/5040
これを自力で達成するのは日が暮れるので、ブラウザ操作を自動で操作できるSeleniumを使いたいと思います。
Seleniumでゲーム操作を自動化
Seleniumは主にテストで使われるもので、所定のブラウザ操作をコードで実現することができます。
様々な言語で使用することができて非常に便利ですし、ブラウザが勝手に動いてくれるのが何となく楽しいです。
ここではRubyとGoで実装した例を紹介します。
環境構築はたくさん情報がありますので省略します。
Rubyの実装例
require 'selenium-webdriver'
url = 'https://shogipoker.net'
driver = Selenium::WebDriver.for :chrome
driver.navigate.to url
# 表示されるまで待機
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {driver.find_element(:class, 'phase').displayed?}
# 操作する要素
phase = driver.find_element(:class, 'phase')
player_row = driver.find_elements(:css, '.player-row td')
com_koma = driver.find_element(:class, 'com-select')
reset_btn = driver.find_element(:class, 'reset-btn')
player_point = driver.find_element(:class, 'player-point')
max_point = 30 # 獲得ポイントの最大値
point = 0 # Playerの獲得ポイント
try_cnt = 0 # 試行回数
comkoma_expected = ['飛', '歩', '香', '桂', '銀', '金', '角'] # Comに選択して欲しい駒順
# 最高ポイントを獲得するまで繰り返す
while point < max_point
try_cnt += 1
# リセットをクリック
reset_btn.click
0.upto 6 do |n|
# Playerは左から順に選択(歩、香、桂、銀、金、 角、飛)
player_row[n].click
# ○手目をクリック
phase.click
# Comが期待する駒でなければ終了
if comkoma_expected[n] != com_koma.text.strip
break
end
end
# ポイントを格納
point = player_point.text.to_i
# 200回ごとに実行回数を出力
puts try_cnt if try_cnt % 200 == 0
end
# スクリーンショットを保存
driver.save_screenshot('./max.png')
puts try_cnt.to_s + '回目で成功'
sleep 5
driver.quit
Goの実装例
package main
import (
"fmt"
"os"
"time"
"strconv"
"github.com/sclevine/agouti"
)
func main() {
driver := agouti.ChromeDriver()
defer driver.Stop()
if err := driver.Start(); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
page, err := driver.NewPage()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
url := "https://shogipoker.net"
page.Navigate(url)
time.Sleep(time.Second * 1)
// 操作する要素
phase := page.FindByClass("phase")
player_row := page.FindByClass("player-row").All("td")
com_koma := page.FindByClass("com-select")
reset_btn := page.FindByClass("reset-btn")
player_point := page.FindByClass("player-point")
max_point := 30 // 獲得ポイントの最大値
point := 0 // Playerの獲得ポイント
try_cnt := 0 // 試行回数
comkoma_expected := [7]string{"飛", "歩", "香", "桂", "銀", "金", "角"} // Comに選択して欲しい駒順
// 最高ポイントを獲得するまで繰り返す
for point < max_point {
try_cnt++
// リセットをクリック
reset_btn.Click()
for n := 0; n < 7; n++ {
// Playerは左から順に選択(歩、香、桂、銀、金、角、飛)
player_row.At(n).Click()
// ○手目をクリック
phase.Click()
// Comが期待する駒でなければ終了
com_koma_text, _ := com_koma.Text()
if comkoma_expected[n] != com_koma_text {
break
}
}
// ポイントを格納
point_str, _ := player_point.Text()
point_int, _ := strconv.Atoi(point_str)
point = point_int
if try_cnt % 200 == 0 {
fmt.Println(try_cnt, "回経過")
}
}
fmt.Println(try_cnt, "回目で成功")
page.Screenshot("max.png")
time.Sleep(time.Second * 5)
}
実行動画はこちらです。