// AutoCAD用テトリスゲーム (C#)
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Threading;
[assembly: CommandClass(typeof(TetrisGame.TetrisCommands))]
namespace TetrisGame
{
public class TetrisCommands
{
private static bool gameOver = false;
private static int score = 0;
private static int[,] grid;
private static List<int[,]> currentShape;
private static int currentRotation = 0;
private static int shapeX = 0;
private static int shapeY = 0;
private static readonly int gridWidth = 10;
private static readonly int gridHeight = 20;
private static readonly int blockSize = 20;
private static readonly int startX = 100;
private static readonly int startY = 100;
private static List<List<int[,]>> shapes;
private static Database db;
private static Editor ed;
[CommandMethod("TETRIS")]
public void Tetris()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
db = doc.Database;
ed = doc.Editor;
try
{
InitializeGame();
DrawGrid();
SpawnNewShape();
DrawShape();
// ゲームループを別スレッドで実行
Thread gameThread = new Thread(GameLoop);
gameThread.Start();
// キーハンドリング
while (!gameOver)
{
PromptResult result = ed.GetKeywords("\n[← Left][→ Right][↓ Down][↑ Rotate][Space Drop]");
if (result.Status == PromptStatus.OK)
{
HandleInput(result.StringResult);
DrawShape();
}
}
ed.WriteMessage("\nGame Over! Final Score: " + score);
}
catch (System.Exception ex)
{
ed.WriteMessage("\nError: " + ex.Message);
}
}
private void InitializeGame()
{
gameOver = false;
score = 0;
grid = new int[gridWidth, gridHeight];
shapes = new List<List<int[,]>>();
// テトリミノの形状定義
// I
shapes.Add(new List<int[,]> {
new int[4,2] { {0,0}, {1,0}, {2,0}, {3,0} },
new int[4,2] { {0,0}, {0,1}, {0,2}, {0,3} }
});
// O
shapes.Add(new List<int[,]> {
new int[4,2] { {0,0}, {1,0}, {0,1}, {1,1} }
});
// T
shapes.Add(new List<int[,]> {
new int[4,2] { {0,0}, {1,0}, {2,0}, {1,1} },
new int[4,2] { {1,0}, {1,1}, {1,2}, {0,1} },
new int[4,2] { {0,1}, {1,1}, {2,1}, {1,0} },
new int[4,2] { {1,0}, {1,1}, {1,2}, {2,1} }
});
// 他の形状も同様に定義...
}
private void SpawnNewShape()
{
Random rand = new Random();
currentShape = shapes[rand.Next(shapes.Count)];
currentRotation = 0;
shapeX = gridWidth / 2;
shapeY = 0;
if (CheckCollision())
{
gameOver = true;
}
}
private bool CheckCollision()
{
int[,] shape = currentShape[currentRotation];
for (int i = 0; i
{
int x = shapeX + shape[i, 0];
int y = shapeY + shape[i, 1];
if (x < 0 || x >= gridWidth || y >= gridHeight || (y >= 0 && grid[x, y] != 0))
{
return true;
}
}
return false;
}
private void LockShape()
{
int[,] shape = currentShape[currentRotation];
for (int i = 0; i
{
int x = shapeX + shape[i, 0];
int y = shapeY + shape[i, 1];
if (y >= 0)
{
grid[x, y] = 1;
}
}
// ライン消去チェック
int linesCleared = 0;
for (int y = gridHeight - 1; y >= 0; y--)
{
bool lineFull = true;
for (int x = 0; x
{
if (grid[x, y] == 0)
{
lineFull = false;
break;
}
}
if (lineFull)
{
linesCleared++;
// ラインを消して上を下にずらす
for (int y2 = y; y2 > 0; y2--)
{
for (int x = 0; x
{
grid[x, y2] = grid[x, y2 - 1];
}
}
// 最上部をクリア
for (int x = 0; x
{
grid[x, 0] = 0;
}
y++; // 同じ行をもう一度チェック
}
}
// スコア更新
score += linesCleared * linesCleared * 100;
}
private void DrawGrid()
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// グリッドを描画
for (int x = 0; x <= gridWidth; x++)
{
Line line = new Line(
new Point3d(startX + x * blockSize, startY, 0),
new Point3d(startX + x * blockSize, startY + gridHeight * blockSize, 0));
btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
}
for (int y = 0; y <= gridHeight; y++)
{
Line line = new Line(
new Point3d(startX, startY + y * blockSize, 0),
new Point3d(startX + gridWidth * blockSize, startY + y * blockSize, 0));
btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
}
tr.Commit();
}
}
private void DrawShape()
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// 既存の形状を削除
foreach (ObjectId id in btr)
{
DBObject obj = tr.GetObject(id, OpenMode.ForRead);
if (obj is Solid && obj.Layer == "TETRIS")
{
obj.UpgradeOpen();
obj.Erase();
}
}
// 現在の形状を描画
int[,] shape = currentShape[currentRotation];
for (int i = 0; i
{
int x = shapeX + shape[i, 0];
int y = shapeY + shape[i, 1];
if (y >= 0)
{
Solid box = new Solid(
new Point3d(startX + x * blockSize, startY + y * blockSize, 0),
new Point3d(startX + (x + 1) * blockSize, startY + y * blockSize, 0),
new Point3d(startX + x * blockSize, startY + (y + 1) * blockSize, 0),
new Point3d(startX + (x + 1) * blockSize, startY + (y + 1) * blockSize, 0));
box.Layer = "TETRIS";
box.ColorIndex = 1; // Red
btr.AppendEntity(box);
tr.AddNewlyCreatedDBObject(box, true);
}
}
// 固定されたブロックを描画
for (int x = 0; x
{
for (int y = 0; y
{
if (grid[x, y] != 0)
{
Solid box = new Solid(
new Point3d(startX + x * blockSize, startY + y * blockSize, 0),
new Point3d(startX + (x + 1) * blockSize, startY + y * blockSize, 0),
new Point3d(startX + x * blockSize, startY + (y + 1) * blockSize, 0),
new Point3d(startX + (x + 1) * blockSize, startY + (y + 1) * blockSize, 0));
box.Layer = "TETRIS";
box.ColorIndex = 3; // Green
btr.AppendEntity(box);
tr.AddNewlyCreatedDBObject(box, true);
}
}
}
tr.Commit();
}
}
private void HandleInput(string input)
{
switch (input)
{
case "Left":
shapeX--;
if (CheckCollision()) shapeX++;
break;
case "Right":
shapeX++;
if (CheckCollision()) shapeX--;
break;
case "Down":
shapeY++;
if (CheckCollision()) shapeY--;
break;
case "Up":
currentRotation = (currentRotation + 1) % currentShape.Count;
if (CheckCollision()) currentRotation = (currentRotation - 1 + currentShape.Count) % currentShape.Count;
break;
case "Space":
while (!CheckCollision())
{
shapeY++;
}
shapeY--;
break;
}
}
private void GameLoop()
{
while (!gameOver)
{
Thread.Sleep(500); // 0.5秒ごとに更新
shapeY++;
if (CheckCollision())
{
shapeY--;
LockShape();
SpawnNewShape();
}
DrawShape();
ed.WriteMessage("\nScore: " + score);
}
}
}
}
**C#版**:
- Visual Studioで.NETプロジェクトを作成し、AutoCAD .NET APIを参照に追加
- コードをコンパイルしてDLLを作成
- AutoCADで「NETLOAD」コマンドでDLLをロード
- コマンドラインで「TETRIS」と入力して実行
## 操作方法
- 左右矢印キー: 左右移動
- 下矢印キー: 加速落下
- 上矢印キー: 回転
- スペースキー: 即時落下