C++러시아 블록 구현(linux 버 전)
주 프로그램
RussiaBlock.cpp
//
// Created by adl on 2020/7/18.
//
#include "Block.h"
#include "Table.h"
#include <thread>
#include <mutex>
#include "hierarchical_mutex.h"
#include "fstream"
using namespace std;
thread_local uint64_t
hierarchical_mutex::this_thread_hierarchical_value = ULONG_MAX;
int main(int argc, char **argv) {
int level = 1;
if (argc == 2) {
if ((level = atoi(argv[1])) == 0) {
cerr << "./a.out number " << endl;
exit(-1);
}
}
static int flag = 1;//
static Table tab(20, 20, level); // 15,20
static Block bl; //
hierarchical_mutex table_mtx(2);
hierarchical_mutex mtx(1);
thread getkey([&]() {
unsigned char buf[2];
struct termios saveterm, nt;
fd_set rfds, rs;
struct timeval tv;
int i = 0, q, r, fd = 0;//
tcgetattr(fd, &saveterm);
nt = saveterm;
nt.c_lflag &= ~ECHO;
nt.c_lflag &= ~ISIG;
nt.c_lflag &= ~ICANON;
tcsetattr(fd, TCSANOW, &nt);
FD_ZERO(&rs);
FD_SET(fd, &rs);
tv.tv_usec = 0;
tv.tv_sec = 0;
while (1) {
read(0, buf, 1);
buf[1] = '\0';
r = select(fd + 1, &rfds, nullptr, nullptr, &tv);
if (r < 0) {
write(fileno(stderr), "select error.
", sizeof("select error.
"));
}
rfds = rs;
std::unique_lock<hierarchical_mutex> table_lock(table_mtx);
//
switch (buf[0]) {
case 'A': {
//
tab.clr_block(bl);//
if (bl.get_type() == 5)continue;
bl.rotate();
if (tab.set_block(bl) == -1) {
bl.rotate_back();
tab.set_block(bl);
continue;
}
break;
}
case 'B': {
// ( )
tab.clr_block(bl);
bl.move(Block::DOWN);
if (tab.set_block(bl) == -1) {
bl.move(Block::UP);
tab.set_block(bl);
}
break;
}
case 'C': {
/* */
tab.clr_block(bl);
bl.move(Block::RIGHT);
if (tab.set_block(bl) == -1) {
bl.move(Block::LEFT);
tab.set_block(bl);
}
break;
}
case 'D': {
//
tab.clr_block(bl);
bl.move(Block::LEFT);
if (tab.set_block(bl) == -1) {
bl.move(Block::RIGHT);
tab.set_block(bl);
}
break;
}
default:
break;
}
table_lock.unlock();
std::unique_lock<hierarchical_mutex> lock(mtx);
if (flag == 2 || buf[0] == 113) {
lock.unlock();
tcsetattr(fd, TCSANOW, &saveterm);
std::cout << "game over" << std::endl;
exit(0);
} else {
lock.unlock();
}
}
tcsetattr(0, TCSANOW, &saveterm);
});
thread printloop([&]() {
while (1) {
system("clear");
std::unique_lock<hierarchical_mutex> table_lock(table_mtx);
tab.paint();
table_lock.unlock();
this_thread::sleep_for(std::chrono::milliseconds(200 / tab.getLevel()));
std::unique_lock<hierarchical_mutex> lock(mtx);
if (flag == 2) {
cout << " " << endl;
lock.unlock();
break;
} else
lock.unlock();
}
});
getkey.detach();
printloop.detach();
int dir, i, c;
while (true) {
//
std::unique_lock<hierarchical_mutex> table_lock(table_mtx);
// std::unique_lock<std::mutex>table_lock(table_mtx);
bl.create_block(tab.getWidth(), tab.getHeight());
table_lock.unlock();
//
table_lock.lock();
if (-1 == tab.set_block(bl)) {
std::unique_lock<hierarchical_mutex> lock(mtx);
flag = 2;
lock.unlock();
table_lock.unlock();
while (1);
} else
table_lock.unlock();
///////////
while (true) {
this_thread::sleep_for(std::chrono::milliseconds(400 / tab.getLevel()));
/////////////
table_lock.lock();
tab.clr_block(bl); //
bl.move(Block::DOWN); //
if (-1 == tab.set_block(bl)) { //
bl.move(Block::UP); // ,
tab.set_block(bl);
table_lock.unlock();
break;
}
table_lock.unlock();
}
//
table_lock.lock();
for (i = 0; i < tab.getHeight(); i++) {
if (tab.if_full(i)) { //
tab.clr_line(i); // ,
tab.move_line(i); //
i--; // , ( )
tab.set_count(100); //
}
}
table_lock.unlock();
}
return 0;
}
grid.h
//
// Created by adl on 2020/7/17.
//
#ifndef UNTITLED_GRID_H
#define UNTITLED_GRID_H
struct grid {
int x;
int y;
grid();
grid(grid&&)noexcept ;
grid(const grid&);
grid(int x, int y);
grid&operator=(const grid&);
grid&operator=( grid&&);
virtual ~grid();
}; //
#endif //UNTITLED_GRID_H
grid.cpp
//
// Created by adl on 2020/7/17.
//
#include "grid.h"
grid::grid(int x, int y) : x(x), y(y) {}
grid::grid() : x(0), y(0) {}
grid::grid(grid &&rhs) noexcept: x(rhs.x), y(rhs.y) {
}
grid::~grid() {
}
grid::grid(const grid &rhs) : x(rhs.x), y(rhs.y) {
}
grid &grid::operator=(const grid &rhs) {
if (this != &rhs) {
x = rhs.x;
y = rhs.y;
}
return *this;
}
grid &grid::operator=(grid &&rhs) {
if (this != &rhs) {
x = rhs.x;
y = rhs.y;
}
return *this;
}
Block.h
//
// Created by adl on 2020/7/17.
//
#ifndef UNTITLED_BLOCK_H
#define UNTITLED_BLOCK_H
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <time.h>
#include<termios.h>
#include<fcntl.h>
#include <zconf.h>
#include "grid.h"
#define BLOCK_SIZE 4
#define SLEEP_TIME 500
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<memory>
#include <random>
class Block {
public:
using Action =Block&(Block::*)();
enum direct {
UP, DOWN, LEFT, RIGHT
};
grid g[BLOCK_SIZE];
Block() : center(0, 0), type(0) {}
void def_block(grid g1, grid g2, grid g3, grid g4) {
g[0] = g1;
g[1] = g2;
g[2] = g3;
g[3] = g4;
}
void rotate() {
//
int x, y;
for (int i = 0; i < 4; i++) {
x = g[i].x - center.x;
y = g[i].y - center.y;
g[i].x = center.x + y;
g[i].y = center.y - x;
}
}
Block &up() {
for (int i = 0; i < 4; ++i) {
g[i].y++;
}
center.y++;
return *this;
}
Block &down() {
for (int i = 0; i < 4; ++i) {
g[i].y--;
}
center.y--;
return *this;
}
Block &left() {
for (int i = 0; i < 4; ++i) {
g[i].x--;
}
center.x--;
return *this;
}
Block &right() {
for (int i = 0; i < 4; ++i) {
g[i].x++;
}
center.x++;
return *this;
}
void move(direct dir) {
(this->*Menu[dir])();
}
void set_cen(grid g) {
center = g;
}
grid get_cen() const {
return center;
}
void set_type(int t) {
type = t;
}
int get_type() const {
return type;
}
void rotate_back() {
//rotate
int x, y;
for (int i = 0; i < 4; i++) {
x = g[i].x - center.x;
y = g[i].y - center.y;
g[i].x = center.x + y;
g[i].y = center.y - x;
}
}
void create_block(int x, int y) {
unsigned int ran;
grid g[BLOCK_SIZE];
static std::uniform_int_distribution<unsigned> u(1, 7);
static std::default_random_engine e(time(0));
ran = u(e);
switch (ran) {
case 1: {
g[0].x = x / 2;
g[0].y = y - 3;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x;
g[2].y = g[0].y + 2;
g[3].x = g[0].x + 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(1);
break;
}
// L
case 2: {
g[0].x = x / 2;
g[0].y = y - 3;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x;
g[2].y = g[0].y + 2;
g[3].x = g[0].x - 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(2);
break;
}
//Z
case 3: {
g[0].x = x / 2;
g[0].y = y - 2;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x + 1;
g[2].y = g[0].y + 1;
g[3].x = g[0].x - 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(3);
break;
}
// Z
case 4: {
g[0].x = x / 2;
g[0].y = y - 2;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x + 1;
g[2].y = g[0].y + 1;
g[3].x = g[0].x - 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(4);
break;
}
//
case 5: {
g[0].x = x / 2;
g[0].y = y - 2;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x + 1;
g[2].y = g[0].y + 1;
g[3].x = g[0].x + 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(5);
break;
}
//1
case 6: {
g[0].x = x / 2;
g[0].y = y - 3;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x;
g[2].y = g[0].y + 2;
g[3].x = g[0].x;
g[3].y = g[0].y - 1;
set_cen(g[0]);
set_type(6);
break;
}
//
case 7: {
g[0].x = x / 2;
g[0].y = y - 2;
g[1].x = g[0].x;
g[1].y = g[0].y + 1;
g[2].x = g[0].x - 1;
g[2].y = g[0].y;
g[3].x = g[0].x + 1;
g[3].y = g[0].y;
set_cen(g[0]);
set_type(7);
break;
}
default:
std::cerr << "someThing err!" << ran << std::endl;
}
def_block(g[0], g[1], g[2], g[3]);
}
private:
static Action Menu[];
grid center;
int type;
};
#endif //UNTITLED_BLOCK_H
Block.cpp
//
// Created by adl on 2020/7/17.
//
#include "Block.h"
Block::Action Block::Menu[]={
&Block::up,
&Block::down,
&Block::left,
&Block::right
};
Table.cpp
//
// Created by adl on 2020/7/17.
//
#include "Table.h"
#include "Block.h"
int Table::set_block(const Block &bl) {
int x, y;
for (int i = 0; i < 4; ++i) {
x = bl.g[i].x;
y = bl.g[i].y;
// table[x][y]
if (table[x][y] != 0 || x >= width || x < 0 || y >= height || y < 0) {
return -1;
}
}
for (int i = 0; i < 4; ++i) {
x = bl.g[i].x;
y = bl.g[i].y;
table[x][y] = 1;
}
return 0;
}
void Table::clr_block(const Block &bl) {
int x, y;
for (int i = 0; i < 4; ++i) {
x = bl.g[i].x;
y = bl.g[i].y;
table[x][y] = 0;
}
}
int Table::clr_line(int y) {
if (y < 0 || y >= height) return -1;
for (int i = 0; i < width; i++) {
table[i][y] = 0;
}
return 0;
}
int Table::getHeight() const {
return height;
}
int Table::getWidth() const {
return width;
}
int Table::if_full(int y) {
for (int i = 0; i < width; ++i) {
if (table[i][y] == 0) return 0;
}
return 1;
}
int Table::get_table(int x, int y) {
return table[x][y];
}
void Table::paint() {
int i, j;
system("clear");
for (i = 0; i < width + 2; i++) std::cout << "-" << std::flush;
std::cout << "
" << std::flush;
for (i = height - 1; i >= 0; i--) {
std::cout << "|" << std::flush;
for (j = 0; j < width; j++) {
if (table[j][i] == 0) std::cout << " " << std::flush;
else std::cout << "#" << std::flush;
//▣
}
if (i == 13)
std::cout << "| :" << getLevel() << std::endl;
else if (i == 10)
std::cout << "| :" << get_count() << std::endl;
else if (i == 7)
std::cout << "| Press 'q' to quit!" << std::endl;
else
std::cout << "|" << std::endl;
}
for (i = 0; i < width + 2; i++) std::cout << "-" << std::flush;
std::cout << "
" << std::flush;
}
void Table::move_line(int y) {
for (int i = y; i < height - 1; ++i) {
for (int j = 0; j < width; ++j) {
table[j][i] = table[j][i + 1];
}
}
}
void Table::set_count(int c) {
count += c;
}
int Table::get_count() {
return count;
}
int Table::getLevel() const {
return level;
}
void Table::setLevel(int level) {
Table::level = level;
}
Table.h
//
// Created by adl on 2020/7/17.
//
#ifndef UNTITLED_TABLE_H
#define UNTITLED_TABLE_H
#include <cstring>
#define TABLE_SIZE 20
class Block;
class Table {
public:
Table():height(TABLE_SIZE),width(10),count(0),level(1){ //
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
table[i][j]=0;
}
}
}
int getLevel() const;
void setLevel(int level);
Table(int x, int y,int level):height(y),width(x),count(0),level(level){
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
table[i][j]=0;
}
}
}
int set_block(const Block &bl); //
void clr_block(const Block &bl); //
int clr_line(int y); //
int getHeight() const;
//
int if_full(int y); //
int get_table(int x, int y); //
void paint(); //
void move_line(int y); //
void set_count(int c); //
int get_count();
int getWidth() const;
//
private:
int table[TABLE_SIZE][TABLE_SIZE];//
int height, width; //
int count; //
int level;
};
#endif //UNTITLED_TABLE_H
hierarchical_mutex.h
//
// Created by adl on 2020/7/18.
//
#ifndef UNTITLED_HIERARCHICAL_MUTEX_H
#define UNTITLED_HIERARCHICAL_MUTEX_H
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<memory>
#include <exception>
#include <mutex>
#include <thread>
#include <climits>
class hierarchical_mutex{
private:
std::mutex internal_mutex;
uint64_t const hierarchical_value;
uint64_t previous_value;
static thread_local uint64_t this_thread_hierarchical_value;
void check_for_hierarchy() noexcept(false) {
if(this_thread_hierarchical_value <= hierarchical_value){
throw std::logic_error("mutex hierarchical violated.");
}
}
void update_hierarchy_value(){
previous_value = this_thread_hierarchical_value;
this_thread_hierarchical_value = hierarchical_value;
}
public:
constexpr explicit hierarchical_mutex(uint64_t value) :
hierarchical_value(value), previous_value(0) {}
void lock() noexcept(false) {
check_for_hierarchy();
internal_mutex.lock();
update_hierarchy_value();
}
void unlock(){
this_thread_hierarchical_value = previous_value;
internal_mutex.unlock();
}
bool try_lock() noexcept(false) {
check_for_hierarchy();
if(!internal_mutex.try_lock()) return false;
update_hierarchy_value();
return true;
}
};
#endif //UNTITLED_HIERARCHICAL_MUTEX_H
쌓 은 경험 치:1.난수 생 성 유 니 버 설int_distribution,defualt_random_engine(time(0))을 사용 할 때 static 를 사용 해 야 하 며,여러 번 프로그램 을 실행 한 첫 번 째 숫자 가 같은 것 이 단점 이다.
2.c+primer p743 과 유사 하 며,구성원 포인터 함수 표를 사용 하면 사용자 가 호출 하 는 함 수 를 더욱 명확 하 게 할 수 있 습 니 다.
3.상호 배척 잠 금 가중 치 를 주 고 가중치 크기 순서 로 잠 금 을 추가 하면 스 레 드 잠 금 순서 가 일치 하고 잠 금(나타 나 면 이상 을 던 집 니 다)을 피 할 수 있 습 니 다.(이 순수 활 학 활용 은 c+잠 금 과 스 레 드 접촉 이 많 지 않 기 때 문 입 니 다)
4.thread xxx([&](){})는 함수 내부 에 놓 을 수 있 는 스 레 드 입 니 다.
5.select 모니터링 표준 을 이용 하여 입력
6.tcgetattr,tcsetaddr,termiosi 구조 체 이용
nt.c_lflag &= ~ECHO; nt.c_lflag &= ~ISIG; nt.c_lflag &= ~ICANON;
Liux 에서 재생 을 닫 고 getch 를 실현 할 수 있 습 니 다.
7.this_thread::sleep_for(std::chrono::milliseconds(400 / tab.getLevel()));어떻게 스 레 드 에서 밀리초 급 수면 을 실현 할 수 있 습 니까?
8.클래스 에서 정적 대상 초기 화 는 대응 하 는.cpp 파일 에 쓸 수 있 습 니 다.
반성:
클래스 의 계승 을 사용 하지 않 으 면 각종 사각형 이론 은 하위 클래스 로 쓸 수 있 습 니 다.메 인 스 레 드 는 처음에 Block 대상 을 직접 사 용 했 기 때문에 후기 에 수정 하기 쉽 지 않 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Visual Studio에서 파일 폴더 구분 (포함 경로 설정)Visual Studio에서 c, cpp, h, hpp 파일을 폴더로 나누고 싶었습니까? 어쩌면 대부분의 사람들이 있다고 생각합니다. 처음에 파일이 만들어지는 장소는 프로젝트 파일 등과 같은 장소에 있기 때문에 파일...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.