• 検索結果がありません。

繝医Λ繝ウ繝励た繝ェ繝い縲繧キ繝ウ繝励Ν繧オ繧、繝「繝ウ

N/A
N/A
Protected

Academic year: 2021

シェア "繝医Λ繝ウ繝励た繝ェ繝い縲繧キ繝ウ繝励Ν繧オ繧、繝「繝ウ"

Copied!
12
0
0

読み込み中.... (全文を見る)

全文

(1)

20

トランプソリテア シンプルサイモン

いよいよ本格的なトランプのゲームを作ります。 シンプルサイモンは,ウィンドウズのゲームパックに入っているトランプソリテア1のひとつ “スパイダーズ” の 1 パック版です。

20.1

ホイル

20.1.1 レイアウト トランプ 1 パック 52 枚を表向きにして次のように 10 列に並べます。左の列から順に,1 枚,2 枚,3 枚,. . . ,7 枚,8 枚,8 枚,8 枚 で,各列のカードは下のカードが何かわかるように少しず らして重ねて置きます。これをテーブルと言います。 20.1.2 移動可能なカード群 各列のトップカード(一番上にあるカード)は移動可能です。その下にトップカードと同じスー トでランクが 1 ずつ小さいカードが重なっている場合は,それらをまとめて移動可能です。たとえ ば,スペードの 5 の下にスペードの 6,スペードの 7 の順に重なっていれば,それら 3 枚をまとめ て移動可能です。 20.1.3 移動先 トップカードの上に,スートに関係なくそれよりランクが 1 大きいカードを乗せることができま す。したがって,上の例の移動可能な 3 枚のカード群は,ランクが 8 のトップカードがあればその 上にまとめて乗せることができます。 また,空になった列があれば,そこには移動可能なカード群は何でも移すことができます。 20.1.4 上げる 同じスートの 13 枚のカードがランク順に重なると,それらをテーブルから取り除く(上げる) ことができます。 20.1.5 目的 4 つのスートをすべて上げてテーブルを空にしたら成功です。 1ソリテア (solitaire) とは一人遊びのことで,特定のゲームを指す言葉ではありません。

(2)

20.2

プログラムの準備

20.2.1 アプリケーションを[ファイル|新規作成]                   フォルダ Simon (Trump の中に作る) ユニット SimonU.pas プロジェクト SimonP.dpr 20.2.2 フォームのプロパティ                   Name FormSimon Caption トランプソリテア シンプルサイモン 学生証番号 氏名 Position poDeskTopCenter 20.2.3 ユニットに追加 uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs ,TrumpU; type TFormSimon = class(TForm) private Trump : TTrump; public end; これだけで翻訳(コンパイル)するとエラーになります。 20.2.4 TrumpU を追加 [プロジェクト|プロジェクトに追加]を行い,TrumpU を追加する。 表示上は何も変化がありませんが,翻訳するとエラーが出なくなっています。 20.2.5 メインパネルと終了ボタン Panel をフォームの中に置く。                   Align alBottom いつもと違って下に付ける Height 40 くらい Name PanelMain Caption Button をメインパネルの中,左端の方に置く。                   Name ButtonClose Caption 終了 Anchors.akLeft False Anchors.akRight True

(3)

(********** Method **********) (********** Event Handler **********)

procedure TFormSimon.ButtonCloseClick(Sender: TObject); begin Close; end; {ButtonCloseClick} 20.2.6 テーブルイメージ Image をフォームの中,メインパネルの外に置く。                   Align alClient Name ImageTable Width 880 (となるように Form を大きくする) Height 640 (となるように Form を大きくする) 20.2.7 作成タイマー

Example プログラムでは,FormCreate 時に Trump を生成し,作成ボタンを押すと各 Card を 作成しました。これを一箇所にまとめて自動的に行うようにしたいのですが,メインフォームの FormCreate 時には FormTrump ができてないので Card を作成することはできません。作成ボタ ンを押すのではなくタイマーを使って自動的に行うようにします。 Timer をフォームの中,任意の場所に置く。         Name         TimerSakusei Interval 1 begin if Trump = NiL // 未作成なら作成する then begin // 最初に1回だけ実行 Trump := TTrump.Create; Trump.Sakusei(Self); Trump.MouseHandler(CardMouseDown,CardMouseUp,CardMouseMove); end; end; TimerSakuseiTimer 20.2.8 Card の Mouse ハンドラーを追加 前回やったように,CardMouseDown,CardMouseUp,CardMouseMove をメソッドとして追加し ます。とりあえず実現部はコメント行を書いておきます(何も書かないと自動的に消されることが あるので)。 20.2.9 実行 カードが作成されます。

