テトリスのガイドラインではホールドに関する記述があります。これによると
テトリミノを1個保持できる。
使うと現在のミノがホールドに入り、ホールドにあったミノが降ってくる
(最初だけはネクストが降る)。
1回使うと設置するまで使えない。
とあります。さっそくプログラムに組み込んでみましょう。
まず、デザイナでホールドされたテトリミノが表示される部分を作成します。

またキーボードによる操作もガイドラインでは決められています。

↓がソフトドロップなのはわかるとしてなぜか右回転は↑キーです。ちょっとやりにくい。またスペースキーにはこれまで回転を割り当てていましたが、ハードドロップを割り当てるべきと書かれています。ホールドはCキーまたは左右のShiftキーになっています。
← 左に移動
→ 右に移動
↑ 右回転
↓ ソフトドロップ
スペースキー ハードドロップ
Shiftキー ホールド
Ctrlキー 左回転
Zキー 左回転
Xキー 右回転
Cキー ホールド
ESCキー Pouse
F1キー Pouse
それではそのように変更しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
public partial class Form1 : Form { private void Form1_KeyDown(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.Left) MoveLeftTetoro(); else if(e.KeyCode == Keys.Right) MoveRightTetoro(); else if(e.KeyCode == Keys.Up) RotateTetoro(); else if(e.KeyCode == Keys.Down) SoftDrop(); else if(e.KeyCode == Keys.Space) HardDrop(); else if(e.KeyCode == Keys.ControlKey) RotateTetoro2(); else if(e.KeyCode == Keys.ShiftKey) Hold(); else if(e.KeyCode == Keys.Z) RotateTetoro2(); else if(e.KeyCode == Keys.X) RotateTetoro(); else if(e.KeyCode == Keys.C) Hold(); else if(e.KeyCode == Keys.Escape) Pouse(); else if(e.KeyCode == Keys.F1) Pouse(); } void Hold() { // あとで考える } void Pouse() { // あとで考える } } |
ホールドするためにはホールドされているミノを格納する変数が必要です。
|
TetoroTypes holdTetoro = TetoroTypes.None; |
最初はホールドされているミノは存在しないので列挙体にNoneを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public partial class Form1 : Form { enum TetoroTypes { // I - テトリミノ(水色) // O - テトリミノ(黄色) // S - テトリミノ(緑) // Z - テトリミノ(赤) // J - テトリミノ(青) // L - テトリミノ(オレンジ) // T - テトリミノ(紫) I = 0, O = 1, S = 2, Z = 3, J = 4, L = 5, T = 6, None = 7, // 追加 } } |
ピクチャーボックスにホールドされているミノのイメージを表示させる必要があります。TetoroTypesからイメージを取得するメソッドとしてGetImageFromTetoroTypeを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public partial class Form1 : Form { Image GetImageFromTetoroType(TetoroTypes types) { if(types == TetoroTypes.I) return Properties.Resources.i; if(types == TetoroTypes.J) return Properties.Resources.j; if(types == TetoroTypes.L) return Properties.Resources.l; if(types == TetoroTypes.O) return Properties.Resources.o; if(types == TetoroTypes.S) return Properties.Resources.s; if(types == TetoroTypes.T) return Properties.Resources.t; if(types == TetoroTypes.Z) return Properties.Resources.z; return null; } } |
ホールドが実行されたら、現在落下中のミノをホールドします。
そしてこれまでホールドされていたものが存在しない場合は新しいミノを降らせ、存在する場合はこれまでホールドされていたミノを降らせます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public partial class Form1 : Form { void Hold() { if(holdTetoro == TetoroTypes.None) { holdTetoro = tetoroTypes; ClearOldTetoro(); ShowNewTetoro(); } else { TetoroTypes oldTetoro = holdTetoro; holdTetoro = tetoroTypes; ClearOldTetoro(); ShowNewTetoro(oldTetoro); } pictureBoxHold.Image = GetImageFromTetoroType(holdTetoro); } } |
これは新しいミノを降らせるためのメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public partial class Form1 : Form { void ShowNewTetoro(TetoroTypes tetoro) { if(tetoro == TetoroTypes.I) CreateTetoroI(); if(tetoro == TetoroTypes.O) CreateTetoroO(); if(tetoro == TetoroTypes.S) CreateTetoroS(); if(tetoro == TetoroTypes.Z) CreateTetoroZ(); if(tetoro == TetoroTypes.J) CreateTetoroJ(); if(tetoro == TetoroTypes.L) CreateTetoroL(); if(tetoro == TetoroTypes.T) CreateTetoroT(); if(FixedTetoro.Intersect(MovingTetoros).Count() != 0) { OnGameOver(); } ShowGohst(); } } |
これでよさそうなのですが、
ホールドは1回使うと設置するまで使えない
というルールがあります。そこで
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public partial class Form1 : Form { bool isAllowHold = true; void Hold() { if(!isAllowHold) return; isAllowHold = false; // 以下、変更なし } void ShowNewTetoro() { isAllowHold = true; // 以下、変更なし } } |
これでホールドを使用すると設置されるまで使用することができなくなります。
またゲーム開始時に設定を初期化する必要があります。
|
public partial class Form1 : Form { void GameStart() { isAllowHold = true; holdTetoro = TetoroTypes.None; pictureBoxHold.Image = null; pictureBoxHold.BackColor = ClearColor; // 以下、変更なし } } |
鳩でも分かるC#管理人からのお願い
できる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。
⇒ 仕事を依頼する
コメントについて
コメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。
Some people make comments in foreign languages such as English, but since the manager does not understand anything other than Japanese, he basically cannot understand the content and does not approve it. Please use Japanese when making comments.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト