テトリスを回転したときほかの設置されているテトリミノに重なってしまう件
解決したいこと
テトリミノを回転したときに設置されているテトリミノに重なってしまいます。
Rキーでテトリミノを回転すると
このように設置されているテトリミノと重なってしまう結果になってしまいます。
一枚目の写真の状態からRキーを押しても回転しないようにしたいです。
↓は私が書いたコードです
例)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include<stdbool.h>
#define FIELD_HIGHT 20
#define FIELD_WIDE 10
int field[FIELD_HIGHT][FIELD_WIDE];
int backBuffer[FIELD_HIGHT][FIELD_WIDE];
//テトリミノの定義
typedef struct {
int shape[4][4];
int width;
int hight;
int currentX;
int currentY;
} Tetrimino;
Tetrimino I = {
{
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
4, // 横のサイズ
1, // 縦のサイズ
0, // 初期のX座標
0 // 初期のY座標
};
Tetrimino T = {
{
{0, 1, 0, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
3, // 横のサイズ
2, // 縦のサイズ
0, // 初期のX座標
0 // 初期のY座標
};
Tetrimino O = {
{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
2, // 横のサイズ
2, // 縦のサイズ
0, // 初期のX座標
0 // 初期のY座標
};
Tetrimino S = {
{
{0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
3, // 横のサイズ
2, // 縦のサイズ
0, // 初期のX座標
0 // 初期のY座標
};
Tetrimino Z = {
{
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
3, // 横のサイズ
2, // 縦のサイズ
0, // 初期のX座標
0 // 初期のY座標
};
// 他のテトリミノ省略...
Tetrimino tetriminos[] = { I,T,Z,S,O };
Tetrimino selectedTetrimino;
void initializeField();
int rotateTetrimino(Tetrimino* tetrimino,int newX,int newY);
void DrawScreen();
void InitMino();
int hit_Mino(int newX,int newY);
void put_Mino();
int main() {
srand((unsigned int)time(NULL));// 乱数の初期化
initializeField();
InitMino();
// キーボード入力を待つループ
while (1) {
if (_kbhit()) {
switch (_getch()) {
case 'a':
if (!hit_Mino(selectedTetrimino.currentX - 1, selectedTetrimino.currentY)) {
selectedTetrimino.currentX--;
}
break;
case 'd':
if (!hit_Mino(selectedTetrimino.currentX + 1, selectedTetrimino.currentY)){
selectedTetrimino.currentX++;
}
break;
case 's':
if (!hit_Mino(selectedTetrimino.currentX , selectedTetrimino.currentY+1)){
selectedTetrimino.currentY++;
}
else {
put_Mino();
}
break;
case 'r':
rotateTetrimino(&selectedTetrimino, selectedTetrimino.currentX, selectedTetrimino.currentY);
break;
}
}
// カーソルを左上に配置
printf("\033[H");
DrawScreen();
}
}
// フィールドを初期化
void initializeField() {
memset(field, 0, sizeof field);
}
void InitMino() {
int rendomIndex = rand() % 5; // 一時的に1つだけ使用
selectedTetrimino = tetriminos[rendomIndex];
// テトリミノの初期位置を指定
selectedTetrimino.currentX = (FIELD_WIDE - selectedTetrimino.currentX) / 2;
selectedTetrimino.currentY = 0;
}
// 描画処理
void DrawScreen() {
memset(backBuffer, 0, sizeof backBuffer);
for (int y = 0; y < FIELD_HIGHT; y++) {
for (int x = 0; x < FIELD_WIDE; x++) {
backBuffer[y][x] = field[y][x];
}
}
// テトリミノの描画
for (int y = 0; y < selectedTetrimino.hight; y++) {
for (int x = 0; x < selectedTetrimino.width; x++) {
if (selectedTetrimino.shape[y][x] == 1) {
backBuffer[selectedTetrimino.currentY + y ][selectedTetrimino.currentX + x] = 1;
}
}
}
// バックバッファをコンソール上に出力
for (int y = 0; y < FIELD_HIGHT; y++) {
printf("■");
for (int x = 0; x < FIELD_WIDE; x++) {
if (backBuffer[y][x] == 1)
printf("■");
else
printf(" ");
}
printf("■\n");
}
for (int x = 0; x < FIELD_WIDE+2; x++)
printf("■");
}
// テトリミノの回転
int rotateTetrimino(Tetrimino* tetrimino,int newX,int newY) {
int original[4][4] = { 0 };
int rotated[4][4] = { 0 };
// 回転前の形状を保存
for (int y = 0; y < tetrimino->hight; y++) {
for (int x = 0; x < tetrimino->width; x++) {
original[y][x] = tetrimino->shape[y][x];
}
}
// 回転の計算
for (int y = 0; y < tetrimino->hight; y++) {
for (int x = 0; x < tetrimino->width; x++) {
rotated[x][tetrimino->hight - 1- y] = tetrimino->shape[y][x];
}
}
// 回転時にテトリミノとの衝突判定
for (int y = 0; y < tetrimino->hight; y++) {
for (int x = 0; x < tetrimino->width; x++) {
if (rotated[y][x] == 1) {
if (newX + x < 0 || newX + x >= FIELD_WIDE ||
newY + y >= FIELD_HIGHT ||
field[newY + y][newX + x] == 1) {
// 衝突時に元の状態に戻す
for (int j = 0; j < tetrimino->hight; j++) {
for (int i = 0; i < tetrimino->width; i++) {
tetrimino->shape[j][i] = original[j][i];
}
}
return false;// 回転失敗
}
}
}
}
// 回転後の形状を元の形状にコピー
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
tetrimino->shape[y][x] = rotated[y][x];
}
}
// 高さと幅の値を入れ替える
int temp = tetrimino->width;
tetrimino->width = tetrimino->hight;
tetrimino->hight = temp;
// 枠外修正
if (tetrimino->currentX + tetrimino->width > FIELD_WIDE) {
tetrimino->currentX = FIELD_WIDE - tetrimino->width;
}
if (tetrimino->currentY + tetrimino->hight > FIELD_HIGHT) {
tetrimino->currentY = FIELD_HIGHT - tetrimino->hight;
}
return true;// 回転成功
}
void put_Mino() {
for (int y = 0; y < selectedTetrimino.hight; y++) {
for (int x = 0; x < selectedTetrimino.width; x++) {
if (selectedTetrimino.shape[y][x] == 1) {
field[selectedTetrimino.currentY + y][selectedTetrimino.currentX + x] = 1;
}
}
}
InitMino();
}
// 衝突判定
int hit_Mino(int newX,int newY) {
for (int y = 0; y < selectedTetrimino.hight; y++) {
for (int x = 0; x < selectedTetrimino.width; x++) {
if (selectedTetrimino.shape[y][x] == 1) {
if (newX + x < 0 || newX + x >=FIELD_WIDE ||
newY + y >=FIELD_HIGHT ||
field[newY + y][newX + x] == 1) {
return true;
}
}
}
}
return false;
}
自分で確かめたこと
rotateTetrimino関数内で回転前の形状を保存するoriginal[][]を作り、回転時の衝突判定で引っかかった場合、回転前のテトリミノにするプログラムを組みましたがうまくいきませんでした。