(4)

20.2.10 カードをばらまく

どうせタイマーを使うなら,楽しみましょう。

procedure TFormSimon.TimerSakuseiTimer(Sender: TObject); var CardNo : TCardNo; RectSaki : TRect; RectMoto : TRect; X1,Y1 : Integer; begin if Trump = NiL // 未作成なら作成する then begin // 最初に1回だけ実行 Trump := TTrump.Create; Trump.Sakusei(Self); Trump.MouseHandler(CardMouseDown,CardMouseUp,CardMouseMove); end; //Trump.Hide; X1 := Random(ClientWidth)-36; Y1 := Random(ClientHeight)-48; CardNo := Random(52); with Trump.Cards[CardNo] do begin RectMoto := Canvas.ClipRect; RectSaki := Bounds(X1,Y1,72,96); ImageTable.Canvas.CopyRect(RectSaki,Canvas,RectMoto); end; end; {TimerSakuseiTimer} 20.2.11 実行 楽しめましたか。 最初に作成したカードがちらついて目障りなので //Trump.Hide;  の // を消して 見えなくしましょう。 実行する前に,TrumpU にメソッドを追加する必要があります。 20.2.12 TrumpU にメソッドを追加 [表示|ユニットの表示]をして TrumpU を表示させて追加します。 procedure TTrump.Hide; (* 見えなくする *) var CardNo : TCardNo; begin for CardNo := 0 to 51 do Cards[CardNo].Hide; end; (* Hide *)

(5)

procedure TTrump.Show; (* 見えるようにする *) var CardNo : TCardNo; begin for CardNo := 0 to 51 do Cards[CardNo].Show; end; (* Show *) 20.2.13 実行 ちらつきがなくなるはずです。 もう TrumpU を変更することはないので,[ファイル|閉じる]で見えなくしてかまいません。

20.3

ゲーム開始準備

SimonU に追加します。 20.3.1 データ構造 type TCol = 1..10; TRow = 0..52; TColAndRow = record Col: TCol; Row: TRow; end;

TTable = array [TCol,TRow] of TCardNo;

TMaisuu = array [TCol] of TRow;

TBasyo = array [TCardNo] of TColAndRow; TFormSimon = class(TForm) 途中省略 private Trump : TTrump; Table : TTable; Maisuu : TMaisuu; Basyo : TBasyo; SentakuChuu: Boolean; ErandaFuda : TCardNo; NokoriSuit : 0..4; public end; 20.3.2 メソッドを追加 (********** Method **********)

(6)

(* Col 列にCardNo番の札を追加する *) var Row : TRow; begin // 内部処理 Inc(Maisuu[Col]); // Col 列の札が1枚増える Row := Maisuu[Col]; // 枚数行目に

Table[Col,Row] := CardNo; // CrdNo 番の札を置く

Basyo[CardNo].Col := Col; // その場所を逆引きできるように Basyo[CardNo].Row := Row; // 表示 with Trump.Cards[CardNo] do begin Top := 30*Row; Left := 80*Col-40; BringToFront; Visible := True; end; end; {Kuwaeru} procedure TFormSimon.Layout; (* 開始状態に並べる *) (* Tableを作る *) var Col : TCol; Row : TRow; CardNo : TCardNo; begin for Col := 1 to 10 do // すべての列を空にする Maisuu[Col] := 0; Row := 1; // 1行目から始める Col := 1; // 1列目から始める for CardNo := 0 to 51 do begin Kuwaeru(Col,CardNo); // 1枚並べる if Col < 10 // 10列になるまで then Inc(Col) // 次の列にする else begin // 10列まで終わったら Inc(Row); // 次の行にする Col := Row; // 行と同じ番号の列から始める end; end; end; {Layout} procedure TFormSimon.Hyouji; (* Tableを表示する *) var Col : TCol; Row : TRow; begin with ImageTable.Canvas do begin Brush.Color := clTeal; FillRect(ClipRect); Brush.Color := clAqua; for Col := 1 to 10 do FillRect(Bounds(80*Col-40,30,72,96));

(7)

for Col := 1 to 10 do

for Row := 1 to Maisuu[Col] do with Trump.Cards[Table[Col,Row]] do begin Visible := True; PosiNiSuru; Top := 30*Row; Left := 80*Col-40; BringToFront; end; end; {Hyouji} procedure TFormSimon.Start; begin Layout; Hyouji; SentakuChuu := False; NokoriSuit := 4; TimerSakusei.Enabled := False; end; {Start} 20.3.3 開始ボタン Button をメインパネルの中,右の方に置く。         Name         ButtonStart Caption ゲーム開始

