月別アーカイブ: 2013年6月

24日目+2 メッセージダイアログ

uses
FMX.Dialogs,
System.UITypes;

を追加

列挙型は、型から書くのがFiremonkey流らしい。

  if mrOk = MessageDlg('ゲームを終了していいですか。', TMsgDlgType.mtConfirmation,  [TMsgDlgBtn.mbOk, TMsgDlgBtn.mbCancel], 0) then
  begin
    GameStep := gsGameEnd;
    Viewer.MainTabPage := mtTitle;
  end;

24日目+1 データベースを使わない方法を模索

データベースを使おうと思ったり理由は、実機テストで信じられないくらい時間がかかったため。

Win32 では数秒の処理が数十分かかった。

これはどうも、動的配列を逐次大きくして追加していた部分にあったみたい

procedure TWordList.AddItem(aWordRecord: TWordRecord);
begin
  SetLength(Self.Items, Length(Self.Items) + 1);
  Self.Items[High(Items)].Assign(aWordRecord);
end;

procedure TWordList.Load(aPathFileName: string);
var
  i: Integer;
  tmpWordRecord: TWordRecord;
  tmpRecordList: TStringList;
  tmpFieldList: TStringList;
  tmpString: String;
begin

//  DeleteFile(aPathFileName);

  self.Clear;

  if FileExists(aPathFileName) then
  begin
    tmpFieldList  := TStringList.Create;
    tmpRecordList := TStringList.Create;

    tmpRecordList.LoadFromFile(aPathFileName);

    for i := 0 to tmpRecordList.Count - 1 do
    begin

      tmpFieldList.Delimiter := chr(DEMILITR_CHR);
      tmpFieldList.StrictDelimiter := False;

      tmpString := tmpRecordList[i];
      tmpFieldList.DelimitedText := tmpString;

      tmpWordRecord.Word := trim(tmpFieldList[0]);
      tmpWordRecord.Japanese := trim(tmpFieldList[1]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]);

      self.AddItem(tmpWordRecord);

    end;
    tmpRecordList.Free;
    tmpFieldList.Free;
  end;

end;

最初に配列の大きさを決定して、代入するととてつもなく早くなった。
これで、データベースを使う必要はなくなった。


procedure TWordList.Load(aPathFileName: string);
var
  i: Integer;
  tmpWordRecord: TWordRecord;
  tmpRecordList: TStringList;
  tmpFieldList: TStringList;
  tmpString: String;
begin

  self.Clear;

  if FileExists(aPathFileName) then
  begin

    tmpFieldList  := TStringList.Create;
    tmpRecordList := TStringList.Create;

    tmpRecordList.LoadFromFile(aPathFileName);

    SetLength(Self.Items, tmpRecordList.Count);

    for i := 0 to tmpRecordList.Count - 1 do
    begin

      tmpFieldList.Delimiter := chr(DEMILITR_CHR);
      tmpFieldList.StrictDelimiter := False;

      tmpString := tmpRecordList[i];
      tmpFieldList.DelimitedText := tmpString;

      tmpWordRecord.Word := trim(tmpFieldList[0]);
      tmpWordRecord.Japanese := trim(tmpFieldList[1]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]);


      Self.Items[i].Assign(tmpWordRecord);

//      self.AddItem(tmpWordRecord);

    end;
    tmpRecordList.Free;
    tmpFieldList.Free;
  end;

end;


24日目+1 InterBase のライセンス認証で四苦八苦

InterBase のライセンス認証で四苦八苦する。

メールで送られてきたライセンス使用許諾ファイルをどこに置くかわからない。

製品: IBLite XE3 for iOS Deployment License
メールで説明されている手順:
1. まず、添付ファイルをハード ドライブ上の任意のフォルダ (“マイ ドキュメント” など) に保存します。
2. RAD Studio XE4 ユーザーのお客様が IBLite ライセンスを必要とされる場合には、上記のライセンス ファイルを “%IBREDISTDIR%” フォルダにコピーします。
3. その後、RAD Studio の配置ウィザードの指示に従って進みます。ファイルは必ず、アプリケーションと一緒にターゲット プラットフォーム向けにバンドルし、ターゲット プラットフォームの interbase/license フォルダ パスに配布してください。
実際にうまくいった手順:
ライセンス ファイルを “%IBREDISTDIR%” フォルダにコピーして、reg_iblite にリネームする。

“%IBREDISTDIR%” フォルダとは

C>ユーザー>パブリック>パブリックのドキュメント>InterBase>redist>InterBaseXe3 (OS:Windows 7)

製品: InterBase XE3 ToGo Test Deployment
RAD Studio XE4 ユーザー様の場合:
ライセンス使用許諾ファイルを “%IBREDISTDIR%” フォルダに reg_ibtogo.txt という名前で保存します。これは、Windows、MacOSX、iOS への配置に適用されます。

とりあえず、iOS Simulator では動作を確認、しかし、実機でのテストではエラー発生。配置のミスか?

23日目 実機テストでテキストファイルを読めるようになったが・・・

