C++러시아 블록 구현(linux 버 전)

19225 단어 C++러시아 블록
본 논문 의 사례 는 C+러시아 블록 을 실현 하 는 구체 적 인 코드 를 공유 하여 여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
주 프로그램
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 대상 을 직접 사 용 했 기 때문에 후기 에 수정 하기 쉽 지 않 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기