F#ゲームプログラミング入門

F#を使ってゲームプログラミングしてみましょう!

目次

ゲームプログラミング入門

プログラミング言語F#を使ってゲームプログラミングの方法を解説したいと思います。

基礎編

じゃんけんゲームを題材に、ゲームプログラミングの基礎を解説したいと思います。

入出力

ゲームプログラミングの基本に入出力があります。

あなたが普段遊んでいるゲームでは、コントローラーで「入力」を行い、ディスプレイにその結果が「出力」されていることでしょう

じゃんけんゲームではキーボードで自分の出す手を入力し、コンソールにその結果を表示します

■サンプルコード

#light
open System

printfn "☆じゃんけんゲーム☆\n"

// 自分と相手の手を決める
printfn "何を出しますか? グー(0) チョキ(1) パー(2)"
let myType = Int32.Parse( Console.ReadLine() ) 


let random = Random()
let cpuType = random.Next( 0, 3 )

// 自分と相手の出した手を表示する
let jankenTable = [("グー",0); "チョキ",1; ("パー",2) ]

for a in jankenTable do
    if myType = snd a then
        printfn "あなたは%sを出しました\n" (fst a) 

for a in jankenTable do
    if cpuType = snd a then
        printfn "あいては%sを出しました\n" (fst a)

// 勝敗の評価
if cpuType = myType then
    printfn "あいこです"
elif cpuType = 0 && myType = 1 
     || cpuType = 1 && myType = 2
     || cpuType = 2 && myType = 0 then
    printfn "あなたの負けです!"
else               
    printfn "あなたの勝ちです!"

■実行結果

☆じゃんけんゲーム☆

何を出しますか? グー(0) チョキ(1) パー(2)
1
あなたはチョキを出しました

あいてはパーを出しました

あなたの勝ちです!

エラーチェック

先ほどのサンプルでは、0,1,2のいずれかがユーザーから入力されることを期待しています。

では、それ以外が入力されてしまったらどうなるでしょうか?意図しない動作になってしまうことは想像に易いでしょう。

今回は期待された値以外でプログラムが動作してしまわないように、入力エラーチェックを行います。エラーを検出するために、F#の例外を使用します。

今回のサンプルコードはエラーチェックに加え、プログラムが多少長くなってきたので関数分けも行いました。

■サンプルコード

#light
open System

// ゲーム開始を表示
let DispGameStart() =
    printfn "☆じゃんけんゲーム☆\n"
    printfn "何を出しますか? グー(0) チョキ(1) パー(2)"

// 自分の手を決める
let InputMyTurn() =
    let myType = 
        try
            let num = Int32.Parse( Console.ReadLine() )
            num
        with
            | _ -> printfn("グー(0) チョキ(1) パー(2)のいずれかを入力してください"); 
                   -1    

    // 入力値が不正だった場合、アプリケーションを終了する
    if myType = -1 then Environment.Exit(0)
    myType

// 相手の手を決める
let InputCpuTurn() =
    let random = Random()
    let cpuType = random.Next( 0, 3 )
    cpuType

// 結果を表示する
let DispResult myType cpuType =
    // 自分と相手の出した手を表示する
    let jankenTable = [("グー",0); "チョキ",1; ("パー",2) ]

    for a in jankenTable do
        if myType = snd a then
            printfn "あなたは%sを出しました\n" (fst a) 

    for a in jankenTable do
        if cpuType = snd a then
            printfn "あいては%sを出しました\n" (fst a)

    // 勝敗の評価
    if cpuType = myType then
        printfn "あいこです"
    elif cpuType = 0 && myType = 1 
         || cpuType = 1 && myType = 2
         || cpuType = 2 && myType = 0 then
        printfn "あなたの負けです!"
    else               
        printfn "あなたの勝ちです!"

// メイン関数
let Main() =
    DispGameStart()

    let myType  = InputMyTurn()
    let cpuType = InputCpuTurn()

    DispResult myType cpuType