実機テストでテキストファイルを読めるようになったが・・・
データ数は40000ぐらい。
Win32 では1秒
iOS simulator では20秒
実機テストでは20分はかかる。
大きいデータではこの方法は無理。
InterBase を使う方向で考える。

procedure TWordList.Load(aPathFileName: string);
var
  i: Integer;
  tmpWordRecord: TWordRecord;
  tmpRecordList: TStringList;
  tmpFieldList: TStringList;
  tmpString: String;
begin

//  DeleteFile(aPathFileName);

  self.Clear;

  if FileExists(aPathFileName) then
  begin
    tmpFieldList  := TStringList.Create;
    tmpRecordList := TStringList.Create;

    tmpRecordList.LoadFromFile(aPathFileName);

    for i := 0 to tmpRecordList.Count - 1 do
    begin

      tmpFieldList.Delimiter := chr(DEMILITR_CHR);
      tmpFieldList.StrictDelimiter := False;

      tmpString := tmpRecordList[i];
      tmpFieldList.DelimitedText := tmpString;

      tmpWordRecord.Word := trim(tmpFieldList[0]);
      tmpWordRecord.Japanese := trim(tmpFieldList[1]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]);
      tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]);

      self.AddItem(tmpWordRecord);

    end;
    tmpRecordList.Free;
    tmpFieldList.Free;
  end;

end;

23日目 配置マネージャー

配置マネージャーで、画像や音声を初回起動時に配置しているが、同名ファイルがあった場合は新たに配置ない仕様になっているみたい。

まず、古いファイルを手動で削除する必要がある。

それにしても、配置マネージャーは使い勝手が悪い。コピー、ペーストもできないし、すべてタイプしなくてはいけないなんて。

みんなどうしてるのかな?

23日目 TList の型キャストはジェネリクスを使って解決

uses に  System.Generics.Collections を追加

private
FUndoList: TList<TUndoRecord>;

FUndoList := TList<TUndoRecord>.Create;
アクセスは直接
GameModel.TileManager.TileList.Assign(FUndoList[tmpUndoStep].UndoTileList);
といった形で。

これは型キャストの必要がないので、コードがすっきり。
iOS Simulator でも動作することを確認。

23日目 TList のキャストが iOS ではうまくいかないことがある?

あまり行儀のよくない型キャストが win32 と iOS系では動作が違うような気がする。

GameModel.TileManager.TileList.Assign(TUndoRecord(FUndoList[tmpUndoStep]).UndoTileList);

このあたりをジェネリクスを使って、書き換えることにする。

 

21日目 実機でテスト(iPhone5 )

ハイスコア関係で手間取り、やっと実機テスト。

どうやら辞書ファイルが読まれていないようだ。

ファイルサイズの上限があるのか?

DB化する必要があるのか?

実はi-Simulator でもアクセス違反のエラーがまだ取れていない。

デザイン、音関係もこれから。

あと3日ではたしてどこまでできるのか。

21日目 クイックソート 序列の配列も返す

type
  TSortArray = array of Integer;



procedure QuickSortWithOrderList(var vSortArray: TSortArray; var vOrderArray:TSortArray);
var
  i: Integer;

  procedure DoQuickSort(vSortArray:TSortArray; vSortOrderArray:TSortArray; start,last:integer);
  var
    tmpCompareIndex,
    tmpSwapIndex,
    tmpCompareValue: integer;

    procedure swapValue(aIndexA, aIndexB: Integer);
    var
      tmpDummyValue: Integer;
    begin
      tmpDummyValue := vSortArray[aIndexA];
      vSortArray[aIndexA] := vSortArray[aIndexB];
      vSortArray[aIndexB] := tmpDummyValue;

      tmpDummyValue := vSortOrderArray[aIndexA];
      vSortOrderArray[aIndexA] := vSortOrderArray[aIndexB];
      vSortOrderArray[aIndexB] := tmpDummyValue;
    end;

  begin
    tmpSwapIndex := (start + last) div 2;

    swapValue(start, tmpSwapIndex);

    tmpCompareValue := vSortArray[start];
    tmpSwapIndex    := start + 1;
    tmpCompareIndex := start + 1;
    while tmpCompareIndex <= last do
    begin
      if vSortArray[tmpCompareIndex] < tmpCompareValue then   	// 降順
      begin
        swapValue(tmpCompareIndex, tmpSwapIndex);
        Inc(tmpSwapIndex);
      end;
      Inc(tmpCompareIndex);
    end;
    Dec(tmpSwapIndex);

    swapValue(start, tmpSwapIndex);

    if tmpSwapIndex-start > 1 then
      DoQuickSort(vSortArray,vSortOrderArray,start,tmpSwapIndex);
    if last-tmpSwapIndex > 1 then
      DoQuickSort(vSortArray,vSortOrderArray,tmpSwapIndex+1,last);
  end;

begin
  SetLength(vOrderArray, Length(vSortArray));
  for i :=0 to Length(vOrderArray) - 1 do
    vOrderArray[i] := i;

  DoQuickSort(vSortArray, vOrderArray, LOW(vSortArray), HIGH(vSortArray));
end;


19日目 クイックソート

数値配列の整列 ~QuickSort~

