记录一下我的成长历程,这是我学了C++之后,写的第一个程序,虽然比较简陋,但也不想改了,有兴趣的小伙伴可以参考一下。

#include<iostream>
#include<windows.h>
#include<conio.h>//使用getch()函数
#include<ctime>
#include <stdio.h>using namespace std;
HANDLE handle;
COORD crd;//坐标
const short LMARGIN = 7;//方块掉落范围的左边界
const short TMARGIN = 5;//方块掉落范围的上边界
char type[19][17] =
{//方块种类"1100011000000000","0010011001000000",//Z型"0110110000000000","0100011000100000",//S型"0000111100000000","0100010001000100",//I型"0000011001100000",//方型"0100111000000000","0100110001000000","1110010000000000","1000110010000000",//T型"0010111000000000","0110001000100000","1110100000000000","0100010001100000",//L型"1000111000000000","0010001001100000","1110001000000000","0110010001000000"//J型
};
char rotate_hinder[19][17] =
{//方块旋转受阻位置"0010000001100000","1100000000100000",//Z型"0000001011100000","0010100011000000",//S型"1111000001110111","1011101100110011",//I型"0000000000000000",//方型"1010000011000000","1010001000100000","0000100010000000","0100001001100000",//T型"0100000011100000","1000110000000000","0000010011100000","1010101000000000",//L型"0110000011100000","1010101000100000","0000110011000000","1000101000100000"//J型
};
short Alter(short n)//旋转函数
{switch (n){case 1:case 3:case 5:return n - 1; break;case 6:return 6; break;case 10:case 14:case 18:return n - 3; break;default:return n + 1; break;}
}
void SetPos(short x, short y)//坐标函数
{crd.X = x; crd.Y = y;SetConsoleCursorPosition(handle, crd);
}
void SetColor(short front, short back)//颜色
{SetConsoleTextAttribute(handle, front + back * 0x10);
}
void PrintGameOver()
{SetPos(12, 9);SetColor(5, 6);cout << "Game Over!";SetColor(7, 0);
}
class Score
{private:short ln;//得分
public:void Reset() { ln = 0; }void Print(){SetPos(4, 1);SetColor(2, 7);cout << "Lines: " << ln << " ";SetColor(7, 0);}Score() { Reset(); }void Update(short n) { ln += n; }
};
class Shape//方块类
{private:short present;//当前形状short color;short x;//左上角横坐标short y;//左上角纵坐标
public:Shape(short, short, short);//颜色、坐标void Draw(bool, bool);//第一个参数为真执行绘制操作,为假执行擦除;第二个参数为真按方块颜色画,为假画成白色friend class Board;bool Rotate(Board& brd);//判断方块能否旋转,如果能则旋转并返回真,如果不能旋转则返回假short Collision(Board& brd);//左侧,右侧,下方受阻时,返回值分别“位或”1,2,4bool Move(short, Board& brd);//左移动第一个参数为1,右移动第一个参数为2bool Fall(Board& brd);//能下落返回true,不能下落返回falsevoid DrawElseWhere(short _x, short _y);//在操作区外面显示一个方块的初始形状
};
class Board//游戏框类
{private:bool wall[22][14];short bottom_line;//保存当前可以消除的最下面一行的行号
public:void Clear()//重置数组元素的值{for (short i = 0; i < 22; i++)for (short j = 0; j < 14; j++)if (j > 1 && j < 12 && i < 20)wall[i][j] = 0;elsewall[i][j] = 1;}Board() { Clear(); }void DrawBoard(){short i;SetColor(0xe, 0);//十进制的14for (i = 0; i < 21; i++)//绘制左边界{SetPos(LMARGIN - 2, TMARGIN + i - 1);cout << "■";}for (i = 0; i < 21; i++){SetPos(LMARGIN + 20, TMARGIN + i - 1);cout << "■";}for (i = 0; i < 10; i++){SetPos(LMARGIN + i * 2, TMARGIN + 19);cout << "■";}SetColor(7, 0);}short SetBlocValue(Shape& shp)//对wall数组的值更新{for (short i = 0; i < 16; i++)if (type[shp.present][i] == '1'){if (shp.y == 0)//检查游戏有没有结束return -1;wall[shp.y + i / 4][shp.x + i % 4] = true;}return 0;}short Drop(Shape& shp)//返回可以消除的行数{short i, n;//i用于遍历方块所在的16个字符,n用来保存检测过的被方块占用的格子数short j;//用于遍历一整行检查是否有wall数组的元素为falseshort k;//用于从上往下逐行往下覆盖short y, _y = -1;//y用于保存当前格子的行号,_y用于保存前一个格子的行号,初始化一个不合理值,确保第一轮对比不相等short lines = 0;//保存了消除多少排short top;//用于检测有没有遍历到堆积块的顶部short l;//在覆盖的操作当中从左到右遍历for (i = 0, n = 0; n < 4 && i < 16; i++){if (type[shp.present][i] == '1'){y = shp.y + i / 4;n++;if (y == _y)//两个格子处于同一横排不必进行两次消除判断continue;_y = y;for (j = 2; j < 12; j++)if (!wall[y][j])break;if (j == 12)//一整排已经填满,应消除{lines++;for (k = y; k > 0; k--){top = 0;for (l = 2; l < 12; l++){wall[k][l] = wall[k - 1][l];top += wall[k - 1][l];}if (top == 0)break;//终止从上到下的遍历}}}}bottom_line = _y;return lines;}void DrowPile()//重绘堆积块,有bottom_line指定需要重绘的最下面一行{for (short i = 0; i <= bottom_line; i++)//行遍历{for (short j = 2; j < 12; j++)//列遍历{SetPos(LMARGIN - 4 + j * 2, TMARGIN - 1 + i);if (wall[i][j]){SetColor(7, 7);//白色用于绘出cout << "□";}else{SetColor(0, 0);//黑色用于擦除cout << "  ";}}}}friend class Shape;
};
Shape::Shape(short _color, short _x = 5, short _y = 0) :color(_color), x(_x), y(_y)
{switch (_color){case 1:present = 0; break;case 2:present = 2; break;case 3:present = 4; break;case 4:present = 6; break;case 5:present = 7; break;case 6:present = 11; break;default:color = 8; present = 15; break;}
}
void Shape::Draw(bool flag = true, bool active = true)
{if (!flag)//擦除SetColor(0, 0);elseif (active)SetColor(color, color);//按方块颜色画elseSetColor(7, 7);//落地方块画成白色for (short i = 0; i < 16; i++)if (type[present][i] == '1'){SetPos(LMARGIN - 4 + (x + i % 4) * 2, TMARGIN + y + i / 4 - 1);cout << "□";}SetColor(7, 0);
}
bool Shape::Rotate(Board& brd)
{for (short i = 0; i < 16; i++){if (brd.wall[y + i / 4][x + i % 4] && rotate_hinder[present][i] == '1')//如果格局中的一个位置被占用,并且这个位置能阻碍旋转return false;}Draw(false);present = Alter(present);Draw();return true;
}
short Shape::Collision(Board& brd)
{short result = 0;for (short i = 0; i < 16; i++){if (type[present][i] == '1')//该格子被当前方块占用{if (brd.wall[y + i / 4][x + i % 4 - 1])result |= 1;//左受阻if (brd.wall[y + i / 4][x + i % 4 + 1])result |= 2;//右受阻if (brd.wall[y + i / 4 + 1][x + i % 4])result |= 4;//下受阻}}return result;
}
bool Shape::Move(short direction, Board& brd)
{if (direction == 1 && !(Collision(brd) & 1))//表达式Collision(brd)&1为0,说明左侧没有受阻,取反之后条件为true{Draw(false, true);x--;Draw();return true;}if (direction == 2 && !(Collision(brd) & 2))//表达式Collision(brd)&2为0,说明右侧没有受阻,取反之后条件为true{Draw(false, true);x++;Draw();return true;}return false;
}
bool Shape::Fall(Board& brd)
{if (Collision(brd) & 4)//已经着地{Draw(true, false);return false;}Draw(false, true);y++;Draw();return true;
}
void Shape::DrawElseWhere(short _x, short _y)
{short i;SetPos(_x, _y);SetColor(7, 0);cout << "Next: ";_x += 6;SetColor(0, 0);SetPos(_x, _y);for (i = 0; i < 12; i++)//擦除上一个方块,方块的初始形状不会占据最后一行,只需要遍历12格就行{SetPos(_x + i % 4 * 2, _y + i / 4);cout << "  ";}SetColor(color, color);_y -= (present == 6 || present == 4);//将方块和棍子形状向上提升一格for (i = 0; i < 12; i++)//绘制下一个方块{if (type[present][i] == '1'){SetPos(_x + i % 4 * 2, _y + i / 4);cout << "□";}}
}
short Menu()//菜单函数,选中开始游戏返回1,离开返回2
{short choice = 1;char c;//记录按键信息system("cls");SetPos(9, 12);cout << "┌────────────────┐";SetPos(9, 13);cout << "│ 俄 罗 斯 方 块 │";SetPos(9, 14);cout << "└────────────────┘";SetPos(7, 21);cout << "按下方向键控制方块";SetPos(7, 23);cout << "按空格键暂停/继续";while (1){SetPos(15, 16);if (choice == 1)SetColor(2, 7);elseSetColor(2, 0);cout << "开始游戏";SetPos(15, 18);if (choice == 2)SetColor(2, 7);elseSetColor(2, 0);cout << "离    开";c = _getch();if (c == 13)break;else if (c == 0)//没有这条语句的话,按下方向键,循环体会执行两遍c = _getch();//方向键比较特殊,第一次获取c的值为0,第二次才是72,或者80if (c == 72 || c == 80)choice = choice == 1 ? 2 : 1;}SetColor(7, 0);return choice;
}int main()
{system("mode con cols=35 lines=27");//设置控制台尺寸handle = GetStdHandle(STD_OUTPUT_HANDLE);Board board;short tmp;//用来保存一个方块消去的行数Shape* shp, * shp_next;Score score;short times;//用于保存执行Sleep函数的次数srand(time(0));char c;//用于记录按键信息while (Menu() == 1)//一次游戏的过程{system("cls");board.Clear();board.DrawBoard();score.Reset();//得分归零score.Print();//显示得分shp_next = new Shape(rand() % 7 + 1);while (1)//一个方块落地的过程{shp = shp_next;//将下一个方块赋给当前方块shp_next = new Shape(rand() % 7 + 1);//新产生下一个方块shp_next->DrawElseWhere(17, 1);//显示下一个方块times = 0;while (1)//捕捉一次按键的过程,循环10次下落一格{shp->Draw();if (GetAsyncKeyState(VK_LEFT) == -32767)//VK_LEFT是左方向键的虚拟键码shp->Move(1, board);if (GetAsyncKeyState(VK_RIGHT) == -32767)//VK_RIGHT是右方向键的虚拟键码shp->Move(2, board);if (GetAsyncKeyState(VK_UP) == -32767)//VK_UP是上方向键的虚拟键码shp->Rotate(board);if (GetAsyncKeyState(VK_DOWN) == -32767)//VK_DOWN是下方向键的虚拟键码shp->Fall(board);if (GetAsyncKeyState(VK_SPACE) == -32767)//空格键暂停{while (!(GetAsyncKeyState(VK_SPACE) == -32767))//没有按下空格键延时25毫秒继续循环,再次按下空格键继续Sleep(25);}Sleep(25);//延时times++;if (times == 10){times = 0;if (!shp->Fall(board))break;}}if (board.SetBlocValue(*shp) == -1){PrintGameOver();fflush(stdin);//清空输入流while ((c = getchar()) != '\n' && c != EOF);delete shp_next;break;}if (tmp = board.Drop(*shp)){board.DrowPile();score.Update(tmp);//累加得分score.Print();//显示得分}//.........delete shp;}}return 0;
}

传送门:

C++小游戏——俄罗斯方块相关推荐

  1. 鸿蒙小游戏-俄罗斯方块

    作者:225王宗振 前言 为了更好地熟练掌握鸿蒙手机应用开发,查阅资料和算法尝试开发鸿蒙小游戏--俄罗斯方块. 概述 完成鸿蒙小游戏APP在手机上的编译在项目中所使用到的软件为DevEco Studi ...

  2. 原生js小游戏——俄罗斯方块

    还记得童年时期的小游戏俄罗斯方块吗?我发现用js就可以写出来 页面效果如下: 具体代码如下: 首先展示css样式: .c {margin: 1px;width: 19px;height: 19px;b ...

  3. python tkinter火柴人_用Python实现童年小游戏俄罗斯方块!别说还挺好玩!

    原标题:用Python实现童年小游戏俄罗斯方块!别说还挺好玩! 前言 大三上学期的程序设计实训大作业,挑了其中一个我认为最简单的的<图书管理系统>来写.用python写是因为py有自带的G ...

  4. Java小游戏-俄罗斯方块

    摘 要 随着时代的不断发展,个人电脑也在不断普及,一些有趣的桌面游戏已经成为人们在使用计算机进行工作或工作之余休闲娱乐的首选,从最开始的Windows系统自带的黑白棋.纸牌.扫雷等游戏开始,到现在目不 ...

  5. python实现小游戏论文_用Python实现童年小游戏俄罗斯方块

    在那个电子产品比较匮乏的年代,小游戏机 还是为数不多的游戏类电子产品,对小孩子更是有着不可抗拒的魔力,在当时如果哪个小孩买了一个小游戏机,大伙一定迅速围上去... 俄罗斯方块作为其中一款小游戏,尽管规 ...

  6. 【Python教你一招】用Python实现童年小游戏俄罗斯方块

    学习素材与源码在Python学习交流群:733089476 获取 在那个电子产品比较匮乏的年代,小游戏机还是为数不多的游戏类电子产品,对小孩子更是有着不可抗拒的魔力,在当时如果哪个小孩买了一个小游戏机 ...

  7. Eclipse小游戏-俄罗斯方块

    个人写的Eclipse小游戏,大家代码写累了,可以拿来玩玩. 分为两个部分,一个是eclipse插件,直接将jar包放到eclipse的drops目录下,重启eclipse就可生效:另外还弄了个Ser ...

  8. Pascal小游戏 俄罗斯方块怀旧版

    俄罗斯方块怀旧版(注释版) {$APPTYPE GUI} {$MODE DELPHI} program WinPiece; uses Windows; const AppName = 'WinPiec ...

  9. python小游戏——俄罗斯方块

    最近研究pygame游戏制作板块,本次对于简单的俄罗斯方块进行介绍. 1.首先引入我们需要用到的pygame库和random库(pygame库基础知识请移步首页) import pygame impo ...

  10. C语言小游戏----俄罗斯方块

    游戏介绍: 1. 按方向键的左右键可实现方块的左右移动. 2. 按方向键的下键可实现方块的加速下落. 3. 按空格键可实现方块的顺时针旋转. 4. 按Esc键可退出游戏. 5. 按S键可暂停游戏,暂停 ...

最新文章

  1. $‘\r‘: command not found解决方法
  2. matlab RBF 神经网络拟合
  3. k8s1.5.4挂载volume之nfs
  4. linux 视频编辑 ffmpeg,ffmpeg转码视频真的好用!(ffmpeg的简单使用方法)
  5. Cesium + Vue 点击获取经纬度 气泡窗(三)
  6. zktime 协议_中控考勤机对接信呼帮助(中控ZKTime5.0系统软件版)
  7. 输出信噪比公式_关于信噪比SNR
  8. 支持jsp、php的免费空间
  9. HCIA-Day_04-链路状态协议OSPF PPP
  10. 向武 清华大学 计算机,哥哥保送弟弟全市第二 双胞胎同时上清华(组图)
  11. 已解决 vmware 虚拟机安装后没有虚拟网卡问题
  12. USB HID Class 的具体应用
  13. https ssl单项认证和双向认证以及证书生成
  14. 云计算机英语怎么说,云用英语怎么说
  15. linux学习笔记-rsync原理及使用
  16. JAVA8中并发类CompletableFuture使用遇到的坑-守护线程
  17. 4511或74LS48来实现BCD转7段数码管及逻辑状态输入演示
  18. python中average什么意思_用numpy.average()做加权平均,结果是nan?
  19. 加载google Z-Xing库实现二维码解析与生成,并将解析结果在另一页面显示
  20. 数据说话:现在是牛市还是熊市?

热门文章

  1. MOD13Q1数据最大合成NDVI数据
  2. 在医疗行业中,FPGA扮演什么角色?
  3. centos7部署prometheus+exporter+grafana+Alertmanager+企业微信
  4. ros安装教程unbuntu20.04
  5. TIF 和Hdmi cec hotplug热插拔事件过程梳理一
  6. 解决搜狗输入法ctrl+shift+z 和phpstorm冲突的问题
  7. WP微信机器人插件v2(更新)
  8. afe模拟前端的重要性_模拟前端afe的作用
  9. android测试命令大全,Android 测试之 adb 常用命令
  10. Android自定义键盘的几个小点