C++ 테트리스 2차

박원엽·2022년 5월 16일
0

CPP Tetris

목록 보기
2/4
post-thumbnail

구현기능

  1. 블록을 양옆으로 이동할 수 있게 만듬
  2. 블록이 랜덤한 순서로 7개씩 순환하게 만듬
  3. 블록 회전 기능 추가
  4. 메인메뉴 업데이트(게임시작, 게임방법, 게임종료)

실행화면

메인코드

//main.cpp

#include <iostream>
#include <vector>
#include <conio.h>
#include <windows.h>
#include "system.h"
#include "screen.h"
#include "game.h"

int main() {
	int sel = 0;
	int stack = 1;
	CursorView(false); //커서 안보이게하기
	system("mode con cols=130 lines=40 | title C++ Tetris"); //상태창 설정
	Screen screen; //메인화면 설정
	Game game; //게임에 필요한 요소 설정
	while (sel != 1) {
		sel = screen.MainMenu();
		if (sel == 2) {
			screen.how();//게임방법 출력
		}
		else if (sel == 3) {
			exit(0);//게임 종료
		}
	}

	//게임 실행
	while (sel == 1) {
		if (stack == 1) {//쌓였을때
			game.setBlock();//다음 블록 선택
		}
		game.drawTable();//블록을 테이블에 그림
		stack = game.drawBlock();//블록의 위치를 테이블위에 정함
		game.moveDrop();//한칸씩 아래로 떨어짐
		game.moveSide();//블록을 양옆으로 움직임
		game.changeRotation();//블록의 방향을 바꿈
		Sleep(200);//대기
	}
	return 0;
}

헤더파일

//game.h

#pragma once
#include<vector>
using namespace std;

class Game
{
private:
	int x, y;
	int num;
	int rotation;
	int shape[4][4][4];
	int Selected_block;
	int stack;
	int stop1, stop2;
	int blockList[7];
	int rand_seed;
	vector<vector<int>> table;
public:
	Game();
	void orderBlock();
	void setBlock();
	void selectBlock();
	void drawTable();
	int drawBlock();
	void moveSide();
	void moveDrop();
	void changeRotation();
};

//screen.h

#pragma once

class Screen {
private:
	int sel, enter;
public:
	Screen();
	int MainMenu();
	void SelectMenu();
	void how();
};

system.h

#pragma once
void CursorView(char show); // 커서 설정
void gotoxy(int x, int y); // 커서 위치 설정

클래스/함수 코드

//game.cpp

#include "game.h"
#include "system.h"
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include<ctime>
using namespace std;
#define TABLE_X 12
#define TABLE_Y 20

/*
* 테트리스 블록 선언
*/
const int Block_I[4][4][4] = { // I블록
        {
                        {0, 0, 0, 0},
                        {2, 2, 2, 2},
                        {0, 0, 0, 0},
                        {0, 0, 0, 0}
        },
        {
                        {0, 0, 2, 0},
                        {0, 0, 2, 0},
                        {0, 0, 2, 0},
                        {0, 0, 2, 0}
        },
        {
                        {0, 0, 0, 0},
                        {0, 0, 0, 0},
                        {2, 2, 2, 2},
                        {0, 0, 0, 0}
        },
        {
                        {0, 2, 0, 0},
                        {0, 2, 0, 0},
                        {0, 2, 0, 0},
                        {0, 2, 0, 0}
        },
};

const int Block_L[4][4][4] = { //L블록
    {
                    {0, 2, 0, 0},
                    {0, 2, 0, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 2},
                    {0, 2, 0, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 0, 2, 0},
                    {0, 0, 2, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 0, 2, 0},
                    {2, 2, 2, 0},
                    {0, 0, 0, 0}
    },
};
const int Block_J[4][4][4] = { //J블록
    {
                    {0, 0, 2, 0},
                    {0, 0, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 0, 0},
                    {0, 2, 2, 2},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 2, 0, 0},
                    {0, 2, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {2, 2, 2, 0},
                    {0, 0, 2, 0},
                    {0, 0, 0, 0}
    },
};
const int Block_Z[4][4][4] = { //Z블록
    {
                    {0, 0, 0, 0},
                    {0, 2, 0, 0},
                    {0, 2, 2, 0},
                    {0, 0, 2, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {2, 2, 0, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 2, 0},
                    {0, 0, 2, 2},
                    {0, 0, 0, 2},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 0, 2, 2},
                    {0, 2, 2, 0}
    },
};
const int Block_S[4][4][4] = {//S블록
    {
                    {0, 0, 0, 0},
                    {0, 0, 2, 0},
                    {0, 2, 2, 0},
                    {0, 2, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {2, 2, 0, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 2},
                    {0, 0, 2, 2},
                    {0, 0, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 0, 2, 2}
    },
};
const int Block_O[4][4][4] = {//O블록
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 0, 0}
    },
};
const int Block_T[4][4][4] = {//T블록
    {
                    {0, 0, 0, 0},
                    {0, 2, 2, 2},
                    {0, 0, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 2, 0},
                    {0, 2, 2, 0},
                    {0, 0, 2, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 2, 0},
                    {0, 2, 2, 2},
                    {0, 0, 0, 0},
                    {0, 0, 0, 0}
    },
    {
                    {0, 0, 2, 0},
                    {0, 0, 2, 2},
                    {0, 0, 2, 0},
                    {0, 0, 0, 0}
    },
};