http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/QSort.htm

procedure QuickSort(vSortArray:TSortArray; start,last:integer);
var
  tmpCompareIndex,
  tmpSwapIndex,
  tmpCompareValue: integer;

  procedure swapValue(aIndexA, aIndexB: Integer);
  var
    tmpDummyValue: Integer;
  begin
    tmpDummyValue := vSortArray[aIndexA];
    vSortArray[aIndexA] := vSortArray[aIndexB];
    vSortArray[aIndexB] := tmpDummyValue;
  end;

begin
  tmpSwapIndex := (start + last) div 2;

  swapValue(start, tmpSwapIndex);

  tmpCompareValue := vSortArray[start];
  tmpSwapIndex    := start + 1;
  tmpCompareIndex := start + 1;
  while tmpCompareIndex <= last do
  begin
    if vSortArray[tmpCompareIndex] < tmpCompareValue then   	// 降順
    begin
      swapValue(tmpCompareIndex, tmpSwapIndex);
      Inc(tmpSwapIndex);
    end;
    Inc(tmpCompareIndex);
  end;
  Dec(tmpSwapIndex);

  swapValue(start, tmpSwapIndex);

  if tmpSwapIndex-start > 1 then
    QuickSort(vSortArray,start,tmpSwapIndex);
  if last-tmpSwapIndex > 1 then
    QuickSort(vSortArray,tmpSwapIndex+1,last);
end;


17日目 動的配列をデフォルトプロパティにしてアクセスを簡単にしようと試みる

エラーがでないのでいけるかなと思ったけどやっぱり無理

type
TStageScore = Record
private

FTileCount        : Integer;

FWordPoint        : Integer;
FItemPoint        : Integer;

FIsCleared        : Boolean;
FIsOnTime         : Boolean;
FIsNoDeleteItem   : Boolean;
FIsNoUndo         : Boolean;
FDoubleUpItemCount: Integer;

FIsStageFinished  : Boolean;

function getStageScore: Integer;
function getBasicPoint: Integer;

public

CompleteWordArray: TWordArray;

procedure Init(aTileCount: Integer);
procedure Assign(aStageScore: TStageScore);

// 受信系
procedure AddCompleteWord(aWord: String);
procedure AddItemPoint(aPoint: Integer);
procedure ClearedStage(aTimePoint: Integer);
procedure GiveUpStage(aTimePoint: Integer);
procedure BreakMoDeteteItem();
procedure BreakNoUnDo();
procedure UseDoubleUpItem();

Property WordPoint        : Integer read FWordPoint;
Property ItemPoint        : Integer read FItemPoint;
Property TileCount        : Integer read FTileCount;
Property IsCleared        : Boolean read FIsCleared;
Property IsOnTimet        : Boolean read FIsOnTime;
Property IsNoDeleteItem   : Boolean read FIsNoDeleteItem;
Property IsNoUndo         : Boolean read FIsNoUndo;
Property DoubleUpItemCount: Integer read FDoubleUpItemCount;
Property IsStageFinished  : Boolean read FIsStageFinished;

Property BasicPoint       : Integer read getBasicPoint;
Property StageScore       : Integer read getStageScore;

end;

type
TGameScore = record
private
//  FItems: array of TStageScore;
function getItem(aIndex: Integer): TStageScore;
procedure setItem(aIndex: Integer; const Value: TStageScore);
public
FItems: array of TStageScore;
// 初期化
procedure Init();
procedure Assign(aGameScore: TGameScore);

function AverageScore(): Single;
function AverageWordLength(): Single;
function CountWhereWordLengthIs(aWordLength: Integer): Integer;

function GameScore(): Integer;

Property Items[aIndex: Integer]: TStageScore read getItem write setItem; default;

end;

修正後
FItems を public にした

type
TGameScore = record
private
public
Items: array of TStageScore;
// 初期化
procedure Init();
procedure Assign(aGameScore: TGameScore);

function AverageScore(): Single;
function AverageWordLength(): Single;
function CountWhereWordLengthIs(aWordLength: Integer): Integer;

function GameScore(): Integer;

end;

class か record か

継承する場合
class のみ

初期化が必要な場合、要素に class をもつ場合
class が望ましい

それ以外
record でOK (メモリー管理が用意、ただし、index が溢れた場合予測不可能なエラーがおこる)

 

 

 

13日目 Delphi XE4 Professional と Mobile Add-On Pack for Delphi XE4 を購入

実はここまでの開発はトライアル版を使っていた。

トライアル期間が過ぎたのでprofessional を リオス e-shop で購入

翌日から、ダウンロードして利用できるらしい。

商品名: Delphi XE4 Professional ESD キャンペーン版
商品コード: HDBX04MLENWBC
数量:1 個
金額:¥ 95,000
商品名: Mobile Add-On Pack for Delphi XE4 Professional キャンペーン版
商品コード: HDLX04MLENWBC
数量:1 個
金額:¥ 47,500
———————————————————–
小 計 ¥ 142,500 (うち消費税 ¥6,784)

XE4、すごいソフトだと思うけど、やっぱり趣味で買う人はなかなかいないよね。