// ジャンケンゲーム実行
Main()
 

プログラムが完成したので、わざとでたらめな入力を行ってみます。

■実行結果

☆じゃんけんゲーム☆

何を出しますか? グー(0) チョキ(1) パー(2)
jfowqjfoqwhfoqhf
グー(0) チョキ(1) パー(2)のいずれかを入力してください

0,1,2のいずれかの入力を促すメッセージが表示されました。 エラーチェックが正常に動作していることがわかります

ゲームを繰り返す

さきほどまでのサンプルだと、1回ゲームを終えるとプログラムが終了してしまいます。

何度もプレイしたいなと思っていた場合、いちいちプログラムを起動するのはとてもめんどうです

今回は再帰関数を使って、ゲームを繰り返しプレイできるようにしました。

今回のサンプルコードはゲーム終了時にゲームを続けるかユーザーに問いかけ、続ける場合は続行、続けない場合はプログラム終了するようにしてあります。 また、また同じく再帰関数使って入力エラーがあった場合もう一度入力を促すようにしてあります。

■サンプルコード

#light
open System

// ゲーム開始を表示
let DispGameStart() =
    printfn "☆じゃんけんゲーム☆\n"
    printfn "何を出しますか? グー(0) チョキ(1) パー(2)"

// 自分の手を決める
let rec InputMyTurn() =
    let myType = 
        try
            let num = Int32.Parse( Console.ReadLine() )
            num
        with
            | _ -> printfn("グー(0) チョキ(1) パー(2)のいずれかを入力してください"); 
                   InputMyTurn()        
    myType

// 相手の手を決める
let InputCpuTurn() =
    let random = Random()
    let cpuType = random.Next( 0, 3 )
    cpuType

// 結果を表示する
let DispResult myType cpuType =
    // 自分と相手の出した手を表示する
    let jankenTable = [("グー",0); "チョキ",1; ("パー",2) ]

    for a in jankenTable do
        if myType = snd a then
            printfn "あなたは%sを出しました\n" (fst a) 

    for a in jankenTable do
        if cpuType = snd a then
            printfn "あいては%sを出しました\n" (fst a)

    // 勝敗の評価
    if cpuType = myType then
        printfn "あいこです"
    elif cpuType = 0 && myType = 1 
         || cpuType = 1 && myType = 2
         || cpuType = 2 && myType = 0 then
        printfn "あなたの負けです!"
    else               
        printfn "あなたの勝ちです!"

// ゲームを引き続きプレイするか
let rec InputContinue() =
    printfn "ゲームを続けますか はい(y), いいえ(n)"
    let yesNo = Console.ReadLine()
    match yesNo with
      "y" -> true
    | "n" -> false
    | _   -> printfn("y か n 以外は入力できません。もう一度入力しなおしてください")
             InputContinue() 

// ジャンケンゲームを実行する
let rec JankenGame() =
    DispGameStart()

    let myType  = InputMyTurn()
    let cpuType = InputCpuTurn()

    DispResult myType cpuType

    let isContinue = InputContinue()
    if isContinue = true 
        then JankenGame()

// メイン関数
let Main() =
    JankenGame()

// ジャンケンゲーム実行
Main()

■実行結果

☆じゃんけんゲーム☆

何を出しますか? グー(0) チョキ(1) パー(2)
adkjl
グー(0) チョキ(1) パー(2)のいずれかを入力してください

あなたはチョキを出しました

あいてはチョキを出しました

あいこです
ゲームを続けますか はい(y), いいえ(n)

 か n 以外は入力できません。もう一度入力しなおしてください
ゲームを続けますか はい(y), いいえ(n)

☆じゃんけんゲーム☆

何を出しますか? グー(0) チョキ(1) パー(2)

不正な入力に対しては再入力を促し、ゲームも繰り返し実行できるようになりました

ゲーム結果を記録する

工事中

inserted by FC2 system