FreeBASIC マニュアルのトップに戻る

FreeBASIC TutMngAHiScrTbl

目次→教本→いっしょに学ぼうSo Biff wants to have a high score table in his game ←オリジナル・サイト

Biffが彼のゲームで高得点表が欲しくて 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

序論

複数の場合に対して、外部ファイルから高得点表を読み込んで、そこに新しい高得点を入力して、そして、改訂した高得点表を保存する、一連の処理について、私はプログラミング初心者から尋ねられました。

Using the same set of routines for high scores since the days of Ball Blazing Fantasy, I decided to write a tutorial on them and implement some lacking flexibility (plus few fixes) there, something that was long needed to be done but wasn't due the fact the routines did their job perfectly.
私は、Ball Blazing ファンタジーの、日数の経過に従った高得点のための処理と同じものを使って、このチュートリアルを書きます。そこで不足していた柔軟性 (および、少しの改修) を実装するつもりです。改修は、長く望まれていましたが、ルーチンで完全に仕事をしたことはありませんでした。

チュートリアルでは、また、私が書いたものではないてすが、いくつかの (高得点表の管理のために) 役に立つ追加ルーチン、名前の入力や、ファイルの暗号化を、示すつもりです。


実際にやってみましょう!

2つの別のサブルーチンが必要なことは、明白です。一つは、高得点表を登録/読むためのもの、もう一つは、それを書く/変更するためのものです。

私たちは、高得点表を登録して読む部分から始めます。この部分が、より簡単で、論理的に最初だからです。

高得点表を読むためのサブルーチンは、比較的簡単な状態で働きます。
まず、名前と得点登録を含むファイルを開きます。そして、適切な変数にこれらを格納して、画面にこれらを表示します。この部分は、開発者の要望と必要 (表示する方法、高得点表の位置、高得点表の形式など) に、最も依存しています。

まず最初に、私たちは、名前と得点登録を含む、テキスト・ファイルを作ります。
'high_scores.dat' という名前のファイルを作ってください。そして、テキスト・エディタでこれを開いて、下のデータを入力してください:

FRED
10000
BILL
9000
SARAH
8000
BOB
7000
RED
6000
SUE
5000
DAVID
4000
GREG
3000
TIM
2000
GEORGE
1000


これは、10 の高得点登録を含んでいます。形式は、名前のあとに、対応する得点が続いています。
私は、この形式が、編集するのに最もふさわしいと思います。あなたは、すべての名前を最初に並べて、次にすべての得点を続ける形式を採用することもできます。
これらの 2つの形式の違いで重要な差異はありません。したがって、私が始めたものを使います。

このファイルは、以下の 'ReadHighScore' サブルーチンで、使います。

いくつかの必要な開始命令文から、主プログラムを始めましょう:

#include "fbgfx.bi"
Using FB

Const num_of_entries = 10


'num_of_entries' は、得点登録 (高得点表の名前か得点) の数の旗を揚げます。そして、'high_score.dat' ファイルの登録数に対応します (行数ではなく、高得点登録です!)。

ここで、下のようにサブルーチンを宣言します。

Declare Sub ReadHighScore (highscore_file As String)


'highscore_file' 変数は、'ReadHighScore' サブルーチンで開きたいファイルの旗を揚げます。
このようにサブルーチンを宣言する必要はありません。しかし、これは、いくつかの柔軟性を加えます。

この後、下の変数を宣言します:

Dim Shared workpage As Integer
Dim Shared hname(num_of_entries) As String
Dim Shared hscore(num_of_entries) As String


'workpage' 変数は、このチュートリアルに関係しません。これは、高得点表を描く場合に、繰返しの中で、画面の作業ページを交換するために、使われます。
'hname' 配列は、名前登録を保持します。'hscore' 配列は、高得点表から、得点登録を保持します。

最後に、下で、画面と、仕事ページ/目に見えるページを、初期化しましょう。

ScreenRes 640, 480, 32, 2, GFX_ALPHA_PRIMITIVES+GFX_WINDOWED
ScreenSet 1, 0


上のコードの後に、下のコードを置きます:

ReadHighScore "high_scores.dat"
End

Sub ReadHighScore (highscore_file As String)

End Sub


あなたはこのコードをコンパイルできます。しかし、'ReadHighScore' サブルーチンが空のときに、何も起こらないでしょう。
それを満たしましょう!