procedure TFormSimon.ButtonStartClick(Sender: TObject); begin Start; end; {ButtonStartClick} 20.3.4 実行 カードが並べられます。まだゲームはできません。 20.3.5 新ゲームボタン Button をゲーム開始ボタンの右に置く。         Name         ButtonNew Caption 新しいゲーム

procedure TFormSimon.ButtonNewClick(Sender: TObject); begin

Trump.Shuffle; Start;

(8)

20.3.6 実行 ゲーム開始ボタンは前と同じゲームに再挑戦するときに使うボタンで,新しいゲームボタンは名 前どおり新しいゲームに挑戦するとき使うボタンです。

20.4

移動可能カード群選択

移動可能カード群の一番下のカードをクリックすると,それらのカードをネガにして選択したこ とがわかるようにします。 20.4.1 メソッド追加

procedure TFormSimon.Erabu(CardNo : TCardNo);

(* CardNo番の札から上の一群が選択可能ならば選択する *) (* 選択可能=同じスーツでランクが1ずつ減少している *) var Col : TCol; Row : TRow; begin with Trump do begin Col := Basyo[CardNo].Col;

Row := Basyo[CardNo].Row; // CardNo番の札がある行から始めて

while (Row < Maisuu[Col]) and

(Cards[Table[Col,Row+1]].Suit = Cards[Table[Col,Row]].Suit) and (Cards[Table[Col,Row+1]].Rank = Cards[Table[Col,Row]].Rank-1) do

Inc(Row); // 選択可能条件を満たしていたら次の行へ

SentakuChuu := Row = Maisuu[Col]; // 上の札がすべて満たしていたらOK

if SentakuChuu then begin

ErandaFuda := CardNo; // 選んだ群の先頭

for Row := Row downto Basyo[CardNo].Row do // 選んだ群を

Cards[Table[Col,Row]].NegaNiSuru; // ネガにする end; end; end; {Erabu} procedure TFormSimon.SentakuKaijo; (* 札が選ばれている状態を解除する *) var Col : TCol; Row : TRow; begin Col := Basyo[ErandaFuda].Col; // 群(の先頭)がある列

for Row := Basyo[ErandaFuda].Row to Maisuu[Col] do // 群の札を

Trump.Cards[Table[Col,Row]].PosiNiSuru; // ポジにする

SentakuChuu := False; // 選ばれてない

end; {SentakuKaijo}

(9)

Shift: TShiftState; X, Y: Integer); begin

with TCard(Sender) do begin

if not SentakuChuu

then Erabu(Tag) // Tag = CardNo

else SentakuKaijo; end; end; {CardMouseDown} 20.4.3 実行 最初のレイアウトでは,トップカードだけが選択できます。 新しいゲームボタンを押して,運良く 2 枚以上の移動可能カード群があるようなレイアウトがで きれば,カード群が選択できることもわかるのですが,なかなかそういうレイアウトができてはく れないでしょう。

20.5

移動

現在は,移動可能カードをクリックすると選択して(ネガにして),選択状態でクリックすると 選択状態を解除します(ポジに戻します)。 選択状態でどこかをクリックしたら,そこに移動させます(もちろん移動可能なとき)。 20.5.1 CardMouseDown 変更

procedure TFormSimon.CardMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

with TCard(Sender) do begin

if not SentakuChuu

then Erabu(Tag) // Tag = CardNo

else Utsusu(Basyo[Tag].Col); end;

end; {CardMouseDown}

20.5.2 ImagaTable の OnMouseDown ハンドラーを追加

procedure TFormSimon.ImageTableMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin

if SentakuChuu and (ImageTable.Canvas.Pixels[X,Y] = clAqua) then Utsusu((X+42) div 80);

(10)

20.5.3 メソッド追加

procedure TFormSimon.Utsusu(ColTo : TCol);

(* 選んだ群をColTo列に移動可能ならば移動する *) (* 移動可能=移動先が空または一番上の札のランクが1大きい *) var RowFrom : TRow; ColFrom : TCol; begin if (Maisuu[ColTo] = 0) or (Trump.Cards[Table[ColTo,Maisuu[ColTo]]].Rank = Trump.Cards[ErandaFuda].Rank+1) then begin ColFrom := Basyo[ErandaFuda].Col;

