完成品はこんな感じになります。
VIDEO
ぷよを消すには?
以下はぷよを下に移動させるメソッドです。これ以上下には移動できない場合、ぷよを固定させることになりますが、テトリスとちがって下になにもない空間ができてはいけません。このようなとき、赤いぷよは切り離されて下に落ちます。
ではもう一度、PuyoMoveDownIfCanメソッドをみてみましょう。
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 ) ;
}
}
FixPuyoメソッドとOnFixedメソッド
これ以上、2つセットになった状態で下に移動できない場合はFixPuyoメソッドとOnFixedメソッドが呼び出されます。これは以下のような処理になっています。
FixPuyoメソッドは簡単です。セルのIsFixedプロパティにtrueをセットしているだけです。これで上から落ちてきた別のぷよが当たったときに当たり判定ができるようになります。
public partial class Form1 : Form
{
void FixPuyo ( int colum , int row )
{
Cells [ row , colum ] . IsFixed = true ;
}
}
OnFixedメソッドのなかでおこなわれる処理は以下のようなものです。
まず、ぷよが固定されたときにプヨの下に空洞があるか調べます。そして空洞がある場合はそれをうめるように上のぷよを下に下げます。
それから4つつながっているぷよがあったら消します。ぷよが消された結果、空洞ができるかもしれません。そこでさらに空洞をうめる処理をおこないます。するとまた連鎖がおきるかもしれないので、空洞がなくなるまで処理をくりかえします。
DownPuyoIfSpacesメソッドとDownPuyoIfSpaceメソッド
DownPuyoIfSpacesメソッドは空洞をうめるための処理をくりかえすためのものです。実際にぷよの直下に空洞があるかどうか調べて、あれば上にあるぷよを下に下げる処理をおこなうのはDownPuyoIfSpaceメソッドです。処理がおこなわれたときはtrueを返すので、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
31
32
33
34
35
36
37
38
39
40
41
42
43
public partial class Form1 : Form
{
async Task < bool > DownPuyoIfSpaces ( )
{
bool ret = false ;
// ぷよの直下に空洞がある限り、上のぷよを下に下げる
while ( DownPuyoIfSpace ( ) )
{
ret = true ;
// 一気に下げるのではなく1段ずつ0.1秒ごとに下げる
await Task . Delay ( 100 ) ;
}
return ret ;
}
bool DownPuyoIfSpace ( )
{
// 一度でも処理がおこなわれた場合はtrueを返す
bool ret = false ;
for ( int y = FIELD_HEIGHT - 3 ; y > = 0 ; y --)
{
for ( int x = 0 ; x < FIELD_WIDTH ; x ++)
{
if ( Cells [ y + 1 , x ] . Puyo == Puyo . None && Cells[y, x].Puyo != Puyo.None)
{
// 下に空間があるぷよは下に落とす
SetPuyo(x, y + 1, Cells[y, x].Puyo);
Cells [ y + 1 , x ] . IsFixed = Cells [ y , x ] . IsFixed ;
SetPuyo ( x , y , Puyo . None ) ;
Cells [ y , x ] . IsFixed = false ;
ret = true ;
}
}
}
if ( ret )
Field . Invalidate ( ) ;
return ret ;
}
}
それでは実際にぷよが固定されたときに呼び出されるOnFixedメソッドを示します。
処理中はキー操作ができないようにして、4つ以上つながっているプヨがあったら消して空洞ができたら上のぷよを移動させます。移動する必要がないぷよだけになったら処理は終了です。上から新しいぷよを降らせます。
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public partial class Form1 : Form
{
// 処理中はキー操作を無効にする
bool isIgnoreKeyDown = false ;
private void Field_KeyDown ( object sender , KeyEventArgs e )
{
if ( isIgnoreKeyDown )
return ;
// 落下しているぷよの操作
// 省略
}
async void OnFixed ( )
{
// 処理中はキー操作ができないようにする
isIgnoreKeyDown = true ;
// 設置されたプヨの下に空洞があれば上のプヨを落として空洞をうめる
Task < bool > task = DownPuyoIfSpaces ( ) ;
await task ;
// 4つつながっているプヨがあったら消す
for ( int i = 0 ; i < FIELD_HEIGHT ; i ++)
{
for ( int j = 0 ; j < FIELD_WIDTH ; j ++)
{
Cell cell = Cells [ i , j ] ;
List < Cell > cells = GetConectedCell ( cell ) ; // 後述
ClearCheck ( ) ;
if ( cells . Count > = 4 )
{
foreach ( Cell cell0 in cells )
cell0 . Puyo = Puyo . None ;
// プヨが消えたら空洞ができているかもしれない
Task < bool > task0 = DownPuyoIfSpaces ( ) ;
bool ret = await task0 ;
if ( ret )
{
i = 0 ;
j = 0 ;
}
}
}
}
isIgnoreKeyDown = false ;
// 処理が終わったら新しいぷよを降らせる
CreateNewPuyo ( ) ;
}
}
4つ以上つながっているプヨを探すために自作メソッド GetConectedCellを使用しています。再帰呼び出しをしているのですが、同じぷよを複数回数えないようにチェックをつけながら調べています。GetConectedCellメソッドが終わったらClearCheckメソッドでチェックをはずします。
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public partial class Form1 : Form
{
List < Cell > GetConectedCell ( Cell cell )
{
int colum = cell . Colum ;
int row = cell . Row ;
List < Cell > cells = new List < Cell > ( ) ;
if ( 0 < colum && colum < FIELD_WIDTH - 1 && 0 < row && row < FIELD_HEIGHT - 1)
{
Puyo puyo = Cells[row, colum].Puyo;
if ( puyo == Puyo . None | | puyo == Puyo . Wall )
return cells ;
if ( ! Cells [ row + 1 , colum ] . isChecked )
{
Cells [ row + 1 , colum ] . isChecked = true ;
if ( Cells [ row + 1 , colum ] . Puyo == puyo )
{
cells . Add ( Cells [ row + 1 , colum ] ) ;
cells . AddRange ( GetConectedCell ( Cells [ row + 1 , colum ] ) ) ;
}
}
if ( ! Cells [ row - 1 , colum ] . isChecked )
{
Cells [ row - 1 , colum ] . isChecked = true ;
if ( Cells [ row - 1 , colum ] . Puyo == puyo )
{
cells . Add ( Cells [ row - 1 , colum ] ) ;
cells . AddRange ( GetConectedCell ( Cells [ row - 1 , colum ] ) ) ;
}
}
if ( ! Cells [ row , colum + 1 ] . isChecked )
{
Cells [ row , colum + 1 ] . isChecked = true ;
if ( Cells [ row , colum + 1 ] . Puyo == puyo )
{
cells . Add ( Cells [ row , colum + 1 ] ) ;
cells . AddRange ( GetConectedCell ( Cells [ row , colum + 1 ] ) ) ;
}
}
if ( ! Cells [ row , colum - 1 ] . isChecked )
{
Cells [ row , colum - 1 ] . isChecked = true ;
if ( Cells [ row , colum - 1 ] . Puyo == puyo )
{
cells . Add ( Cells [ row , colum - 1 ] ) ;
cells . AddRange ( GetConectedCell ( Cells [ row , colum - 1 ] ) ) ;
}
}
}
return cells ;
}
void ClearCheck ( )
{
for ( int i = 0 ; i < FIELD_HEIGHT ; i ++)
{
for ( int j = 0 ; j < FIELD_WIDTH ; j ++)
{
Cell cell = Cells [ i , j ] ;
cell . isChecked = false ;
}
}
}
}
鳩でも分かる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.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト
エラーほとんどなくなったんですが、
すすめると2つエラーでてきました
すみませんが 下記の2つのメソッド教えてもらえませんか?
GetConectedCell(cell);
ClearCheck();
記事を修正、GetConectedCellメソッドとClearCheckメソッドを追加しました。