//게임배경 설정
Game::Game() {
	for (int i = 0; i < TABLE_Y; i++) {
		vector<int> temp;
		for (int j = 0; j < TABLE_X; j++) {
			temp.push_back(0);
		}
		table.push_back(temp);
	}
	for (int i = 0; i < TABLE_X; i++) {
		table[0][i] = 1;
		table[TABLE_Y - 1][i] = 1;
	}
	for (int i = 0; i < TABLE_Y-1; i++) {
		table[i][0] = 1;
		table[i][TABLE_X-1] = 1;
	}
    num = 0;
    rand_seed = (unsigned int)time(NULL);
}

//게임화면 출력 및 업데이트
void Game::drawTable() {
    system("cls");
	for (int i = 0; i < TABLE_Y; i++) {
		for (int j = 0; j < TABLE_X; j++) {
			if (table[i][j] == 1)cout << "▦";
			else if (table[i][j] == 2) { // 블록을 실시간으로 이동시키는기능
				cout << "■";
				if (stack == 1)table[i][j] = 3;
				else table[i][j] = 0;
			}
			else if (table[i][j] == 3) { // 블록 쌓이는기능
				cout << "■";
			}
			else cout << "  ";
		}
		cout << "\n";
	}
    if (stack == 1)stack = 0;
}

//출력될 블록 세팅
void Game::setBlock() {
	x = 4;
	y = 1;
	rotation=0;
    stop1 = 0;
    stop2 = 0;
    if (num == 7) num = 0;
    if (num == 0) orderBlock();
    selectBlock();
    num++;
}

//다음에 나올 블럭을 설정함
void Game::selectBlock() {
	if (blockList[num] == 1) {
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_I[i][j][k];
				}
			}
		}
	}
    else if (blockList[num] == 2) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_J[i][j][k];
                }
            }
        }
    }
    else if (blockList[num] == 3) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_L[i][j][k];
                }
            }
        }
    }
    else if (blockList[num] == 4) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_Z[i][j][k];
                }
            }
        }
    }
    else if (blockList[num] == 5) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_S[i][j][k];
                }
            }
        }
    }
    else if (blockList[num] == 6) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_T[i][j][k];
                }
            }
        }
    }
    else if (blockList[num] == 7) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    shape[i][j][k] = Block_O[i][j][k];
                }
            }
        }
    }
}

//블록을 화면상 출력하기위해 세팅
int Game::drawBlock() {
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if(shape[rotation][i][j] == 2){
                table[y+i][x+j] = 2;
                if (table[y + i + 1][x + j] == 1 || table[y + i + 1][x + j] == 3)stack = 1;//블록이 바닥이나 다른 블록에 부딪히면 멈춤
                if (table[y + i][x + j + 1] == 1 || table[y + i][x + j + 1] == 3) {//오른쪽이 벽이거나 블록이면 옆으로 이동하지않음
                    stop1 = 1;
                    stop2 = 0;
                }
                else if (table[y + i][x + j -1] == 1 || table[y + i][x + j -1] == 3) {//왼쪽이 벽이거나 블록이면 옆으로 이동하지않음
                    stop1 = 0;
                    stop2 = 1;
                }
            }
        }
    }
    return stack;
}

//블록을 한칸 아래로 내림
void Game::moveDrop() {
    y += 1;
}

//블록을 양옆으로 이동시킴
void Game::moveSide() {
    if (stop1 == 0 && GetAsyncKeyState(VK_RIGHT) & 0x8001) {
        x++;
    }
    else if (stop2 == 0 && GetAsyncKeyState(VK_LEFT) & 0x8001) {
        x--;
    }
    
}

//블록의 방향을 바꿈
void Game::changeRotation() {
    if (GetAsyncKeyState('z') || 0x8000 && GetAsyncKeyState('Z') & 0x8001)rotation++;
    else if (GetAsyncKeyState('x') || 0x8000 && GetAsyncKeyState('X') & 0x8001)rotation++;

    if (rotation > 3) rotation = 0;
    else if (rotation < 0)rotation = 3;
}

//다음 7개의 블록의 순서를 결정함
void Game::orderBlock() {
    int buffer;
    int randset;
    rand_seed++;
    srand(rand_seed);
    for (int i = 0; i < 7; i++) {
        blockList[i] = i + 1;
    }
    for (int i = 0; i < 7; i++) {
        randset = rand() % (7 - i);
        buffer=blockList[randset];
        blockList[randset] = blockList[6-i];
        blockList[6 - i] = buffer;
    }
}

