구현기능
실행화면
메인코드
//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);
}