'high_scores.dat' ファイルを開いて、これから必要なデータを読むことで、それを始める必要があります。
ファイルを開くことになじみがないなら、FreeBASIC の OPEN 命令文を参照して、ファイル・オープニングに関する情報を得てください。

空いているファイル・ハンドルを使ってファイルを開きたいので、ハンドルの情報を保持して、ハンドルを OPEN 命令文に渡す変数を定義する必要があります。
下のコードを使います:

Dim free_filehandle As Integer

free_filehandle = FreeFile


私たちは、今、下のコードで高得点ファイルを開きます。

Open highscore_file For Input As #free_filehandle


ファイルを、読む (FOR INPUT) ために開いた後、for loop を使って、ファイルから、すべてのデータを検索して、変数 'hname' と 'hscore' に、格納します:

For count_entry As Integer = 1 To num_of_entries
Input #free_filehandle, hname (count_entry)
Input #free_filehandle, hscore (count_entry)
' ファイルの終りに達したら、FOR ループを出ます。
If EOF(free_filehandle) Then Exit For
Next count_entry


'count_entry' 変数がどのように使われているか、そして、各登録に対して、付随の得点に従って、名前がどのように格納されるか、に注意してください。
'hname(1)' は、'hscore(1)' がトップの得点なので、トップ得点の名前の旗を揚げます。
'hname(num_of_entries)' は、'hscore(num_of_entries)' が、高得点表の最も低い得点なのて、最も低い得点の名前の旗を揚げます。

ここで、下でファイルを閉じるのを忘れないでください。

Close #free_filehandle 


ここまで来れば、残ったものは、表にうまく配置された、これらのすべての名前と得点を表示するループだけです。

Do

ScreenLock
ScreenSet workpage, workpage Xor 1

Line (0,0)-(639,479), RGBA(0, 0, 0, 255), BF

Draw String (285, 120), "TOP SCORES", RGBA (255,255, 255, 255)

For count_entry As Integer = 1 To num_of_entries
Draw String (270, 140 + count_entry * 12), hname(count_entry), RGBA (255,255, 255, 250-count_entry*10)
Draw String (340, 140 + (count_entry) * 12), hscore(count_entry), RGBA (255,255, 255, 250-count_entry*10)
Next count_entry

Draw String (245, 400), "Press ESCAPE to exit", RGBA (255,255, 255, 220)

workpage Xor = 1
ScreenUnlock

Sleep 10

Loop Until MultiKey (SC_ESCAPE)


単純な DO...LOOP は、ユーザが ESCAPE キーを押すと、終わります。

私は、名前と得点を表示するのに、Draw String を使いました。
別の FOR ループは、名前と得点の登録を貫通する輪として使っています。そして、次の高いものの下に、より低い得点を表示するために、使われます。(表示するテキストの Y 位置が、どう 'count_entry' 変数に関連づけられているかに注意してください - 垂直方向で、得点の間で、より多くの空白を得ために 12 増加させています)。
私は、また、小さいトリックを使って、順に次の得点を、低い半透明性 (RGBA 関数 の最後のパラメタ) で表示しました。

'ReadHighScore' サブルーチンに、このすべてのコードを置いた後、あなたは、これをコンパイルできます。そして、希望した結果が、画面に現れるでしょう。

問題の簡単な部分が終わったので、次に、高得点表に新しい登録を書く部分に移りましょう。

私は、下のように 'WriteHighScore' サブルーチンを構成しました:

Sub WriteHighScore (highscore_file As String, users_score As Integer)


このサブルーチンは、高得点表ファイルと、入力したい得点を呼んでいることを、表しています。
この得点が、高得点表で、最も低いものより少ないと評価すると、コードは全く実行されません。

このサブルーチンは、下のコードで始まります:

Dim free_filehandle As Integer

Dim startwrite As Integer

free_filehandle = FreeFile

Open highscore_file For Input As #free_filehandle

For count_entry As Integer = 1 To num_of_entries
Input #free_filehandle, hname (count_entry)
Input #free_filehandle, hscore (count_entry)
' ファイルの終りに達したら、FOR ループを出ます。
If EOF(free_filehandle) Then Exit For
Next count_entry

Close #free_filehandle


ご覧のように、これは 'ReadHighScore' サブルーチンとして開始します。
ユーザの得点を評価して、まさに高得点表を入れ替えるために、高得点登録を含むファイルを開いて、これらを、適当な変数に格納する必要があります。
'startwrite' 変数は、新しい登録が、高得点表の中で、置かれることになる場所 (位置) の旗を立てます。

