Tetris on C # in 100 lines

 
3r3-31. Recently I had an idea - to write a simple game in the minimum number of lines. My choice fell on Tetris. In this article I will describe my code.
 
 
To begin with, it is worth noting that in my implementation I included only the basic features: 3r3333368.  
 
 
movement of figures left /right;
 
the fall of the figures;
 
turn figures;
 
deleting filled figures;
 
ending the game.
 
 
So, first add a PictureBox to the form and create a timer.
 
 
Also, the game will need:
 
 
public const int width = 1? height = 2? k = 15; //Size of the field and size of the cell in pixels
public int[,]shape = new int[2, 4]; //Array for storing the falling figure (for each block 2 coordinates are[0, i]And[1, i]
Public int[,]Field = new int[width, height]; //Array to store the field
Public Bitmap bitfield = new Bitmap (k * (width + 1) + ? k * (height + 3) + 1);
Public Graphics gr; //To draw a field on the PictureBox 3r33382.
3rr3359. 3r33368.  
Fill in the margin:
 
 
for (int i = 0; i < width; i++)
field[i, height - 1]= 1;
for (int i = 0; i < height; i++) {
field[0, i]= 1;
field[width - 1, i]= 1;
}

 
Fill the shape:
 
 
public void SetShape () {
Random x = new Random (DateTime.Now.Millisecond);
switch (x.Next (7)) {//Randomly choose 1 out of 7 possible figures 3r33382. case 0: shape = new int[,]{{? ? ? 5}, {? ? ? 8}}; break;
case 1: shape = new int[,]{{? ? ? 3}, {? ? ? 9}}; break;
case 2: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
case 3: shape = new int[,]{{? ? ? 4}, {? ? ? 7}}; break;
case 4: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
case 5: shape = new int[,]{{? ? ? 4}, {? ? ? 7}}; break;
case 6: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
}
}

 
The procedure that draws a “glass” in PictureBox:
 
 
public void FillField () {
gr.Clear (Color.Black); //Clear the field
for (int i = 0; i < width; i++)
for (int j = 0; j 3r33272. if (field[i, j]== 1) {//If the cell of the field exists
gr.FillRectangle (Brushes.Green, i * k, j * k, k, k); //Draw a small square in this place,
gr.DrawRectangle (Pens.Black, i * k, j * k, k, k);
} 3rr3382. for (int i = 0 ; i < 4; i++){ //Рисуем падающую фигуру
gr.FillRectangle (Brushes.Red, shape[1, i]* k, shape[0, i]* k, k, k);
gr.DrawRectangle (Pens.Black, shape[1, i]* k, shape[0, i]* k , k, k);
}
FieldPictureBox.Image = bitfield;
}
3r33358. 3rr3359. 3r3368.  
I first move the figures, and then check whether such an option is possible or not. If there is an error in some place (the figure has gone beyond the bounds of the field or superimposed on the figure already lying in the field), the figure returns to its previous place. For this, I wrote a function that returns true if there was an error on the field or false if there is no error: 3r33333.  
 
public bool FindMistake () {
for (int i = 0; i < 4; i++)
if (shape[1, i]> = width || shape[0, i]> = height ||
shape[1, i]<= 0 || shape[0, i]<= 0 ||
field[shape[1, i]., shape[0, i]]== 1)
return true;
return false;
}
3r3r588. 3r33359. 3rr3368.  
Now proceed to the movement of the figures. Create a KeyDown event in the constructor.
 
 
Move left:
 
 
switch (e.KeyCode) {
case Keys.A:
for (int i = 0; i < 4; i++)
shape[1, i]-; //First we shift the coordinates of all the pieces of the figure 1 left on the axis OX
if (FindMistake ()) //If after that an error
for (int i = 0; i 3r33286. shape[1, i]++; //Return the figure back 1 to the right
break;
} 3r33333. 3r3358. 3r33359. 3r3333368.  
Similarly, moving right:
 
 
case Keys.D:
for (int i = 0; i < 4; i++)
shape[1, i]++;
if (FindMistake ())
for (int i = 0; i 3r33r. 3349. shape[1, i]-;
break; 3r33382.
-;
break; 3r33382.
-;
break; 3r33382.
-;
break; 3r33382.
-;
break; 3r33382.
 
The flipping of the figure is a little more complicated: 3r3333368.  
 
case Keys.W:
var shapeT = new int[2, 4];
Array.Copy (shape, shapeT, shape.Length); //Create a copy of the figure, so that if there is an error on the field after the coup, do not turn it back, but simply restore the copy 3r3382. int maxx = ? maxy = 0;
for (int i = 0; i < 4; i++){
if (shape[0, i]> maxy)
maxy = shape[0, i];
if (shape[1, i]> maxx) 3rr3382. maxx = shape[1, i]; 3rrn33r33r.???. The maximum coordinates of the figure's value are in X and Y. . = maxx - (3 - (maxy - temp)) + 1;
} //Turn the figure. I found these formulas after careful study of the drawn square with the figure before and after the coup.
if (FindMistake ()) 3r38282.Array.Copy (shapeT, shape, shape.Length); 3r3333382 break;
3r33333.
3r3333368  
Now it remains only to add a drop of figures and the removal of lines. All this will happen at the TimerTick event:
 
 
private void TickTimer_Tick (object sender, System.EventArgs e) {
if (field[8, 3]== 1)
Environment.Exit (0); //If the cell of the field where the figures appear on, complete the program.
for (int i = 0; i 3r3r-3286. shape[0, i]++; //Move the figure down
if (FindMistake ()) {
for (int i = 0; i 3rr3349. field[shape[1, i], --shape[0, i].]++;
SetShape ();
} //If an error was found, move the figure up 1 cell, save it to the field array and create a new figure 3r3382. For (int i = height - 2; i> 2 ; i -) {
var cross = (from t in Enumerable.Range (? field.GetLength (0)). Select (j => field[j, i]) .ToArray () where t == 1 select t) .Count (); //Number of filled fields in the row
If (cross == width)
For (int k = i; k> 1; k--) 3r33382. For (int l = 1; l < width - 1; l++)
field[l, k]= field[l, k - 1];
} //Checking for fullness with a row, if there are rows in which all cells are filled, move all rows that are above the harvested line 1 down
FillField (); //Redraw the field
}

 
Finally, when creating a form, you need to call: 3r3333368.  
 
SetShape ();

 
The resulting code:
 
 
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
namespace LittleTetris {
public partial class Form1: Form {
public const int width = 1? height = 2? k = 15;
public int[,]shape = new int[2, 4];
public int[,]field = new int[width, height];
public Bitmap bitfield = new Bitmap (k * (width + 1) + ? k * (height + 3) + 1);
public Graphics gr;
public Form1 () {
InitializeComponent ();
gr = Graphics.FromImage (bitfield);
for (int i = 0; i 3-3r3271. field[i, height - 1]= 1;
for (int i = 0; i < height; i++) {
field[0, i]= 1; 3r3382. field[width - 1, i]= 1;
} 3r3333382. ;
}
Public void FillField () {
Gr.Clear (Color.Black);
For (int i = 0; i < width; i++)
For (int j = 0; j 3r33232. If) field ([i, j]== 1) {
Gr.FillRectangle (Brushes.Green, i * k, j * k, k, k);
Gr.DrawRectangle (Pens.Black, i * k, j * k, k, k) ;
}
For (int i = 0; i < 4; i++){
Gr.FillRectangle (Brushes.Red, shape[1, i]* K, shape[0, i]* K, k, k);
Gr.DrawRectangle (Pens.Black , shape[1, i]* k, shape[0, i]* k, k, k); 3r3382.} 3r3r???. FieldPictureBox.Image = bitfield;
}
private void TickTimer_Tick (object sender, System.EventArgs e) {
if (field[8, 3]== 1)
Environment.Exit (0);
for (int i = 0; i < 4; i++)
shape[0, i]++;
for (int i = height - 2; i> 2; i -) {
var cross = (from t in Enumerable.Range (0 , field.GetLength (0)). Select (j => field[j, i]) .ToArray () where t == 1 select t) .Count ();
if (cross == width)
for (int k = i; k> 1; k--)
  for (int l = 1; l < width - 1; l++)
field[l, k]= field[l, k - 1]; ++;
SetShape ();}
FillField ();
}
Private void Form1KeyDown (object sender, KeyEventArgs e) {
Switch (e.KeyCode) {3r3333382. for (int i = 0; i < 4; i++)
shape[1, i]-;
if (FindMistake ())
for (int i = 0; i 3rr3349. shape[1, i]++;
break; 3r33333. case Keys .D:
For (int i = 0; i < 4; i++)
Shape[1, i]++;
If (FindMistake ())
for (int i = 0; i < 4; i++)
shape[1, i]-;
break;
case Keys.W:
var shapeT = new int[2, 4];
Array.Copy (shape, shapeT, shape.Length);
int maxx = ? maxy = 0;
for (int i = 0; i < 4; i++){
if (shape[0, i]> maxy)
maxy = shape[0, i];
if (int i = 0; i 3r33232. int temp = shape[0, i];
shape[0, i]= maxy - (maxx - shape[1, i]) - 1;
shape[1, i]= maxx - (3 - (maxy - temp) + 1; 3r33382.} 3r33382. If (FindMistake ()) 3r33382. Array.Copy (shapeT, shape, shape.Length);
Break; 3r33382.}
}
Public void SetShape () {3r38233). Random x = new Random (DateTime.Now.Millisecond);
Switch (x.Next (7)) {
Case 0: shape = new int w2w2w 285. {{? ? ? 5}, {? ? ? 8}}; break;
case 1: shape = new int[,]{{? ? ? 3}, {? ? ? 9}}; break;
case 2: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
case 3: shape = new int[,]{{? ? ? 4}, {? ? ? 7}}; break;
case 4: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
case 5: shape = new int[,]{{? ? ? 4}, {? ? ? 7}}; break;
case 6: shape = new int[,]{{? ? ? 4}, {? ? ? 9}}; break;
}
}
public bool FindMistake () {
for (int i = 0; i < 4; i++)
if (shape[1, i]> = width || shape[0, i]> = height ||
shape[1, i]<= 0 || shape[0, i]<= 0 ||
field[shape[1, i]., shape[0, i]]== 1)
return true;
return false;
}
}
} 3r38282. 3r3588. 3r33359. 3r3333368.  
As a result, except for lines with a closing bracket and a painted condition in FindMistake, it turns out 95 lines.
 
 
Here is a screenshot of the running program:
 
 
Tetris on C # in 100 lines
+ 0 -

Add comment