using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
namespace tetris_test1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
image = Image.FromFile("tetrisBlock3 198 22.bmp");
PutStartPos();
}
Image image;
const int nColor = 9;
const int width = 10;
const int height = 20;
readonly Point start_pos = new Point(4, 1);
int[,] screen = new int[width, height];
Block block;
Point pos;
int rot;
int score = 0;
const int fall_cycle = 10;
int fall_cnt = 0;
bool rot_stop;
class Block
{
public Point[,] sq; // sq[i, j]は回転パターンiのj個目の四角の位置
public int color; // 黒、水、黄、青、赤、橙、緑、紫
public Block(Point[] sq, int n, int color)
{ // nは回転パターンの数
this.sq = new Point[n, 4];
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < 4; ++j) this.sq[i, j] = sq[j];
for (int j = 0; j < 4; ++j) sq[j] = RotateSq(sq[j]);
}
this.color = color;
}
private Point RotateSq(Point sq) { return new Point(sq.Y, -sq.X); }
}
readonly Block[] blocks = new Block[] {
new Block(new Point[] { new Point(-1, 0), new Point(0, 0), new Point(1, 0), new Point(2, 0) }, 2, 7), // I
new Block(new Point[] { new Point(0, -1), new Point(1, -1), new Point(0, 0), new Point(1, 0) }, 1, 2), // 四角
new Block(new Point[] { new Point(-1, -1), new Point(-1, 0), new Point(0, 0), new Point(1, 0) }, 4, 5), // J
new Block(new Point[] { new Point(-1, 0), new Point(0, 0), new Point(0, 1), new Point(1, 1) }, 2, 1), // Z
new Block(new Point[] { new Point(-1, 0), new Point(0, 0), new Point(1, 0), new Point(1, -1) }, 4, 6), // L
new Block(new Point[] { new Point(-1, 1), new Point(0, 1), new Point(0, 0), new Point(1, 0) }, 2, 4), // S
new Block(new Point[] { new Point(-1, 0), new Point(0, 0), new Point(1, 0), new Point(0, -1) }, 4, 3), // T
};
private void Form1_Paint(object sender, PaintEventArgs e)
{
const int length = 22;
var srcRect = new Rectangle[nColor];
var destRect = new Rectangle[width, height];
for (int i = 0; i < nColor; ++i) srcRect[i] = new Rectangle(i * length, 0, length, length);
for (int j = 0; j < height; ++j) for (int i = 0; i < width; ++i) destRect[i, j] = new Rectangle(i * length, j * length, length, length);
for (int j = 0; j < height; ++j) for (int i = 0; i < width; ++i) e.Graphics.DrawImage(image, destRect[i, j], srcRect[screen[i, j]], GraphicsUnit.Pixel);
}
private void timer1_Tick(object sender, EventArgs e)
{
Point next_pos;
int next_rot;
GetNextPosRot(out next_pos, out next_rot);
ReviseScreen(next_pos, next_rot);
}
void GetNextPosRot(out Point next_pos, out int next_rot)
{
next_pos = new Point(pos.X, pos.Y);
next_rot = rot;
if ((fall_cnt = (fall_cnt + 1) % fall_cycle) == 0) next_pos.Y += 1; // 自然落下
else if (Keyboard.IsKeyDown(Key.Up)) { if (!rot_stop) next_rot = (next_rot + 1) % block.sq.GetLength(0); }
else if (Keyboard.IsKeyDown(Key.Down)) next_pos.Y += 1;
else if (Keyboard.IsKeyDown(Key.Right)) next_pos.X += 1;
else if (Keyboard.IsKeyDown(Key.Left)) next_pos.X -= 1;
// 連続して回らないようにする
if (Keyboard.IsKeyDown(Key.Up)) rot_stop = true;
else rot_stop = false;
}
void ReviseScreen(Point next_pos, int next_rot)
{
Point[] sqs, next_sqs;
GetSqs(block, pos, rot, out sqs);
PutSqs(sqs, 0);
if (GetSqs(block, next_pos, next_rot, out next_sqs))
{
PutSqs(next_sqs, block.color);
pos = next_pos;
rot = next_rot;
}
else
{
PutSqs(sqs, block.color);
if (next_pos.Y == pos.Y + 1)
{
DeleteLine();
label1.Text = Convert.ToString(score);
PutStartPos();
if (!GetSqs(block, pos, rot, out sqs))
{
PutSqs(sqs, block.color);
GameOver();
}
}
}
Invalidate();
}
private void PutStartPos()
{
pos = start_pos;
block = blocks[(new Random()).Next(0, blocks.Length)];
rot = (new Random()).Next(0, block.sq.GetLength(0));
}
private bool GetSqs(Block block, Point pos, int rot, out Point[] sqs)
{
bool overlap = false;
sqs = new Point[block.sq.GetLength(1)];
for (int i = 0; i < sqs.Length; ++i)
{
var p = new Point(pos.X + block.sq[rot, i].X, pos.Y + block.sq[rot, i].Y);
overlap |= p.X < 0 || p.X >= screen.GetLength(0) || p.Y < 0 || p.Y >= screen.GetLength(1) || screen[p.X, p.Y] != 0;
sqs[i] = p;
}
return !overlap;
}
private void PutSqs(Point[] sqs, int color)
{
foreach (var sq in sqs) screen[sq.X, sq.Y] = color;
}
private void GameOver()
{
for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) if (screen[i, j] != 0) screen[i, j] = 8;
timer1.Enabled = false;
}
int DeleteLine()
{
int sum = 0;
var delCount = 0;
for (int j = 0; j < height; ++j)
{
bool delete = true;
for (int i = 0; i < width; ++i)
if (screen[i, j] == 0)
delete = false;
if (delete)
{
for (int k = j; k >= 1; --k)
for (int i = 0; i < width; ++i)
screen[i, k] = screen[i, k - 1];
delCount++;
}
}
if (delCount == 4)
sum = 1200;
if (delCount == 3)
sum = 300;
if (delCount == 2)
sum = 100;
if (delCount == 1)
sum = 40;
score = score + sum;
return score;
}
}
}
自分で試行錯誤やってみたのですが、なかなかうまくいきません。
ちょっとしたアドバイスでも良いので教えて頂けると幸いです。よろしくお願いします。