下のコードは、IF 節で始まります。IF 節は、ユーザの得点が、高得点表の最も低い得点より高い場合にだけ、IF 節の中のコードを実行します (通常):

If users_score > hscore(num_of_entries) Then

For check_score As Integer = 1 To num_of_entries

If users_score > hscore(check_score) Then
InputName

' 新しい得点が置かれた位置を記録して、
' そして、FOR loop を出ます。
startwrite = check_score
Exit For
End If

Next check_score


FOR ループは、高得点登録で、最も高いものから最も低いものまで、繰り返します。そして、より低い得点の登録が見つかると、これは、新しい登録が記録される場所 ('startwrite' と 'check_score' の旗を立てる) になります。
例えば、最初のループでは、プログラムは 'hscore(1)' - 高得点表のトップ得点 - かどうか、チェックします。
ユーザの得点が、それより高いなら、ユーザの得点は、新しいトップ得点で、'startwrite' は、1になるのは、明白です。
'InputName' は、私たちが後で作成するつもりのサブルーチンです。そして、その中で、ユーザは、彼の名前を入力します。 :P

下は、私たちのルーチンの '中核' です。新しい高得点登録を適切な場所に置いて、より低いものすべてを、下に移動させるコードです。
下のコードを確認して下さい:

If startwrite = num_of_entries Then
hscore(startwrite) = users_score
hname(startwrite) = playername
Else
 
For write_pos As Integer = (num_of_entries - 1) To startwrite Step -1
hscore(write_pos + 1) = hscore (write_pos)
hname(write_pos + 1) = hname (write_pos)
Next write_pos
hscore(startwrite) = users_score
hname(startwrite) = playername
End If


最初の条件は、新しい登録が、高得点表の、最低 (最後) かどうかをチェックします。
この条件に合致すれば、下位に相当する得点は何もないので、どの登録も引き下げる必要はありません。 単に、最下位得点の登録を、新しいものに取り替えるだけです。

この条件に合致しなければ、FOR ループは、高得点登録の最も低いものから、新しい高得点登録 ('startwrite' の旗を揚げています) まで、つまりお尻から頭まで、実行を繰返します。

例えば、高得点表に 10の登録があって、新しい登録を、位置 5に置く必要があるなら、ループは 9〜5 まで繰返します。
"write_pos" が 9 のとき、'hscore(9)' と 'hname(9)' からの値は、'hscore(9+1)' と 'hname(9+1)' に渡されます。
'write_pos' が 8 のとき、'hscore(8)' と 'hname(8)' からの値は、'hscore(8+1)' と 'hname(8+1)' に渡されます。
など、などです。

FOR ループの後で、私たちは、適切な位置 ('startwrite' の旗が揚がっている) に、新しい登録を入力する必要があります。新しい登録は、'users_score' と 'playername' で始まります。'InputName' sub の中で、'playername' が 入力されるところです。

'WriteHighScore' sub で最後にすることは、新しい高得点登録を、ファイルに格納戻しすることです:

free_filehandle = FreeFile

Open highscore_file For Output As free_filehandle
For count_entry As Integer = 1 To num_of_entries
Print #free_filehandle, hname (count_entry)
Print #free_filehandle, hscore (count_entry)
Next count_entry
Close free_filehandle


FOR OUTPUT の使い方と、外部ファイルにデータを書くための PRINT に注意してくださいか。

この後、'ReadHighScore' 呼び出しを置いて、END IF で閉じます。新しい登録をファイルに入力した後、新しい高得点表を表示するのが良いと思うからです。

現在必要なのは、下のように 'InputName' sub を作ることです:

Sub InputName

ScreenSet workpage, workpage Xor 1
ScreenSet 0,0
Line (0,0)-(639,479), RGBA(0, 0, 0, 255), BF
Locate 12, 17
Input ; "Please input your name: ", playername

End Sub


もちろん、これは、あなたのゲームでは、まったく違った形になるでしょう。
おそらく、あなたは、ゲームの別の場所で、プレーヤーの名前を入力するようにに頼むでしょう(その人が新しいゲームを始める時のような)。
ちょっと心に留めておいて下さい。

ルーチンをテストするために、下のように置いてください...

ReadHighScore "high_scores.dat"
WriteHighScore "high_scores.dat", 4500
End


