C++ 实现俄罗斯方块
C++ 实现俄罗斯方块
一、实验介绍
1.1 实验内容
本节实验我们进行设计俄罗斯方块前的思路分析,以及介绍ncurses 库的使用方法。
1.2 实验知识点
C++ 编程基础
ncurses 库的使用
俄罗斯方块逻辑设计
1.3 实验环境
xfce 终端
g++ 编译器
ncurses 库
1.4 适合人群
本课程难度一般,适合有 C++ 编程基础,对游戏设计、逻辑分析感兴趣的同学。
1.5 代码获取
git clone https://github.com/Gamerchen/game_zero.git
二、开发准备
2.1 安装 ncurses 库
sudo apt-get update
sudo apt-get install libncurses5-dev
2.2 编译程序
编译命令要加上 -l 选项引入 ncurses 库:
g++ main.cpp -l ncurses
三、实验原理
3.1 设计前的分析
在开始程序编写之前,我们要先分析程序设计需要实现哪些功能,划分为哪些模块,在俄罗斯方块中我们首先想到的应该是显示方块,其次是方块的下落,左右移动,旋转,最后的层满消行,另外一个基本的俄罗斯方块游戏还应该有下一个方块形状的提示功能。
所以我们编程中需要解决的问题有:
显示方块
实现方块的移动
方块旋转
对层满的方块消行
提示下一个方块形状
3.2 基本图形
每个方块由四个 box 组成,从游戏框的中心位置掉落,在框内不碰撞边界和其他方块的情况下可以进行旋转。
3.3 NCURSES库的使用
简单地说,NCURSES 是一个从 System V Release 4.0 (SVr4) 中 CURSES 的克隆,这是一个可自由配置的库,完全兼容旧版本的 CURSES,是一个可以使应用程序直接控制终端屏幕显示的库。NCURSES封装了底层的终端功能,包含了一些创建窗口的函数,并且有Menu、Panel 和 Form对CURSES基础库的扩展,我们可以建立一个同时包含多窗口(multiple windows)、菜单(menus)、面板(panels)和表单(forms)的应用程序。窗口可以被独立管理,例如让它卷动(scrollability)或者隐藏。 菜单(Menus)可以让用户建立命令选项,从而方便执行命令。而窗体(Forms)允许用户建立一些简单的数据输入和显示的窗口。面板(Panels)是 NCURSES 窗口管理功能的扩展,可以用它覆盖或堆积窗口。
3.3.1 NCURSES--从Hello World程序开始
如果调用 NCURSES 库中的函数,必须在代码中加载 ncurses.h 文件( ncurses.h中已经包含stdio.h ) 例:
#include <ncurses.h>
int main()
{
initscr(); //初始化,进入NCURSES模式
printw("Hello World!"); //在虚拟屏幕上打印 Hello Wowrld!
refresh(); //将虚拟屏幕上的内容写到显示器上,并刷新
getch(); //等待用户输入
endwin(); //退出NCURSES模式
return 0;
}
在以上实例中我们介绍了 NCURSES 库中最基本函数的使用方法,函数的功能已在注释中说明,这里不再赘述。
3.3.2 窗口机制
当 NCURSES 初始化的时候,它会默认创建一个叫做 stdscr 的窗口,大小一般是 80 列,25 行(根据显示器或者显卡的不同,可能会出现不同的大小),除此之外,你还可以通过窗口系统的函数创建你自己的窗口。 举例说明,如果调用以下函数:
printw("Hi!");
refresh();
它会在stdscr上当前光标位置输出 "Hi!",调用 refresh() 函数,只更新 stdscr 上的缓冲区。
如果你已经建立了一个叫做win的窗口,想要在win窗口上输出内容,可以再普通函数前添加w,同时参数也要发生变化。
printw(string) //在stdscr的当前光标位置打印字符串string
mvprintw(y,x,string) //将字符串string打印在坐标(y,x)处
wprintw(win,string) //在窗口win的当前光标位置打印字符串string
mvwprintw(win,y,x,string) //将光标移动到窗口win的(y,x)处然后打印字符串string
相信看完上面的例子,你已经能够通过函数的命名规则看出各个函数的功能区别
3.3.3 newwin和box函数
一个窗口的建立是通过 newwin() 函数开始的,函数返回一个指向窗口的结构指针,这个指针可以被传送至一些类似于 wprintw() 这样需要窗口参数的函数中。 然而,我们创建了一个窗口却无法看见它,需要用 box() 函数在已经定义的窗口外围画上边框。 例:
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
WINDOW *local_win;
local_win = newin(height, width, starty, startx);
box(local_win, 0, 0);
wrefresh(local_win);
return local_win;
}
关于 NCURSES 库的基本使用方法就介绍到这里了,在具体使用中遇到问题仍需要查阅相关资料。
c++实现俄罗斯方块代码
#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ncurses.h>
#include <unistd.h>
using namespace std;
void swap(int &a, int &b){
int t=a;
a = b;
b = t;
}
int getrand(int min, int max)
{
return(min+rand()%(max-min+1));
}
WINDOW *create_newwin(int height,int width,int starty,int startx);
void destory_win(WINDOW *local_win);
int game_win_height=30;
int game_win_width=45;
int hint_win_height=10;
int hint_win_width=20;
WINDOW * game_win, *hint_win ,*score_win;
int key;
class Piece
{
public:
int score;
int shape;
int next_shape;
int head_x;
int head_y;
int size_h;
int size_w;
int next_size_h;
int next_size_w;
int box_shape[4][4];
int next_box_shape[4][4];
int box_map[30][45];
bool game_over;
public:
void initial();
void set_shape(int &cshape, int box_shape[][4],int &size_w, int & size_h);
void score_next();
void judge();
void move();
void rotate();
bool isaggin();
bool exsqr(int row);
};
int main()
{
initscr();
//raw();
cbreak();
noecho();
curs_set(0);
keypad(stdscr,TRUE);
refresh();
game_win = create_newwin(game_win_height, game_win_width, 0,0);
wborder(game_win, '*', '*', '*', '*', '*', '*', '*', '*');
wrefresh(game_win);
hint_win = create_newwin(hint_win_height, hint_win_width, 0, game_win_width+10);
mvprintw(0, game_win_width+10+2,"%s","Next");
refresh();
score_win = create_newwin(hint_win_height, hint_win_width, 20, game_win_width+10);
mvprintw(20, game_win_width+10+2,"%s","Score");
refresh();
Piece* pp = new Piece;
pp->initial();
while(1)
{
pp->move();
if(pp->game_over)
break;
}
destory_win(game_win);
destory_win(hint_win);
destory_win(score_win);
delete pp;
system("clear");
int row,col;
getmaxyx(stdscr,row,col);
mvprintw(row/2,col/2 ,"%s","GAMER OVER ! \n ");
mvprintw(row/2+2,col/2-2 ,"%s","Wait 5s to return tthe erminal ! \n ");
refresh();
sleep(5);
endwin();
return 0;
}
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win,0,0);
wrefresh(local_win);
return local_win;
}
void destory_win(WINDOW *local_win)
{
wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh(local_win);
delwin(local_win);
}
void Piece::initial()
{
score=0;
game_over=false;
for(int i =0;i<game_win_height;i++)
for(int j=0;j<game_win_width;j++){
if(i==0 || i==game_win_height-1 || j==0 || j==game_win_width-1){
box_map[i][j]=1;
}
else
box_map[i][j]=0;
}
srand((unsigned)time(0));
shape=getrand(0,6);
set_shape(shape,box_shape,size_w,size_h);
next_shape=getrand(0,6);
set_shape(next_shape,next_box_shape,next_size_w,next_size_h);
for(int i =0;i<4;i++)
for(int j=0;j<4;j++)
if(next_box_shape[i][j]==1){
mvwaddch(hint_win,(hint_win_height-size_h)/2+i,(hint_win_width-size_w)/2+j,'#');
wrefresh(hint_win);
}
mvwprintw(score_win, hint_win_height/2,hint_win_width/2-2,"%d",score);
wrefresh(score_win);
}
void Piece::set_shape(int &cshape, int shape[][4],int &size_w,int &size_h)
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
shape[i][j]=0;
switch(cshape)
{
case 0:
size_h=1;
size_w=4;
shape[0][0]=1;
shape[0][1]=1;
shape[0][2]=1;
shape[0][3]=1;
break;
case 1:
size_h=2;
size_w=3;
shape[0][0]=1;
shape[1][0]=1;
shape[1][1]=1;
shape[1][2]=1;
break;
case 2:
size_h=2;
size_w=3;
shape[0][2]=1;
shape[1][0]=1;
shape[1][1]=1;
shape[1][2]=1;
break;
case 3:
size_h=2;
size_w=3;
shape[0][1]=1;
shape[0][2]=1;
shape[1][0]=1;
shape[1][1]=1;
break;
case 4:
size_h=2;
size_w=3;
shape[0][0]=1;
shape[0][1]=1;
shape[1][1]=1;
shape[1][2]=1;
break;
case 5:
size_h=2;
size_w=2;
shape[0][0]=1;
shape[0][1]=1;
shape[1][0]=1;
shape[1][1]=1;
break;
case 6:
size_h=2;
size_w=3;
shape[0][1]=1;
shape[1][0]=1;
shape[1][1]=1;
shape[1][2]=1;
break;
}
head_x=game_win_width/2;
head_y=1;
if(isaggin()) /* GAME OVER ! */
game_over=true;
}
void Piece::rotate()
{
int temp[4][4]={0};
int temp_piece[4][4]={0};
int i,j,tmp_size_h,tmp_size_w;
tmp_size_w=size_w;
tmp_size_h=size_h;
for(int i=0; i<4;i++)
for(int j=0;j<4;j++)
temp_piece[i][j]=box_shape[i][j];
for(i=0;i<4;i++)
for(j=0;j<4;j++)
temp[j][i]=box_shape[i][j];
i=size_h;
size_h=size_w;
size_w=i;
for(i=0;i<size_h;i++)
for(j=0;j<size_w;j++)
box_shape[i][size_w-1-j]=temp[i][j];
if(isaggin()){
for(int i=0; i<4;i++)
for(int j=0;j<4;j++)
box_shape[i][j]=temp_piece[i][j];
size_w=tmp_size_w;
size_h=tmp_size_h;
}
else{
for(int i=0; i<4;i++)
for(int j=0;j<4;j++){
if(temp_piece[i][j]==1){
mvwaddch(game_win,head_y+i,head_x+j,' ');
wrefresh(game_win);
}
}
for(int i=0; i<size_h;i++)
for(int j=0;j<size_w;j++){
if(this->box_shape[i][j]==1){
mvwaddch(game_win,head_y+i,head_x+j,'#');
wrefresh(game_win);
}
}
}
}
void Piece::move(){
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec= 500000;
if (select(1, &set, NULL, NULL, &timeout) == 0){
head_y++;
if(isaggin()){
head_y--;
for(int i=0;i<size_h;i++)
for(int j=0;j<size_w;j++)
if(box_shape[i][j]==1)
box_map[head_y+i][head_x+j]=1;
score_next();
}
else{
for(int i=size_h-1; i>=0;i--)
for(int j=0;j<size_w;j++){
if(this->box_shape[i][j]==1){
mvwaddch(game_win,head_y-1+i,head_x+j,' ');
mvwaddch(game_win,head_y+i,head_x+j,'#');
}
}
wrefresh(game_win);
}
}
if (FD_ISSET(0, &set)) {
while ((key = getch()) == -1) ;
if(key==KEY_LEFT){
head_x--;
if(isaggin())
head_x++; //undo
else{
for(int i=0; i<size_h;i++)
for(int j=0;j<size_w;j++){
if(this->box_shape[i][j]==1){
mvwaddch(game_win,head_y+i,head_x+j+1,' ');
mvwaddch(game_win,head_y+i,head_x+j,'#');
}
}
wrefresh(game_win);
}
}
if(key==KEY_RIGHT){
head_x++;
if(isaggin())
head_x--;
else{
for(int i=0; i<size_h;i++)
for(int j=size_w-1;j>=0;j--){
if(this->box_shape[i][j]==1){
mvwaddch(game_win,head_y+i,head_x+j-1,' ');
mvwaddch(game_win,head_y+i,head_x+j,'#');
}
}
wrefresh(game_win);
}
}
if(key==KEY_DOWN){
head_y++;
if(isaggin()){
head_y--;
for(int i=0;i<size_h;i++)
for(int j=0;j<size_w;j++)
if(box_shape[i][j]==1)
box_map[head_y+i][head_x+j]=1;
score_next();
}
else{
for(int i=size_h-1; i>=0;i--)
for(int j=0;j<size_w;j++){
if(this->box_shape[i][j]==1){
mvwaddch(game_win,head_y-1+i,head_x+j,' ');
mvwaddch(game_win,head_y+i,head_x+j,'#');
}
}
wrefresh(game_win);
}
}
if(key==KEY_UP)
rotate();
if(head_x+size_w+1>game_win_width)
head_x=game_win_width-size_w-1;
if(head_x<1)
head_x=1;
}
}
bool Piece::isaggin(){
for(int i=0;i<size_h;i++)
for(int j=0;j<size_w;j++){
if(box_shape[i][j]==1){
if(head_y+i > game_win_height-2)
return true;
if(head_x+j > game_win_width-2 || head_x+i-1<0)
return true;
if(box_map[head_y+i][head_x+j]==1)
return true ;
}
}
return false;
}
bool Piece::exsqr(int row){
for(int j=1;j<game_win_width-1;j++)
if(box_map[row][j]==1)
return true;
return false;
}
void Piece::judge(){
int i,j;
int line=0;
bool full;
for(i=1;i<game_win_height-1;i++){
full=true;
for(j=1;j<game_win_width-1;j++){
if(box_map[i][j]==0)
full=false;
}
if(full){
line++;
score+=50;
for(j=1;j<game_win_width-1;j++)
box_map[i][j]=0;
}
}
if(line!=0){
for(i=game_win_height-2;i>=2;i--){
int s=i;
if(exsqr(i)==0){
while(s>1 && exsqr(--s)==0);
for(j=1;j<game_win_width-1;j++){
box_map[i][j]=box_map[s][j];
box_map[s][j]=0;
}
}
}
for(int i=1;i<game_win_height-1;i++)
for(int j=1;j<game_win_width-1;j++){
if(box_map[i][j]==1){
mvwaddch(game_win,i,j,'#');
wrefresh(game_win);
}
else{
mvwaddch(game_win,i,j,' ');
wrefresh(game_win);
}
}
}
}
void Piece::score_next(){
score+=10;
judge();
mvwprintw(score_win, hint_win_height/2,hint_win_width/2-2,"%d",score);
wrefresh(score_win);
set_shape(next_shape,box_shape,size_w,size_h);
this->next_shape=getrand(0,6);
set_shape(next_shape,next_box_shape,next_size_w,next_size_h);
for(int i =1;i<hint_win_height-1;i++)
for(int j=1;j<hint_win_width-1;j++){
mvwaddch(hint_win, i, j,' ');
wrefresh(hint_win);
}
for(int i =0;i<4;i++)
for(int j=0;j<4;j++)
if(next_box_shape[i][j]==1){
mvwaddch(hint_win,(hint_win_height-size_h)/2+i,(hint_win_width-size_w)/2+j,'#');
wrefresh(hint_win);
}
}
运行如下 有点low 基本功能都有
运行结果.jpg
C++ 实现俄罗斯方块的更多相关文章
- 还是俄罗斯方块之android版
前面的,口水话 请直接跳过. 虽然现在不比以前了 也没多少人气了,放到首页 都不到几百的点击量.也许博客园整体水平也是在往水的方向发展.不谈那些了,哥也曾经辉煌过 有过一天上千的点击量 ,哥也曾经有过 ...
- x01.Tetris: 俄罗斯方块
最强大脑有个小孩玩俄罗斯方块游戏神乎其技,那么,就写一个吧,玩玩而已. 由于逻辑简单,又作了一些简化,所以代码并不多. using System; using System.Collections.G ...
- 俄罗斯方块C#版
using System; using System.Windows.Forms; using System.Drawing; using System.Media; class me : Form ...
- 纯JS实现俄罗斯方块,打造属于你的游戏帝国
纯JS俄罗斯方块,打造属于你的游戏帝国. 本文原始作者博客 http://www.cnblogs.com/toutou 俄罗斯方块(Tetris, 俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏 ...
- 用纯JS做俄罗斯方块 - 简要思路介绍(1)
大家都知道俄罗斯方块是一款大众化的游戏了,我很小的时候就玩过,今年已经25岁了,可以说俄罗斯方块确实是历史悠久,做俄罗斯方块是我上个星期开始的想法.也许是由于自己从来没有写过这种东西吧,所以有生疏.代 ...
- 趣味python编程之经典俄罗斯方块
国庆期间闲不住,用python把经典俄罗斯方块实现了一遍,找到了些儿时的乐趣.因此突发奇想,打算用python写点经典又确实有趣的小程序形成系列.正统编程之余也给自己找点儿乐趣,换个角度写程序. 原计 ...
- javascript俄罗斯方块游戏
在线试玩:http://keleyi.com/game/5/ 操作指南:键盘方向键←→控制左右移动,↑键变形,↓键快速下落. 别看这段js代码只有短短的100多行,效果却非常不错,用键盘的方向键操作, ...
- 俄罗斯方块(Win32实现,Codeblocks+GCC编译)
缘起: 在玩Codeblocks自带的俄罗斯方块时觉得不错,然而有时间限制.所以想自己再写一个. 程序效果: 主要内容: 程序中有一个board数组,其中有要显示的部分,也有不显示的部分,不显示的部分 ...
- CCF 201604-2 俄罗斯方块
题目不难,但是感觉很有意思.一开始忘了把调试信息注释掉,WA了两次... 试题编号: 201604-2 试题名称: 俄罗斯方块 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 ...
- Javascript 俄罗斯方块 游戏代码解释!
俄罗斯方块代码说明 /** 名称:Javascript 俄罗斯方块! 作者:Gloot 邮箱:glootz@gmail.com QQ:345268267 网站:http://www.cnblogs.c ...
随机推荐
- 大数据学习总结(6)what is our foucus
1.搜索业务 2.画像业务 3.关系图谱 借助es构建搜索.画像和关系图谱
- SpringCloud的Archaius - 动态管理属性配置
参考链接:http://www.th7.cn/Program/java/201608/919853.shtml 一.Archaius是什么? Archaius用于动态管理属性配置文件. 参考自Gett ...
- Python大婶博客汇总
Python大神金星 博客:http://www.cnblogs.com/jin-xin/articles/7459977.html
- RxJava系列5(组合操作符)
RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...
- Windows10+Docker搭建分布式Redis集群(一)
摘要,Docker for Windows 仅支持专业版 目录 第一步:检查系统支持虚拟化 第二步:下载Docker对应版本 第三步:配置镜像加速 第一步:检查系统是否支持虚拟化 Docker前提是需 ...
- Python/ MySQL练习题(一)
Python/ MySQL练习题(一) 查询“生物”课程比“物理”课程成绩高的所有学生的学号 SELECT * FROM ( SELECT * FROM course LEFT JOIN score ...
- VMwaretools、共享文件夹、全屏
VMware12.1 + Ubuntu14.04 + win10专业版 设置 共享文件夹和解决Ubuntu全屏问题. 我实在不喜欢这种敲敲打打的工作,不喜欢这种有点无聊的配置环境.我喜欢 ...
- ABP框架 - N层架构
目录 介绍 DDD分层 ABP架构模型 客户端 展现层 分布式服务层 应用层 领域层 基础设施层 介绍 在应用程序设计中,分层架构是一种被广泛使用的技术,它助于降低复杂度和提高代码的可重用性.在ABP ...
- Java 静态内部类注意点
静态内部类(嵌套类)的对象除了没有对生成它的外部类对象的引用特权外,与其他所有内部类完全一样. 在内部类不需要访问外部类时,应该使用静态内部类(嵌套类). 与常规内部类不同的是,静态内部类可以拥有静态 ...
- [LeetCode] Set Intersection Size At Least Two 设置交集大小至少为2
An integer interval [a, b] (for integers a < b) is a set of all consecutive integers from a to b, ...