完成品はこんな感じになります。
Contents
ぷよを落下させる
前回からはじまった「C#でぷよぷよもどきを作る」。前回はフィールドをつくるところをやりました。今回はぷよを落下させます。
まずゲームがはじまったら、新しいぷよを画面の上部に描画します。この処理をするのがCreateNewPuyoメソッドです。
ぷよは2つ組み合わさった状態でおちてきます。回転するときは一方を軸に回転するので、このぷよの位置を現在位置とします。これをフィールド変数puyoPositionXとpuyoPositionYに保存しておきます。
それからぷよにはいくつかの種類があります。ここでは4種類とします。乱数でどのようなタイプのぷよをつくるか決定し、それをフィールド変数に保存します。回転軸になるぷよのタイプを Puyo列挙型フィールド変数 DropingPuyoに、他方をSubDropingPuyoに保存します。
| 
					 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 GameStartMenuItem_Click(object sender, EventArgs e)     {         CreateNewPuyo();         //timer1.Start(); // 今はタイマーは使わない     }     void CreateNewPuyo()     {         PuyoAngle = Angle.Angle0;         int r = Random.Next(0, 4);         if(r == 0)             DropingPuyo = Puyo.Puyo1;         if(r == 1)             DropingPuyo = Puyo.Puyo2;         if(r == 2)             DropingPuyo = Puyo.Puyo3;         if(r == 3)             DropingPuyo = Puyo.Puyo4;         r = Random.Next(0, 4);         if(r == 0)             SubDropingPuyo = Puyo.Puyo1;         if(r == 1)             SubDropingPuyo = Puyo.Puyo2;         if(r == 2)             SubDropingPuyo = Puyo.Puyo3;         if(r == 3)             SubDropingPuyo = Puyo.Puyo4;         puyoPositionX = puyoStartPositionX;         puyoPositionY = puyoStartPositionY;         SetPuyo(puyoPositionX, puyoPositionY, DropingPuyo);         SetPuyo(puyoPositionX, puyoPositionY-1, SubDropingPuyo);         CheckGameOver(); // ゲームオーバーになっているかもしれない     } }  | 
					
ゲームオーバーの処理
それからゲームオーバーの処理も必要です(コメントで指摘されるまで気づかないって)。これを先にやっておきましょう。ゲームオーバーかどうかの判定はCreateNewPuyoメソッドを実行するときに新しいぷよが出てきたときにすでに別のぷよが設置されているかどうかで判断できます。
もしゲームオーバーであった場合はタイマーを止め、キー操作不能にします。またゲームをもう一度するときにはIsGameOver = falseに戻すとともに全セルを初期化します。
| 
					 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  | 
						public partial class Form1 : Form {     bool IsGameOver = true;     void CheckGameOver()     {         if (Cells[puyoPositionY, puyoPositionX].IsFixed)         {             timer1.Stop();             IsGameOver = true;             // ゲームオーバーであることがわかるような表示が必要かもしれない             // ラベルに「Game Over」と書いてIsGameOver = trueのときだけ表示させるとか・・・         }     }     private void GameStartMenuItem_Click(object sender, EventArgs e)     {         // ゲーム中にゲーム開始をクリックしてもなにもおきないようにする         // IsGameOverをfalseで初期化するとゲームを開始しようとしてもなにもおきなくなるので注意。         // これもコメントで指摘されてきづいた。いろいろお粗末すぎ         if (!IsGameOver)             return;         IsGameOver = false;         InitCells();         CreateNewPuyo();         //timer1.Start(); // 将来的にタイマーを使う     } }  | 
					
次にぷよを落下の処理ですが、タイマーをつかって一定時間の経過とともに下に移動させます。ただいまの段階では↓キーをおすと下に移動するようにします。またゲームオーバーの場合はキー操作をしてもなにもおきません。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						public partial class Form1 : Form {     private void Field_KeyDown(object sender, KeyEventArgs e)     {         if(IsGameOver)             return;         if(e.KeyCode == Keys.Left)             PuyoMoveLeftIfCan();         if(e.KeyCode == Keys.Right)             PuyoMoveRightIfCan();         if(e.KeyCode == Keys.Down)             PuyoMoveDownIfCan();         if(e.KeyCode == Keys.Space)             PuyoRotateIfCan();     } }  | 
					
ここでは下への移動だけを考えます。
PuyoMoveLeftIfCan()
PuyoMoveRightIfCan()
PuyoRotateIfCan()
これらはぷよを回転させる C#でぷよぷよもどきを作るを参照してください。
GetSubPuyoPositionメソッド
ぷよは二つで組になっていて、片方が回転軸になっています。回転軸ではないぷよの位置を取得するのがGetSubPuyoPositionメソッドです。
回転角度は「まったく回転していない」「時計回りに90度」「同180度」「同270度」のどれかです。回転軸になるぷよの位置と現在の回転角度がわかればもうひとつのぷよの位置も知ることができます。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  | 
						public partial class Form1 : Form {     Position GetSubPuyoPosition(int mainColun, int mainRow, Angle angle)     {         if(angle == Angle.Angle0)             return new Position(mainColun, mainRow - 1);         if(angle == Angle.Angle90)             return new Position(mainColun+1, mainRow);         if(angle == Angle.Angle180)             return new Position(mainColun, mainRow + 1);         if(angle == Angle.Angle270)             return new Position(mainColun-1, mainRow);         return null;     } }  | 
					
Positionクラスは以下のようになっています。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						public class Position {     public Position(int colum, int row)     {         Colum = colum;         Row = row;     }     public int Colum     {         get;         private set;     }     public int Row     {         get;         private set;     } }  | 
					
PuyoMoveDownIfCanメソッド
PuyoMoveDownIfCanメソッドは名前のとおり「もし可能であればぷよを下に移動させる」メソッドです。
考え方は現在の位置がフィールド変数として保存されているので、これを取得、そして実際に下に移動できるかどうかを確認します。下に移動できない場合として、ぷよが床に接触している、すでに設置されているぷよと重なってしまう場合が考えられます。
回転軸のぷよとそうでないほうのぷよ、両方とも下に移動できる場合のみが移動可能な状態です。
CanMoveDownメソッドがtrueを返した場合は、まだ下に移動させることができるので、ぷよの新しい位置を設定します。そしてFieldを再描画します。CanMoveDownメソッドがfalseを返した場合はこれ以上、下に移動することができないので設置の処理をおこないます。
CanMoveDownメソッド
| 
					 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  | 
						public partial class Form1 : Form {     void PuyoMoveDownIfCan()     {         int oldX = puyoPositionX;         int oldY = puyoPositionY;         Position subPosition = GetSubPuyoPosition(puyoPositionX, puyoPositionY, PuyoAngle);         int oldSubX = subPosition.Colum;         int oldSubY = subPosition.Row;         // 移動できるのか?         int newX = puyoPositionX;         int newY = puyoPositionY + 1;         int newSubX = oldSubX;         int newSubY = subPosition.Row + 1;         // 下げられないなら固定する         if(!CanMoveDown(new Position(newX, newY)) || !CanMoveDown(new Position(newSubX, newSubY)))         {             FixPuyo(oldX, oldY);             FixPuyo(oldSubX, oldSubY);             OnFixed();             return;         }         SetPuyo(oldX, oldY, Puyo.None);         SetPuyo(oldSubX, oldSubY, Puyo.None);         puyoPositionY = newY;         SetPuyo(puyoPositionX, puyoPositionY, DropingPuyo);         SetPuyo(newSubX, newSubY, SubDropingPuyo);     } }  | 
					
そして実際に下に移動できるかどうかを判定しているのがCanMoveDownメソッドです。ぷよがすでに床に接触している場合や設置されているぷよと重なってしまう場合は移動できないということになります。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13  | 
						public partial class Form1 : Form {     bool CanMoveDown(Position newPos)     {         if(             newPos.Row < 0 || newPos.Row > FIELD_HEIGHT - 2 ||             Cells[newPos.Row, newPos.Colum].IsFixed         )             return false;         else             return true;     } }  | 
					
FixPuyo(int colum, int row)はぷよを固定するためのものであり、OnFixed()は固定されたあとつながったぷよを消す、消えたあとできた空洞をうめる処理をおこなうメソッドです。この部分についてはぷよを消す C#でぷよぷよもどきを作るを参照してください。

Positionのクラス宣言がない
PuyoMoveLeftIfCan()
PuyoMoveRightIfCan()
PuyoRotateIfCan()
FixPuyo(oldX, oldY);
FixPuyo(oldSubX, oldSubY);
OnFixed();
上記6つのメソッドがない
以上ですかね。 おおいですが エラーでてまったくお手上げですので
すみませんが、おねがいします。
Positionのクラス宣言がない.
これはこちらのミスで記載忘れです。修正しておきました。
PuyoMoveLeftIfCan()
PuyoMoveRightIfCan()
PuyoRotateIfCan()
この3つは落下処理とは違うので別のページに書いてあります。
ぷよを回転させる C#でぷよぷよもどきを作るを参照してください。
それから
FixPuyo(oldX, oldY)
OnFixed()
は落下し終わったあとの処理なので
ぷよを消す C#でぷよぷよもどきを作るを参照してください。
メソッドだけ書いて定義はあとまわしにするという
非常にわかりにくい記事になってしまい申し訳ありません。