for RowFrom := Basyo[ErandaFuda].Row to Maisuu[ColFrom] do begin Kuwaeru(ColTo,Table[ColFrom,RowFrom]); Dec(Maisuu[ColFrom]); end; end; SentakuKaijo; //SorottaraAgeru(ColTo); end; {Utsusu} 20.5.4 実行 最初のレイアウトで,次のことができることを確認しなさい。 (1) クラブの A をハートの 2 の上に移す。 (2) スペードの J を Q の上に移す。 (3) スペードの Q(とその上の J)を K の上に移す。 (4) スペードの K たちを左端の空の列に移す。 (5) その上にスペードのカードを次々に全部移す。 まだ 13 枚そろっても “上げる” ことをしません。

20.6

上げる

20.6.1 Utsusu を変更 実行部最後の //SorottaraAgeru(ColTo); の // を消す。

(11)

20.6.2 メソッドを追加

procedure TFormSimon.SorottaraAgeru(Col : TCol);

(* 13 枚揃ったら取り除く *) begin if Maisuu[Col] >= 13 then begin Erabu(Table[Col,Maisuu[Col]-12]); if SentakuChuu then Ageru(Col); end; end; {SorottaraAgeru}

procedure TFormSimon.Ageru(Col : TCol);

(* 13枚揃った群を上げる(取り除く) *) var K : 1..13; begin SentakuKaijo; // 選択状態を解除する for K := 1 to 13 do with Trump.Cards[Table[Col,Maisuu[Col]]] do begin repeat Top := Top+1; Application.ProcessMessages; // 表示する

until Top+Height >= ImageTable.Height;

Visible := False; // 見えなくする Dec(Maisuu[Col]); // 1枚減らす end; Dec(NokoriSuit); //if NokoriSuit = 0 // then GameOver(True); end; {Ageru} 20.6.3 実行 さっきと同じようにして,スペードを 13 枚そろえると,揃ったカードを上げます。 どのように上げるでしょうか。 他のスートも上げられますよ。

20.7

ゲーム終了

全部上げたら,“おめでとう” と表示するようにします。また,ギブアップできるようにします。 20.7.1 Ageru 変更 最後の 2 行の // を消す。

(12)

20.7.2 ギブアップボタン Button を 1 つ追加する。

        Name         ButtonGiveUp

Caption ギブアップ

procedure TFormSimon.ButtonClick(Sender: TObject); begin

GameOver(False); end; ButtonClick

20.7.3 メソッド追加

procedure TFormSimon.GameOver(Seikou : Boolean);

(* ゲーム終了 *) begin TimerSakusei.Enabled := True; if Seikou then ShowMessage(#13+#13+#13+’   おめでとう   ’+#13+#13+#13) else ShowMessage(#13+#13+#13+’   残念でした   ’+#13+#13+#13); end; GameOveer 20.7.4 実行 これで完全なゲームになりました。

20.8

問題

現在は,移動可能カード群を選択した後,“移動先のカードをクリックすると移動する” ように なっていますが,移動先までドラッグする(引きずっていく)ように改良しなさい。 ヒント カードをドラッグするのは Example でやりました。 移動先のカードを知る必要はありません。CardMouseUp したときの X によってどの Col に移 そうとしているかがわかれば十分です。

参照

関連したドキュメント

Such simple formulas seem not to exist for the Lusztig q-analogues K λ,μ g (q) even in the cases when λ is a single column or a single row partition.. Moreover the duality (3) is

standard Young tableau (SYT) : Obtained by filling in the boxes of the Young diagram with distinct entries 1 to n such that the entries in each row and each column are increasing.. f

N˜ ao s´ o faltam ra´ızes quadradas em Q, como muitas potˆencias fra- cion´ arias. Em particular, temos conjuntos limitados sem supremo, sequˆencias limitadas sem subsequˆencias

Ex. Qual valor de n nos d´ a uma probabilidade de aproximadamente 50%?.. Ralph Costa Teixeira, Augusto C´ esar Morgado 23!. Ex. Quem tem a maior chance de ganhar algum

If we assign to each rook diagram d the n × n, 0-1 matrix having a 1 in row i and column j if and only if the ith vertex in the top row of d is connected to the j th vertex in

Do

For Army cutworm, Armyworm species, Cutworm species, Stalkborer, or True armyworm, apply as a 5- to 7-inch band over the row on the soil surface, a 5- to 7-inch band over the

For Army cutworm, Armyworm species, Cutworm species, Stalkborer, or True armyworm, apply as a 5- to 7-inch band over the row on the soil surface, a 5- to 7-inch band over the