人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

ハイスコアランキングの作り方

CGIへスコア情報を送信する(2005/8/7)でJavaプログラムからCGIへスコア情報を送信できました。また、サーバー上のファイルにスコアを保存する(2005/8/15)で送信されたスコア情報をサーバー上のファイルに保存できるようになりました。今回は最後の手順として保存されたスコア情報からハイスコアランキングを作成します。ハイスコアランキングはJavaプログラムではありません。Perlで実装します。

ハイスコアランキングの表示

スコアは次のような形式で保存されています。

 2005/08/15 10:46&Aさん&1500
 2005/08/15 10:47&Bさん&50
 2005/08/15 14:24&Cさん&2000
 2005/09/03 13:35&Dさん&500

日付、名前、スコアです。この情報をハイスコアランキングとして表示する手順をまとめると次のようになります。

  1. スコアファイルを開く
  2. スコアが高い順にソートする
  3. 表形式のHTMLを出力する

ではプログラムです。

#!/usr/bin/perl

# スコアファイルを開く
open(SCORE_FILE, "score.txt") || die("can't open score.txt");

# 出力されるHTML
print <<END;
Content-type: text/html

<html>
<head><title>スコアランキング</title></head>
<body>
<center>
<table border="2" width="50%">
<caption>スコアランキング</caption>
<tr><th>日付</th><th>お名前</th><th>スコア</th></tr>
END

# スコアファイルを全部読み込んで配列に入れる
@scores = <SCORE_FILE>;

# スコア順にソート
@tmp = map {(split /&/)[2]} @scores;
@scores = @scores[sort {$tmp[$b] <=> $tmp[$a]} 0 .. $#tmp]; 

# それぞれの行をテーブルで表示
foreach $line (@scores) {
    ($date, $name, $score) = split(/&/, $line);
    # $scoreのうしろに改行があるので改行を除去
    chomp $score;
    print "<tr><td>$date</td><td>$name</td><td>$score</td></tr>\n"
}

print <<END;
</table>
</body>
</html>
END

close(SCORE_FILE);

Perlに慣れてない人は面食らうかもしれません。PerlのプログラムはHTMLの中に挿入できてしまうんです。上のプログラムでは、HTMLのヘッダ、テーブルのタグを出力したあとにPerlのプログラムが埋め込まれています。

まずファイルの内容を全部読み込んで@scoresに入れてしまいます。その後、スコアをもとにソートします。これが結構難しい処理です。まあ[2] という数字によって、スコア(日付が0、お名前が1、スコアが2)を対象にソートされていることだけわかればいいと思います。詳しく知りたい方は、Perlメモ特定の項目をソートするを見てください。Schwartzian変換と呼ぶ手法だそうです。@scoresにはソートされた全データが入っているのであとはテーブル形式に出力するだけです。

表示するときにソートするんではなくて、スコアを登録するときに予めスコア順になるようにしたほうが効率がよさそうです。というかプレイヤーが多くなってきたらそうやらないとまずいです。すべてのプレイヤーのスコアをファイルに保存するわけにはいかないからです。上位100人だけのスコアをファイルに保存する場合、予めスコア順に並んでいたほうが登録するかしないかが判断しやすくなります。この改良は今度気が向いたらやってみます。