goo blog サービス終了のお知らせ 

CyberChaos(さいばかおす)

プログラミング言語、トランスパイラ、RPA、ChatGPT、データマイニング、リバースエンジニアリングのための忘備録

AutoCADでテトリス!C#版www

2025-04-05 22:10:29 | Visual C#
// 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」と入力して実行

## 操作方法
- 左右矢印キー: 左右移動
- 下矢印キー: 加速落下
- 上矢印キー: 回転
- スペースキー: 即時落下


最新の画像もっと見る

コメントを投稿

サービス終了に伴い、10月1日にコメント投稿機能を終了させていただく予定です。
ブログ作成者から承認されるまでコメントは反映されません。