博主晚上闲来无事,用opencv写了一个俄罗斯方块程序,以前是用dos界面写的,不太好理解,所以这次把opencv代码贴出来,供大家娱乐,哈哈。
一、测试软硬件
测试硬件:PC-Windows
测试软件:VS2013
二、测试可执行程序
可执行程序下载地址:https://download.csdn.net/download/samylee/10855245
三、操作说明
界面1:选择困难度:1(简单)、2(适中)、3(困难)
界面2:操作说明:A(向左)、D(向右)、J(变换)、右上角提示下个方块信息
四、代码展示
头文件:defense.h
#ifndef DEFENSE_H
#define DEFENSE_H
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
using namespace std;
using namespace cv;
class Defense
{
public:
Defense();
void Run();
private:
Mat defense_bg;
Mat defense_fg;
Rect defense_fg_rect;
Point begin_block;
int score;
int difficult;
vector<Mat> Russia_block;
void Define_Block();
Mat Set_Random_Block();
bool Go_End(Rect current_position, Mat ¤t_block, int direction);
};
#endif
源文件:defense.cpp
#include "defense.h"
Defense::Defense()
{
//initialize
Mat difficult_choice = Mat::zeros(Size(640, 480), CV_8UC3);
cv::putText(difficult_choice, "TETRIS", Point(170, 170), 4, 3, Scalar(0, 255, 255), 2);
cv::putText(difficult_choice, "Choice difficulty", Point(230, 220), 0, 0.8, Scalar(0, 255, 0), 2);
cv::putText(difficult_choice, "1: easy", Point(230, 270), 0, 0.8, Scalar(0, 255, 0), 2);
cv::putText(difficult_choice, "2: moderation", Point(230, 320), 0, 0.8, Scalar(0, 255, 0), 2);
cv::putText(difficult_choice, "3: difficulty", Point(230, 370), 0, 0.8, Scalar(0, 255, 0), 2);
cv::imshow("Tetris", difficult_choice);
char wait = cv::waitKey(0);
if (wait == 49)
difficult = 500;
else if (wait == 50)
difficult = 350;
else if (wait == 51)
difficult = 200;
else
difficult = 500;
defense_bg = Mat::zeros(Size(640, 480), CV_8UC3);
switch (difficult)
{
case 500:
cv::putText(defense_bg, "Phase: Easy", Point(495, 270), 0, 0.7, Scalar(0, 255, 0), 2);
break;
case 350:
cv::putText(defense_bg, "Phase: Mode", Point(495, 270), 0, 0.7, Scalar(0, 255, 0), 2);
break;
case 200:
cv::putText(defense_bg, "Phase: Diff", Point(495, 270), 0, 0.7, Scalar(0, 255, 0), 2);
break;
default:
break;
}
cv::putText(defense_bg, "Score: 0", Point(495, 220), 0, 0.7, Scalar(0, 255, 0), 2);
cv::putText(defense_bg, "A(left)", Point(530, 360), 0, 0.7, Scalar(0, 255, 0), 2);
cv::putText(defense_bg, "D(right)", Point(520, 405), 0, 0.7, Scalar(0, 255, 0), 2);
cv::putText(defense_bg, "J(Transform)", Point(495, 450), 0, 0.7, Scalar(0, 255, 0), 2);
rectangle(defense_bg, Rect(480, 0, 160, 480), Scalar(0, 255, 255), 4);
line(defense_bg, Point(480, 160), Point(640, 160), Scalar(0, 255, 255), 2);
line(defense_bg, Point(480, 320), Point(640, 320), Scalar(0, 255, 255), 2);
defense_fg = Mat(Size(480, 480), CV_8UC3, Scalar(0, 0, 0));
defense_fg_rect.x = 0;
defense_fg_rect.y = 0;
defense_fg_rect.width = 480;
defense_fg_rect.height = 480;
begin_block.x = 220;
begin_block.y = 0;
score = 0;
//初始化模块
Define_Block();
}
void Defense::Define_Block()
{
Mat merge_block(Size(20, 20), CV_8UC3, Scalar(0, 0, 0));
Mat block(Size(60, 40), CV_8UC3, Scalar(255, 255, 0));
line(block, Point(0, 20), Point(60, 20), Scalar(1, 0, 200), 2);
line(block, Point(20, 0), Point(20, 40), Scalar(1, 0, 200), 2);
line(block, Point(40, 0), Point(40, 40), Scalar(1, 0, 200), 2);
rectangle(block, Rect(0, 0, 60, 40), Scalar(1, 0, 200), 4);
Mat block2 = block.clone();
merge_block.copyTo(block2(Rect(0, 0, 20, 20)));
merge_block.copyTo(block2(Rect(40, 0, 20, 20)));
Mat block3 = block.clone();
merge_block.copyTo(block3(Rect(0, 0, 20, 20)));
merge_block.copyTo(block3(Rect(40, 20, 20, 20)));
Mat block3_flip = block3.clone();
flip(block3_flip, block3_flip, 1);
Mat block4 = block.clone();
merge_block.copyTo(block4(Rect(0, 0, 20, 20)));
merge_block.copyTo(block4(Rect(20, 0, 20, 20)));
Mat block4_flip = block4.clone();
flip(block4_flip, block4_flip, 1);
Mat block5(Size(80, 20), CV_8UC3, Scalar(255, 255, 0));
line(block5, Point(20, 0), Point(20, 20), Scalar(1, 0, 200), 2);
line(block5, Point(40, 0), Point(40, 20), Scalar(1, 0, 200), 2);
line(block5, Point(60, 0), Point(60, 20), Scalar(1, 0, 200), 2);
rectangle(block5, Rect(0, 0, 80, 20), Scalar(1, 0, 200), 4);
Mat block6(Size(40, 40), CV_8UC3, Scalar(255, 255, 0));
line(block6, Point(20, 0), Point(20, 40), Scalar(1, 0, 200), 2);
line(block6, Point(0, 20), Point(40, 20), Scalar(1, 0, 200), 2);
rectangle(block6, Rect(0, 0, 40, 40), Scalar(1, 0, 200), 4);
Mat block7 = block6.clone();
merge_block.copyTo(block7(Rect(0, 0, 20, 20)));
Mat block7_flip = block7.clone();
flip(block7_flip, block7_flip, 1);
Russia_block.push_back(block2);
Russia_block.push_back(block3);
Russia_block.push_back(block4);
Russia_block.push_back(block5);
Russia_block.push_back(block6);
Russia_block.push_back(block7);
Russia_block.push_back(block3_flip);
Russia_block.push_back(block4_flip);
Russia_block.push_back(block7_flip);
}
Mat Defense::Set_Random_Block()
{
srand(time(0));
int rand_num = rand() % Russia_block.size();
Mat select_block = Russia_block[rand_num];
return select_block;
}
bool Defense::Go_End(Rect current_position, Mat ¤t_block, int direction)
{
if (direction == 0)
{
current_position.height += 1;
Mat defense_fg_crop = defense_fg(current_position);
for (int row = current_block.rows - 1; row >= 0; row--)
{
for (int col = 0; col < current_block.cols; col++)
{
if (current_block.at<Vec3b>(row, col)[0] != 0)
{
if (defense_fg_crop.at<Vec3b>(row+1, col)[0] != 0)
return true;
}
}
}
}
else if (direction == 1)
{
current_position.x -= 1;
if (current_position.x < 0)
return true;
current_position.width += 1;
Mat defense_fg_crop = defense_fg(current_position);
for (int col = 0; col < current_block.cols; col++)
{
for (int row = 0; row < current_block.rows; row++)
{
if (current_block.at<Vec3b>(row, col)[0] != 0)
{
if (defense_fg_crop.at<Vec3b>(row, col-1)[0] != 0)
return true;
}
}
}
}
else if (direction == 2)
{
current_position.width += 1;
if (current_position.x + current_position.width > 480)
return true;
Mat defense_fg_crop = defense_fg(current_position);
for (int col = current_block.cols - 1; col >= 0; col--)
{
for (int row = 0; row < current_block.rows; row++)
{
if (current_block.at<Vec3b>(row, col)[0] != 0)
{
if (defense_fg_crop.at<Vec3b>(row, col+1)[0] != 0)
return true;
}
}
}
}
return false;
}
void Defense::Run()
{
Mat select_block = Set_Random_Block();
Mat select_block_next;
int first_nor = 0;
bool end_game = false;
while (true)
{
if (first_nor != 0)
select_block = select_block_next.clone();
first_nor = 1;
select_block_next = Set_Random_Block();
select_block_next.copyTo(defense_bg(Rect(530, 50, select_block_next.cols, select_block_next.rows)));
Mat defense_fg_cp;
int i = 0;
int down_x = begin_block.x;
int down_y;
while (true)
{
down_y = i * 20;
Rect current_position(down_x, down_y, select_block.cols, select_block.rows);
defense_fg_cp = defense_fg.clone();
Mat add_fg = defense_fg_cp(current_position) + select_block;
add_fg.copyTo(defense_fg_cp(current_position));
defense_fg_cp.copyTo(defense_bg(defense_fg_rect));
if (down_y + select_block.rows >= 480)
{
cv::imshow("Tetris", defense_bg);
char wait = cv::waitKey(difficult);
if (wait == 97 && !Go_End(current_position, select_block, 1))
{
down_x -= 20;
}
else if (wait == 100 && !Go_End(current_position, select_block, 2))
{
down_x += 20;
}
else
{
defense_fg = defense_fg_cp.clone();
break;
}
continue;
}
if (Go_End(current_position, select_block, 0))
{
if (current_position.y == 0)
{
end_game = true;
break;
}
defense_fg = defense_fg_cp.clone();
break;
}
i++;
cv::imshow("Tetris", defense_bg);
char wait = cv::waitKey(difficult);
if (wait == 97 && down_x > 0)
{
if (!Go_End(current_position, select_block, 1))
{
down_x -= 20;
i--;
}
}
else if (wait == 100 && down_x + select_block.cols < 480)
{
if (!Go_End(current_position, select_block, 2))
{
down_x += 20;
i--;
}
}
else if (wait == 106)
{
i--;
Mat select_block_convert = select_block.clone();
transpose(select_block_convert, select_block_convert);
flip(select_block_convert, select_block_convert, 1);
if (down_x + select_block_convert.cols > 480 || down_y + select_block_convert.rows > 480)
continue;
Mat block_merge = defense_fg(Rect(down_x, down_y, select_block_convert.cols, select_block_convert.rows));
bool merge_ = false;
for (int row = 0; row < block_merge.rows; row++)
{
for (int col = 0; col < block_merge.cols; col++)
{
if (select_block_convert.at<Vec3b>(row, col)[0] == 255 && block_merge.at<Vec3b>(row, col)[0] == 255)
{
merge_ = true;
break;
}
}
}
if (merge_)
continue;
select_block = select_block_convert.clone();
}
}
if (end_game) break;
vector<int> remove_line;
for (int row = defense_fg.rows - 1; row >= 0; row-=20)
{
int remove_count = 0;
for (int col = 0; col < defense_fg.cols; col+=20)
{
if (defense_fg.at<Vec3b>(row, col)[0] == 1)
{
remove_count++;
}
}
if (remove_count == defense_fg.cols/20)
{
remove_line.push_back(row - 19);
}
}
if (remove_line.size() > 0)
{
Mat defense_fg_move = defense_fg.clone();
Mat merge_move(Size(480, 20), CV_8UC3, Scalar(0, 0, 0));
for (int i = 0; i < remove_line.size(); i++)
{
merge_move.copyTo(defense_fg_move(Rect(0, remove_line[i], 480, 20)));
}
for (int i = 0; i < 3; i++)
{
defense_fg_move.copyTo(defense_bg(defense_fg_rect));
cv::imshow("Tetris", defense_bg);
cv::waitKey(100);
defense_fg.copyTo(defense_bg(defense_fg_rect));
cv::imshow("Tetris", defense_bg);
cv::waitKey(100);
}
defense_fg = defense_fg_move.clone();
vector<Mat> resort;
for (int row = defense_fg.rows - 20; row >= 0; row -= 20)
{
int same_count = 0;
for (int i = 0; i < remove_line.size(); i++)
{
if (row == remove_line[i])
{
same_count++;
break;
}
}
if (same_count == 0)
resort.push_back(defense_fg(Rect(0, row, 480, 20)));
}
for (int i = 0; i < 24 - resort.size(); i++)
{
resort.push_back(merge_move);
}
int which_line = defense_fg.rows - 20;
for (int row = 0; row < resort.size(); row++)
{
resort[row].copyTo(defense_fg(Rect(0, which_line, 480, 20)));
which_line -= 20;
}
defense_fg.copyTo(defense_bg(defense_fg_rect));
cv::imshow("Tetris", defense_bg);
cv::waitKey(100);
cv::putText(defense_bg, "Score: " + to_string(score), Point(495, 220), 0, 0.7, Scalar(0, 0, 0), 2);
score += remove_line.size() * (remove_line.size() + 1);
cv::putText(defense_bg, "Score: " + to_string(score), Point(495, 220), 0, 0.7, Scalar(0, 255, 0), 2);
}
Mat next_merge(Size(100, 100), CV_8UC3, Scalar(0, 0, 0));
next_merge.copyTo(defense_bg(Rect(530, 50, next_merge.cols, next_merge.rows)));
}
cv::putText(defense_bg, "Game Over!", Point(60, 240), 0, 2, Scalar(0, 0, 255), 8);
cv::imshow("Tetris", defense_bg);
cv::waitKey(0);
}
主函数:main.cpp
#include "defense.h"
int main()
{
Defense defense;
defense.Run();
return 0;
}
打完收工!
任何问题请加唯一QQ2258205918(名称samylee)!
或唯一VX:samylee_csdn