using System;
using System.Collections .Generic ;
using System.ComponentModel ;
using System.Data ;
using System.Drawing ;
using System.Linq ;
using System.Text ;
using System.Windows .Forms ;
using System.Threading ;
namespace TetrisCS
{
public partial class Form1 : Form
{
const int blockCol = 10 ;
const int blockRow = 20 ;
const int blockSize = 32 ;
int [ , ] board = new Int32[ 11 , 21 ] ;
System.Windows .Forms .Timer timer1 = new System.Windows .Forms .Timer ( ) ;
public class Block
{
public int x, y;
public Block( int _x, int _y)
{
x = _x; y = _y;
}
}
Block[ ] [ ] block = new Block[ ] [ ] { new Block[ ] { new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 4 , 2 ) , new Block( 4 , 3 ) } , // 棒
new Block[ ] { new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 4 , 2 ) , new Block( 5 , 2 ) } , // L
new Block[ ] { new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 4 , 2 ) , new Block( 3 , 2 ) } , // 逆L
new Block[ ] { new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 5 , 0 ) , new Block( 5 , 1 ) } , // 正方形
new Block[ ] { new Block( 3 , 1 ) , new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 5 , 0 ) } , // S
new Block[ ] { new Block( 3 , 1 ) , new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 5 , 1 ) } , // 凸
new Block[ ] { new Block( 3 , 0 ) , new Block( 4 , 0 ) , new Block( 4 , 1 ) , new Block( 5 , 1 ) } , // Z
} ;
public Form1( )
{
InitializeComponent( ) ;
Load += Form1_Load;
Shown += Form1_Shown;
KeyDown += Form1_KeyDown;
FormBorderStyle = FormBorderStyle.Fixed3D ;
BackColor = Color.Black ;
//
var timer1 = new System.Windows .Forms .Timer ( ) ;
timer1.Interval = 500 ;
timer1.Tick += Timer1_Tick;
timer1.Enabled = true ;
}
void Form1_KeyDown( object sender, KeyEventArgs e)
{
if ( e.KeyCode == Keys.Left )
MoveBlock( - 1 ) ;
else if ( e.KeyCode == Keys.Right )
MoveBlock( 1 ) ;
}
void Timer1_Tick( object sender, EventArgs e)
{
BoardEdit( ) ;
}
void Form1_Load( object sender, EventArgs e)
{
ClientSize = new Size( blockCol * blockSize, blockRow * blockSize) ;
timer1.Start ( ) ;
}
void Form1_Shown( object sender, EventArgs e)
{
CreateBlock( ) ;
}
void MoveBlock( int xOffset)
{
if ( xOffset == - 1 )
{
for ( int i = 0 ; i < blockCol; i++ )
{
for ( int j = 0 ; j < blockRow; j++ )
{
if ( board[ i, j] == 1 && 0 <= ( i - 1 ) )
{
board[ i, j] = 0 ;
board[ i- 1 , j] = 1 ;
}
}
}
}
else if ( xOffset == 1 )
{
for ( int i = blockCol - 1 ; i >= 0 ; i-- )
{
for ( int j = blockRow - 1 ; j >= 0 ; j-- )
{
if ( board[ i, j] == 1 && i < blockCol - 1 )
{
board[ i, j] = 0 ;
board[ i+ 1 , j] = 1 ;
}
}
}
}
}
void CreateBlock( )
{
int seed = ( DateTime.Now .Second + 20 ) % 8 ;
for ( int i = 0 ; i < 4 ; i++ )
{
board[ block[ seed] [ i] .x , block[ seed] [ i] .y ] = 1 ;
}
DrawBoard( ) ;
}
void BlockFixed( )
{
for ( int i = 0 ; i < blockCol; i++ )
{
for ( int j = 0 ; j < blockRow; j++ )
{
if ( board[ i, j] == 1 )
{
board[ i, j] = 2 ;
}
}
}
// ブロックが固定された場合、新たなブロックが出現
CreateBlock( ) ;
}
void PutBlock( )
{
for ( int i = 0 ; i < blockCol; i++ )
{
for ( int j = 0 ; j < blockRow; j++ )
{
if ( board[ i, j] == 1 )
board[ i, j] = 2 ;
}
}
CreateBlock( ) ;
}
void BoardEdit( )
{
// 1段下げる処理
for ( int i = blockCol - 1 ; i >= 0 ; i-- )
{
for ( int j = blockRow - 1 ; j >= 0 ; j-- )
{
if ( board[ i, j] == 1 )
{
board[ i, j] = 0 ;
board[ i, j + 1 ] = 1 ;
}
}
}
// 固定処理
for ( int i = 0 ; i < blockCol; i++ )
{
for ( int j = 0 ; j < blockRow; j++ )
{
// 底に着いた場合、固定
if ( board[ i, j] == 1 && j == 19 )
PutBlock( ) ;
// 下に固定済みのブロックがあった場合、固定
if ( board[ i, j] == 1 && (
board[ i+ 1 , j] == 2 ||
board[ i, j+ 1 ] == 2 ) )
{
PutBlock( ) ;
}
}
}
// ライン成立で消す処理
for ( int i = 0 ; i < blockRow; i++ )
{
int c = 0 ;
for ( int j = 0 ; j < blockCol; j++ )
{
if ( board[ j, i] == 2 )
c++;
}
// 固定されたブロックが10個あった場合ライン成立
if ( c == 10 )
{
for ( int j = 0 ; j < blockCol; j++ )
{
board[ j, i] = 0 ;
}
}
}
DrawBoard( ) ;
}
void DrawBoard( )
{
Graphics g = this.CreateGraphics ( ) ;
g.Clear ( Color.Black ) ;
for ( int i = 0 ; i < blockCol; i++ )
{
for ( int j = 0 ; j < blockRow; j++ )
{
if ( board[ i, j] == 1 )
g.FillRectangle ( Brushes.Pink , i * blockSize, j * blockSize, blockSize, blockSize) ;
if ( board[ i, j] == 2 )
g.FillRectangle ( Brushes.Gray , i * blockSize, j * blockSize, blockSize, blockSize) ;
}
}
//
for ( int i = 0 ; i <= blockCol; i++ )
{
g.DrawLine ( new Pen( Color.Black , 2 ) , blockSize * i, 0 , blockSize * i, blockRow * blockSize) ;
}
for ( int i = 0 ; i <= blockRow; i++ )
{
g.DrawLine ( new Pen( Color.Black , 2 ) , 0 , blockSize * i, blockCol * blockSize, blockSize * i) ;
}
g.Dispose ( ) ;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkNvbXBvbmVudE1vZGVsOwp1c2luZyBTeXN0ZW0uRGF0YTsKdXNpbmcgU3lzdGVtLkRyYXdpbmc7CnVzaW5nIFN5c3RlbS5MaW5xOwp1c2luZyBTeXN0ZW0uVGV4dDsKdXNpbmcgU3lzdGVtLldpbmRvd3MuRm9ybXM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmc7CgpuYW1lc3BhY2UgVGV0cmlzQ1MKewogICAgcHVibGljIHBhcnRpYWwgY2xhc3MgRm9ybTEgOiBGb3JtCiAgICB7CiAgICAgICAgY29uc3QgaW50IGJsb2NrQ29sID0gMTA7CiAgICAgICAgY29uc3QgaW50IGJsb2NrUm93ID0gMjA7CiAgICAgICAgY29uc3QgaW50IGJsb2NrU2l6ZSA9IDMyOwoKICAgICAgICBpbnRbLF0gYm9hcmQgPSBuZXcgSW50MzJbMTEsMjFdOwoKICAgICAgICBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5UaW1lciB0aW1lcjEgPSBuZXcgU3lzdGVtLldpbmRvd3MuRm9ybXMuVGltZXIoKTsKICAgICAKICAgICAgICBwdWJsaWMgY2xhc3MgQmxvY2sKICAgICAgICB7CiAgICAgICAgICAgIHB1YmxpYyBpbnQgeCwgeTsKCiAgICAgICAgICAgIHB1YmxpYyBCbG9jayhpbnQgX3gsIGludCBfeSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgeCA9IF94OyB5ID0gX3k7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIEJsb2NrW11bXSBibG9jayA9IG5ldyBCbG9ja1tdW10geyAgIG5ldyBCbG9ja1tdIHsgbmV3IEJsb2NrKDQsIDApLCBuZXcgQmxvY2soNCwgMSksIG5ldyBCbG9jayg0LCAyKSwgbmV3IEJsb2NrKDQsIDMpIH0sIC8vIOajkgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBCbG9ja1tdIHsgbmV3IEJsb2NrKDQsIDApLCBuZXcgQmxvY2soNCwgMSksIG5ldyBCbG9jayg0LCAyKSwgbmV3IEJsb2NrKDUsIDIpIH0sIC8vIEwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgQmxvY2tbXSB7IG5ldyBCbG9jayg0LCAwKSwgbmV3IEJsb2NrKDQsIDEpLCBuZXcgQmxvY2soNCwgMiksIG5ldyBCbG9jaygzLCAyKSB9LCAvLyDpgIZMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEJsb2NrW10geyBuZXcgQmxvY2soNCwgMCksIG5ldyBCbG9jayg0LCAxKSwgbmV3IEJsb2NrKDUsIDApLCBuZXcgQmxvY2soNSwgMSkgfSwgLy8g5q2j5pa55b2iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEJsb2NrW10geyBuZXcgQmxvY2soMywgMSksIG5ldyBCbG9jayg0LCAwKSwgbmV3IEJsb2NrKDQsIDEpLCBuZXcgQmxvY2soNSwgMCkgfSwgLy8gUwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBCbG9ja1tdIHsgbmV3IEJsb2NrKDMsIDEpLCBuZXcgQmxvY2soNCwgMCksIG5ldyBCbG9jayg0LCAxKSwgbmV3IEJsb2NrKDUsIDEpIH0sIC8vIOWHuAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBCbG9ja1tdIHsgbmV3IEJsb2NrKDMsIDApLCBuZXcgQmxvY2soNCwgMCksIG5ldyBCbG9jayg0LCAxKSwgbmV3IEJsb2NrKDUsIDEpIH0sIC8vIFoKICAgICAgICB9OwoKICAgICAgICBwdWJsaWMgRm9ybTEoKQogICAgICAgIHsKICAgICAgICAgICAgSW5pdGlhbGl6ZUNvbXBvbmVudCgpOwoKICAgICAgICAgICAgTG9hZCArPSBGb3JtMV9Mb2FkOwogICAgICAgICAgICBTaG93biArPSBGb3JtMV9TaG93bjsKICAgICAgICAgICAgS2V5RG93biArPSBGb3JtMV9LZXlEb3duOwogICAgICAgICAgICBGb3JtQm9yZGVyU3R5bGUgPSBGb3JtQm9yZGVyU3R5bGUuRml4ZWQzRDsKICAgICAgICAgICAgQmFja0NvbG9yID0gQ29sb3IuQmxhY2s7CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyAKICAgICAgICAgICAgdmFyIHRpbWVyMSA9IG5ldyBTeXN0ZW0uV2luZG93cy5Gb3Jtcy5UaW1lcigpOwogICAgICAgICAgICB0aW1lcjEuSW50ZXJ2YWwgPSA1MDA7CiAgICAgICAgICAgIHRpbWVyMS5UaWNrICs9IFRpbWVyMV9UaWNrOwogICAgICAgICAgICB0aW1lcjEuRW5hYmxlZCA9IHRydWU7CgogICAgICAgIH0KCiAgICAgICAgdm9pZCBGb3JtMV9LZXlEb3duKG9iamVjdCBzZW5kZXIsIEtleUV2ZW50QXJncyBlKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGUuS2V5Q29kZSA9PSBLZXlzLkxlZnQpCiAgICAgICAgICAgICAgICBNb3ZlQmxvY2soLTEpOwogICAgICAgICAgICBlbHNlIGlmIChlLktleUNvZGUgPT0gS2V5cy5SaWdodCkKICAgICAgICAgICAgICAgIE1vdmVCbG9jaygxKTsKCiAgICAgICAgfQoKICAgICAgICB2b2lkIFRpbWVyMV9UaWNrKG9iamVjdCBzZW5kZXIsIEV2ZW50QXJncyBlKQogICAgICAgIHsKICAgICAgICAgICAgCiAgICAgICAgICAgIEJvYXJkRWRpdCgpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBGb3JtMV9Mb2FkKG9iamVjdCBzZW5kZXIsIEV2ZW50QXJncyBlKQogICAgICAgIHsKICAgICAgICAgICAgQ2xpZW50U2l6ZSA9IG5ldyBTaXplKGJsb2NrQ29sICogYmxvY2tTaXplLCBibG9ja1JvdyAqIGJsb2NrU2l6ZSk7CiAgICAgICAgICAgIHRpbWVyMS5TdGFydCgpOwogICAgICAgICAgICAKICAgICAgICB9CgogICAgICAgIHZvaWQgRm9ybTFfU2hvd24ob2JqZWN0IHNlbmRlciwgRXZlbnRBcmdzIGUpCiAgICAgICAgewogICAgICAgICAgICBDcmVhdGVCbG9jaygpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBNb3ZlQmxvY2soaW50IHhPZmZzZXQpCiAgICAgICAgewogICAgICAgICAgICBpZiAoeE9mZnNldCA9PSAtMSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBibG9ja0NvbDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgYmxvY2tSb3c7IGorKykKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChib2FyZFtpLCBqXSA9PSAxICYmIDAgPD0gKGkgLSAxKSkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaSwgal0gPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaS0xLCBqXSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoeE9mZnNldCA9PSAxKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gYmxvY2tDb2wgLSAxOyBpID49IDA7IGktLSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBqID0gYmxvY2tSb3cgLSAxOyBqID49IDA7IGotLSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChib2FyZFtpLCBqXSA9PSAxICYmIGkgPCBibG9ja0NvbCAtIDEpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvYXJkW2ksIGpdID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvYXJkW2krMSwgal0gPSAxOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2b2lkIENyZWF0ZUJsb2NrKCkKICAgICAgICB7CiAgICAgICAgICAgIGludCBzZWVkID0gKERhdGVUaW1lLk5vdy5TZWNvbmQgKyAyMCkgJSA4OwoKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCA0OyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGJvYXJkW2Jsb2NrW3NlZWRdW2ldLngsIGJsb2NrW3NlZWRdW2ldLnldID0gMTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgRHJhd0JvYXJkKCk7CiAgICAgICAgfQoKICAgICAgICB2b2lkIEJsb2NrRml4ZWQoKQogICAgICAgIHsKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBibG9ja0NvbDsgaSsrKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IGJsb2NrUm93OyBqKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJvYXJkW2ksIGpdID09IDEpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBib2FyZFtpLCBqXSA9IDI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIOODluODreODg+OCr+OBjOWbuuWumuOBleOCjOOBn+WgtOWQiOOAgeaWsOOBn+OBquODluODreODg+OCr+OBjOWHuuePvgogICAgICAgICAgICBDcmVhdGVCbG9jaygpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBQdXRCbG9jaygpCiAgICAgICAgewogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGJsb2NrQ29sOyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgYmxvY2tSb3c7IGorKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoYm9hcmRbaSwgal0gPT0gMSkKICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaSwgal0gPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBDcmVhdGVCbG9jaygpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBCb2FyZEVkaXQoKQogICAgICAgIHsKICAgICAgICAgICAgLy8gMeauteS4i+OBkuOCi+WHpueQhgogICAgICAgICAgICBmb3IgKGludCBpID0gYmxvY2tDb2wgLSAxOyBpID49IDA7IGktLSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZm9yIChpbnQgaiA9IGJsb2NrUm93IC0xOyBqID49IDA7IGotLSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoYm9hcmRbaSwgal0gPT0gMSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJvYXJkW2ksIGpdID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaSwgaiArMV0gPSAxOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8g5Zu65a6a5Yem55CGCiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgYmxvY2tDb2w7IGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBibG9ja1JvdzsgaisrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vIOW6leOBq+edgOOBhOOBn+WgtOWQiOOAgeWbuuWumgogICAgICAgICAgICAgICAgICAgIGlmIChib2FyZFtpLCBqXSA9PSAxICYmIGogPT0gMTkpCiAgICAgICAgICAgICAgICAgICAgICAgIFB1dEJsb2NrKCk7CgogICAgICAgICAgICAgICAgICAgIC8vIOS4i+OBq+WbuuWumua4iOOBv+OBruODluODreODg+OCr+OBjOOBguOBo+OBn+WgtOWQiOOAgeWbuuWumgogICAgICAgICAgICAgICAgICAgIGlmIChib2FyZFtpLCBqXSA9PSAxICYmICgKICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaSsxLGpdPT0gMiB8fAogICAgICAgICAgICAgICAgICAgICAgICBib2FyZFtpLGorMV09PSAyICkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBQdXRCbG9jaygpOwogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIOODqeOCpOODs+aIkOeri+OBp+a2iOOBmeWHpueQhgogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGJsb2NrUm93OyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGludCBjID0gMDsKCiAgICAgICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IGJsb2NrQ29sOyBqKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJvYXJkW2osaV0gPT0gMikKICAgICAgICAgICAgICAgICAgICAgICAgYysrOyAgICAgICAgICAKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyDlm7rlrprjgZXjgozjgZ/jg5bjg63jg4Pjgq/jgYwxMOWAi+OBguOBo+OBn+WgtOWQiOODqeOCpOODs+aIkOeriwogICAgICAgICAgICAgICAgaWYgKGMgPT0gMTApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBibG9ja0NvbDsgaisrKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgYm9hcmRbaiwgaV0gPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgRHJhd0JvYXJkKCk7CiAgICAgICAgfQoKICAgICAgICB2b2lkIERyYXdCb2FyZCgpCiAgICAgICAgewogICAgICAgICAgICBHcmFwaGljcyBnID0gdGhpcy5DcmVhdGVHcmFwaGljcygpOwoKICAgICAgICAgICAgZy5DbGVhcihDb2xvci5CbGFjayk7CgogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGJsb2NrQ29sOyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgYmxvY2tSb3c7IGorKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoYm9hcmRbaSwgal0gPT0gMSkKICAgICAgICAgICAgICAgICAgICAgICAgZy5GaWxsUmVjdGFuZ2xlKEJydXNoZXMuUGluaywgaSAqIGJsb2NrU2l6ZSwgaiAqIGJsb2NrU2l6ZSwgYmxvY2tTaXplLCBibG9ja1NpemUpOwogICAgICAgICAgICAgICAgICAgIGlmIChib2FyZFtpLCBqXSA9PSAyKQogICAgICAgICAgICAgICAgICAgICAgICBnLkZpbGxSZWN0YW5nbGUoQnJ1c2hlcy5HcmF5LCBpICogYmxvY2tTaXplLCBqICogYmxvY2tTaXplLCBibG9ja1NpemUsIGJsb2NrU2l6ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIAoKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPD0gYmxvY2tDb2w7IGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZy5EcmF3TGluZShuZXcgUGVuKENvbG9yLkJsYWNrLCAyKSwgYmxvY2tTaXplICogaSwgMCwgYmxvY2tTaXplICogaSwgYmxvY2tSb3cgKiBibG9ja1NpemUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDw9IGJsb2NrUm93OyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGcuRHJhd0xpbmUobmV3IFBlbihDb2xvci5CbGFjaywgMiksIDAsYmxvY2tTaXplICogaSwgIGJsb2NrQ29sICogYmxvY2tTaXplLGJsb2NrU2l6ZSAqIGkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBnLkRpc3Bvc2UoKTsKICAgICAgICB9CiAgICB9Cn0K