holyya.com
2025-09-04 13:50:06 Thursday
登录
文章检索 我的文章 写文章
俄罗斯方块C++代码文件
2023-07-05 13:35:23 深夜i     --     --
俄罗斯方块 C++ 代码文件

俄罗斯方块是一款经典的游戏,通过控制下落的方块,使它们堆叠在一起并填满整个屏幕。如果你是一位C ++编程爱好者,那么写一个俄罗斯方块的程序是一个不错的练习。

下面是一个俄罗斯方块的C++代码文件。这个代码文件主要包括两个类:方块类和游戏类。方块类用于表示方块的形状和位置,游戏类用于管理游戏的逻辑流程和显示。


#include <iostream>

#include <vector>

#include <cstdlib>

#include <ctime>

#include <conio.h>

#include <Windows.h>

using namespace std;

const int WIDTH = 10;

const int HEIGHT = 20;

const char BLOCK = char(219);

const char BLANK = ' ';

class Block {

public:

  Block() {

    srand(time(nullptr));

    int shapeIndex = rand() % 7;

    shape_ = SHAPES[shapeIndex];

    color_ = shapeIndex + 1;

    x_ = WIDTH / 2 - 2;

    y_ = 0;

  }

  void moveDown() {

    y_++;

  }

  void moveLeft()

    x_--;

  

  void moveRight() {

    x_++;

  }

  void rotate(bool clockwise = true) {

    vector<string> newShape(shape_[0].size(), string(shape_.size(), ' '));

    int dx = shape_.size() - 1;

    int dy = shape_[0].size() - 1;

    if (clockwise) {

      for (int i = 0; i < shape_.size(); i++) {

        for (int j = 0; j < shape_[0].size(); j++) {

          newShape[j][dx - i] = shape_[i][j];

        }

      }

    } else {

      for (int i = 0; i < shape_.size(); i++) {

        for (int j = 0; j < shape_[0].size(); j++) {

          newShape[dy - j][i] = shape_[i][j];

        }

      }

    }

    shape_ = newShape;

  }

  vector<string> getShape() const

    return shape_;

  

  int getColor() const

    return color_;

  

  int getX() const

    return x_;

  

  int getY() const

    return y_;

  

private:

  vector<vector<char>> shape_;

  int color_;

  int x_;

  int y_;

  static const vector<vector<char>> SHAPE_I;

  static const vector<vector<char>> SHAPE_J;

  static const vector<vector<char>> SHAPE_L;

  static const vector<vector<char>> SHAPE_O;

  static const vector<vector<char>> SHAPE_S;

  static const vector<vector<char>> SHAPE_T;

  static const vector<vector<char>> SHAPE_Z;

  static const vector<vector<char>> SHAPES[7];

};

const vector<vector<char>> Block::SHAPE_I = {

     ' ',

     BLOCK,

     ' ',

     ' '

};

const vector<vector<char>> Block::SHAPE_J = {

     ' ',

     BLOCK,

    ' ',

};

const vector<vector<char>> Block::SHAPE_L = {

    ' ',

     BLOCK,

    ' ',

};

const vector<vector<char>> Block::SHAPE_O = {

    BLOCK,

     BLOCK,

};

const vector<vector<char>> Block::SHAPE_S = {

     BLOCK,

    BLOCK,

     ' ',

};

const vector<vector<char>> Block::SHAPE_T = {

     BLOCK,

     BLOCK,

    ' ',

};

const vector<vector<char>> Block::SHAPE_Z = {

     ' ',

     BLOCK,

     ' ',

};

const vector<vector<char>> Block::SHAPES[7] = SHAPE_O;

class Game {

public:

  Game() {

    score_ = 0;

    isRunning_ = true;

    board_.resize(HEIGHT, string(WIDTH, BLANK));

    nextBlock_ = make_unique<Block>();

    activeBlock_ = make_unique<Block>();

    showInfo();

  }

  void run() {

    while (isRunning_) {

      Sleep(500);

      if (canMoveDown(*activeBlock_)) {

        activeBlock_->moveDown();

        flush();

      } else if (activeBlock_->getY() == 0) {

        gameOver();

      } else {

        fixBlock(*activeBlock_);

        checkAndRemoveRows();

        activeBlock_ = move(nextBlock_);

        nextBlock_ = make_unique<Block>();

      }

      handleInput();

    }

  }

private:

  int score_;

  bool isRunning_;

  vector<string> board_;

  unique_ptr<Block> nextBlock_;

  unique_ptr<Block> activeBlock_;

  void showInfo() const {

    cout << "=====Tetris=====" << endl;

    cout << "Use arrow keys to play" << endl;

    cout << "Score: " << score_ << endl;

    cout << "Next block:" << endl;

    auto shape = nextBlock_->getShape();

    for (int i = 0; i < shape.size(); i++) {

      cout << shape[i] << endl;

    }

    flush();

  }

  void flush() const {

    system("cls");

    for (int i = 0; i < board_.size(); i++) {

      cout << board_[i] << endl;

    }

    showInfo();

  }

  bool checkAndRemoveRows() {

    bool removed = false;

    for (int i = board_.size() - 1; i >= 0; i--) {

      if (board_[i].find(BLANK) == string::npos) {

        board_.erase(board_.begin() + i);

        board_.insert(board_.begin(), string(WIDTH, BLANK));

        score_ += 10;

        removed = true;

      }

    }

    if (removed) {

      flush();

    }

    return removed;

  }