//mainscreen.cpp

#include "screen.h"
#include "system.h"
#include <iostream>
#include <cstdlib>
#include <conio.h>
using namespace std;
Screen::Screen() {
    sel = 1;
    enter = 0;
}
//메인화면 출력
int Screen::MainMenu() {
    cout << "\n\n\n\n";
    cout << "\t\t" << "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n";
    cout << "\t\t" << "□■■■■□□■□■□□□□■■■■■■■■□□□■■■■■■□□■□□□□□□□□■□□□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□■□□□□□□□□□□□□□□□■□□■□□□□□□□□■□□□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□■□□□□□□□□□□□□□□□■□□■□□□□□□□□■□□□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□■■■■■■■■□□□□□□□□■□□■□□□□□□□■□■□□□□\n";
    cout << "\t\t" << "□■■■□■■■□■□□□□■□□□□□□□□□□■■■■■■□□■□□□□□□■□□□■□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□■□□□□□□□□□□■□□□□□□□■□□□□■■□□□□□■■□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□■■■■■■■■□□□■□□□□□□□■□□□□□□□□□□□□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□□□□□□□□□□□□■□□□□□□□■□□□□□□□□□□□□□□\n";
    cout << "\t\t" << "□■□□□□□■□■□□□□□□□□□□□□□□□■□□□□□□□■□□□□□□□□□□□□□□\n";
    cout << "\t\t" << "□■■■■■□■□■□□□■■■■■■■■■■□□■■■■■■■□■□□□■■■■■■■■■■□\n";
    cout << "\t\t" << "□□□□□□□■□■□□□□□□□□□□□□□□□□□□□□□□□■□□□□□□□□□□□□□□\n";
    cout << "\t\t" << "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□\n";
    if (sel == 1) {//게임시작 선택
        cout << "\n\n\t\t\t\t\t\t\t" << "> 게임시작\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "게임방법\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "게임종료\n";
    }
    else if (sel == 2) {//게임방법 선택
        cout << "\n\n\t\t\t\t\t\t\t" << "게임시작\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "> 게임방법\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "게임종료\n";
    }
    else if (sel == 3) {//게임종료선택
        cout << "\n\n\t\t\t\t\t\t\t" << "게임시작\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "게임방법\n";
        cout << "\n\n\t\t\t\t\t\t\t" << "> 게임종료\n";
    }

    if (enter == 1) {//선택한 메뉴를 실행
        system("cls");
        return sel;
    }
    else {
        SelectMenu();//위아래로 움직이며 메뉴를 선택
        system("cls");
        return 0;
    } 
}

//조작법 및 플레이방법
void Screen::how() {
    cout << "\n\n\n\n";
    cout << "\t\t\t" << "조작법" << endl;
    cout << "\n\n\t\t\t" << "←→ 좌우로 움직이기" << endl;
    cout << "\n\t\t\t" << "↓ 빠르게 떨어뜨리기" << endl;
    cout << "\n\t\t\t" << "z 오른쪽으로 회전" << endl;
    cout << "\n\t\t\t" << "x 왼쪽으로 회전" << endl;
    cout << "\n\t\t\t" << "spacebar 바로 떨어뜨리기" << endl;
    cout << "\n\t\t\t" << "shift 홀드" << endl;
    cout << "\n\n\n\t\t\t" << "How to play" << endl;
    cout << "\n\n\t\t\t" << "1. 떨어지는 블록을 쌓습니다." << endl;
    cout << "\n\t\t\t" << "2. 줄을 빈틈없이 쌓으면 줄이 사라지며 점수를 얻을 수 있습니다." << endl;
    cout << "\n\t\t\t" << "3. 여러줄을 동시에 없애면 추가 점수를 얻을 수 있습니다." << endl;
    cout << "\n\t\t\t" << "4. 블록이 천장에 닿이면 게임오버입니다." << endl;
    system("pause>null");
    system("cls");
    enter = 0;
    sel = 1;
}

//키보드를 이용해 메뉴를 선택
void Screen::SelectMenu() {
    char c;
    c = _getch();
    if (c == 80) {
        if (sel < 3)sel += 1;
    }
    else if (c == 72) {
        if (sel > 1)sel -= 1;
    }
    if (c == 13) {
        enter = 1;
    }
}

//system.cpp

#include <iostream>
#include <windows.h>
#include "system.h"
using namespace std;
//커서 설정
void CursorView(char show) {
    HANDLE hConsole;
    CONSOLE_CURSOR_INFO ConsoleCursor;

    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    ConsoleCursor.bVisible = show;
    ConsoleCursor.dwSize = 1;

    SetConsoleCursorInfo(hConsole, &ConsoleCursor);
}

//커서 위치 지정
void gotoxy(int x, int y) {
    COORD pos = { x,y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
profile
다양한 분야 해보는중

0개의 댓글