...最初の SCREENSET (サブルーチンの外) の後にです。
高得点表の異なる場所に異なる得点を入力するために、'WriteHighScore' 呼び出しを使って、2番目のパラメータを変更します。
私は、あなたが 'WriteHighScore' を呼ぶとき、第2のパラメータを、静的な数字で決め打ちしてはならないことに気づいていると確信します。 これは、あなたの場合では、あなたがプレーヤーの得点を保存する変数です。(つまり、 'Player.Score')

次は何ですか?

このテーマに関連して共有したいその他の項目は、高得点の暗号化と、名前を入力するためのより良いルーチンです。
私が使っている両方のルーチンは、私が作ったものではないですが、あなた自身のニーズのために簡単に使えるプログラムの例として、提供します。

暗号化は、2つの関数、'neoENCpass' と 'neodeENCpass' を使って行います。
一つは暗号化のため、もう一つは復号化のためのものです。
これらは、文字列 (ここでは、高得点登録文字列) とパスワードで呼ばれます。パスワードは、あなたが選ぶどんな文字列でもよくて、同じものが、暗号化と復号化で使われます (もちろん)。

ファイルから文字列登録を検索した直後に、下のようにして、これを復号化します:

Input #free_filehandle, hname (count_entry)
neoENCdepass SAdd(hname(count_entry)), Len(hname(count_entry)), "yourpass"



With 'hscore' variables, being INTEGER, we need to use a temporary STRING variable which has to be decrypted and then pass its value to 'hscore'.
'hscore' 変数は、INTEGER になっているので、復号化して、その値を、'hscore' に渡すために、一時的な STRING 変数を使う必要が有ります。

この方法の唯一の煩わしい点は、高得点ファイルを暗号化/復号化するために、別々のソースコードを必要とするという事実です。高得点ファイルが、前もって暗号化されている場合にだけ、プロジェクトの中のルーチンが働くからです。
私は、この暗号化する、小さいプログラムを、あなたのために提供します。
高得点ファイルを暗号化しない場合でも、別のフォルダーに、高得点ファイルのバックアップを保存することを推奨します。(私は、zip ダウンロードで、これを提供します。)

暗号化の代わりに、BINARY ファイルを使うこともできます。しかし、私は、これを書いている時点で、BINARY ファイルの使い方を知りません。(私は、研究する時間がありません。ぎりぎりの日程でこのチュートリアルを提出しています)。そして、BINARY ファイルは、暗号化と同じでありません。
BINARY ファイルは、あなたのソースを持っているひとは、だれでも読むことができます。しかし、このルーチンを使って暗号化されたファイルは、パスワードを知っている人 (そうです、ほとんどの人々です) は、単に解読できるだけです。
そうです。あなたのソースコードを公開するときは、ソースコードの中の暗号化パスワードを、必ず変えてください。

とにかく、あなたは、暗号化を全く必要としないか、好まないかもしれません。
しかし、私は、個人的に、高得点ファイル/スクリプト・ファイルを暗号化するのが好きです。なので、太郎さんも花子さんも誰も、メモ帳やテキスト・エディタで、それを変更したり読んだり、できません。
Unencrypted high scores might kill the challenge to beat them with some players.
暗号化されない高得点は、プレーヤーの誰かに挑戦されて死ぬかもしれません。

名前入力処理は、ここでは重要でないので、私は、説明しません。
あなたは、コードを読んで理解して下さい。
これは、平文の INPUT より、はるかに良いです。(あつらえの字体の表示ライブラリと共に、これを使うことができます)。そして、名前の文字数を制限することも、できます。
ルーチンは、'Ryan Szrama' が作ったものです。すべて彼のおかげです。

拡張した例を、ダウンロードしてください (暗号化を追加して、名前入力を改良してあります):
http://lachie.phatcode.net/Downloads/Managing_A_High_Score_Table.zip

そして、このチュートリアルはこれでおしまいです。

次回まで、楽しんでください!

Lachie D によって書かれたチュートリアル。
(mailto CHR$(58) lachie13 CHR$(64) yahoo CHR$(46) com ; http://lachie.phatcode.net - The Maker Of Stuff)

いっしょに学ぼう に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2012-01-22 22:22:54
日本語翻訳:WATANABE Makoto、原文著作者:NkKkan(Lachie Dazdarian(September, 2007))

ホームページのトップに戻る

表示-非営利-継承