  void handleInput() {

    if (_kbhit()) {

      int key = _getch();

      switch (key) {

        case 224:

          key = _getch();

          switch (key) {

            case 72:

              rotate(false);

              break;

            case 80:

              rotate(true);

              break;

            case 75:

              moveLeft();

              break;

            case 77:

              moveRight();

              break;

            default:

              break;

          }

          break;

        default:

          break;

      }

    }

  }

  bool canMoveDown(const Block &block) const {

    auto shape = block.getShape();

    int x = block.getX();

    int y = block.getY();

    for (int i = 0; i < shape.size(); i++) {

      for (int j = 0; j < shape[0].size(); j++) {

        if (shape[i][j] != BLANK) {

          int px = x + j;

          int py = y + i;

          if (py >= HEIGHT || board_[py][px] != BLANK) {

            return false;

          }

        }

      }

    }

    return true;

  }

  void fixBlock(const Block &block) {

    auto shape = block.getShape();

    int x = block.getX();

    int y = block.getY();

    for (int i = 0; i < shape.size(); i++) {

      for (int j = 0; j < shape[0].size(); j++) {

        if (shape[i][j] != BLANK) {

          int px = x + j;

          int py = y + i;

          board_[py][px] = BLOCK;

        }

      }

    }

  }

  void moveLeft() {

    if (canMoveLeft(*activeBlock_)) {

      activeBlock_->moveLeft();

      flush();

    }

  }

  void moveRight() {

    if (canMoveRight(*activeBlock_)) {

      activeBlock_->moveRight();

      flush();

    }

  }

  bool canMoveLeft(const Block &block) const {

    auto shape = block.getShape();

    int x = block.getX();

    int y = block.getY();

    for (int i = 0; i < shape.size(); i++) {

      for (int j = 0; j < shape[0].size(); j++) {

        if (shape[i][j] != BLANK) {

          int px = x + j - 1;

          int py = y + i;

          if (px < 0 || board_[py][px] != BLANK) {

            return false;

          }

        }

      }

    }

    return true;

  }

  bool canMoveRight(const Block &block) const {

    auto shape = block.getShape();

    int x = block.getX();

    int y = block.getY();

    for (int i = 0; i < shape.size(); i++) {

      for (int j = 0; j < shape[0].size(); j++) {

        if (shape[i][j] != BLANK) {

          int px = x + j + 1;

          int py = y + i;

          if (px >= WIDTH || board_[py][px] != BLANK) {

            return false;

          }

        }

      }

    }

    return true;

  }

  void rotate(bool clockwise) {

    auto blockCopy = *activeBlock_;

    blockCopy.rotate(clockwise);

    if (canRotate(blockCopy)) {

      *activeBlock_ = blockCopy;

      flush();

    }

  }

  bool canRotate(const Block &block) const {

    auto shape = block.getShape();

    int x = block.getX();

    int y = block.getY();

    for (int i = 0; i < shape.size(); i++) {

      for (int j = 0; j < shape[0].size(); j++) {

        if (shape[i][j] != BLANK) {

          int px = x + j;

          int py = y + i;

          if (px < 0 || px >= WIDTH || py < 0 || py >= HEIGHT || board_[py][px] != BLANK) {

            return false;

          }

        }

      }

    }

    return true;

  }

  void gameOver() {

    isRunning_ = false;

    cout << "Game over!" << endl;

    cout << "Score: " << score_ << endl;

  }

  unique_ptr<Block> move(unique_ptr<Block> block) {

    auto result = move(block);

    return result;

  }

};

int main() {

  Game game;

  game.run();

  return 0;

}

在这个代码文件中,主要包括两个类`Block`和`Game`。`Block`类表示方块的形状和位置,包含了几种不同的形状和对应的颜色,以及在游戏中的位置坐标。`Game`类用于管理游戏的逻辑流程和显示,包含了游戏的主循环、得分、判断方块是否能够向下移动、横向移动、旋转等等。

在`Block`类中,我们使用了一个`vector`来表示方块的形状。每种形状都是一个二维字符数组,其中空白字符代表空格,另外的字符则代表方块的图案。

在`Game`类中,我们使用了一个`vector`来表示整个游戏区域的状态。游戏区域的大小是固定的,但是方块的大小和形状以及位置是不断变化的。我们使用方块的坐标和形状来更新游戏区域的状态。

整个程序的过程大致如下:首先,我们创建一个白色的游戏区域,并在游戏区域的最上方预留一个位置来显示下一个方块的形状。然后,创建一个活动方块和一个下一个方块,将下一个方块的图案显示在游戏区域的顶部,并开始游戏的主循环。在游戏循环中,我们先判断活动方块是否能够向下移动。如果能够向下移动,那么就更新方块的位置并刷新游戏区域。如果不能向下移动了,那么我们判断方块的位置是否在游戏区域的最上方,如果是,那么游戏结束。如果不是,那么我们将活动方块固定到游戏区域中,并检查游戏区域中是否有可以消除的行。如果有可以消除的行,那么就将这些行都消除掉,并更新分数和游戏区域的状态。最后,我们创建一个新的活动方块并开始下一轮游戏循环。

总的来说,这个C++代码文件实现了一个简单的俄罗斯方块游戏。虽然不是很完美,但是它可以用来练习C++编程技能和游戏编程技能。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复