C++程序设计:俄罗斯方块(模拟方块下落,经典问题)

【问题描述】

  俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
  游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
  在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
  具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。

【输入形式】

  输入的前15行包含初始的方格图,每行包含10个数字,相邻的数字用空格分隔。如果一个数字是0,表示对应的方格中没有方块,如果数字是1,则表示初始的时候有方块。输入保证前4行中的数字都是0。
  输入的第16至第19行包含新加入的板块的形状,每行包含4个数字,组成了板块图案,同样0表示没方块,1表示有方块。输入保证板块的图案中正好包含4个方块,且4个方块是连在一起的(准确的说,4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
  第20行包含一个1到7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是16至19行所输入的板块图案,如果板块图案的最左边一列全是0,则它的左边和实际所表示的板块的左边是不一致的(见样例)

【输出形式】

  输出15行,每行10个数字,相邻的数字之间用一个空格分隔,表示板块下落后的方格图。注意,你不需要处理最终的消行。

【样例输入】

  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 1 0 0
  0 0 0 0 0 0 1 0 0 0
  0 0 0 0 0 0 1 0 0 0
  1 1 1 0 0 0 1 1 1 1
  0 0 0 0 1 0 0 0 0 0
  0 0 0 0
  0 1 1 1
  0 0 0 1
  0 0 0 0
  3

【样例输出】

  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0 1 0 0
  0 0 0 0 0 0 1 0 0 0
  0 0 0 0 0 0 1 0 0 0
  1 1 1 1 1 1 1 1 1 1
  0 0 0 0 1 1 0 0 0 0

#include <iostream>
using namespace std;
int main() {
	int a[15][10];//初始方格图 
	int i,j;
	for(i=0; i<15; i++)
		for(j=0; j<10; j++)
			cin>>a[i][j];
	int b[4][4];//下落中的板块 
	for(i=0; i<4; i++)
		for(j=0; j<4; j++)
			cin>>b[i][j];
	int place;//下落板块的左右位置(横坐标,题目中从1开始)
	cin>>place;
	int step;//下落板块的上下位置(纵坐标,设为从1开始)
	for(step=1; step<16; step++)
		for(i=step-1; i<step+3; i++) //step从1开始,对应于数组从0开始 
			for(j=place-1; j<place+3; j++) //place从1开始,对应于数组从0开始 
				//一步步模拟下落,直至发生冲突(同一位置两个1) 
				if(a[i][j]+b[i-(step-1)][j-(place-1)]==2)
					goto here;
here:
	//回退一步,即为最终位置 
	step-=1;
	for(i=step-1; i<step+3; i++)
		for(j=place-1; j<place+3; j++)
			if (b[i-step+1][j-place+1]==1)
				//计算最终方格图 
				a[i][j]=b[i-step+1][j-place+1];
	for(i=0; i<15; i++) {
		for(j=0; j<10; j++)
			cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 游戏需求 随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,设置几个关卡,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。 2.游戏界面需求: 良好的用户界面,有关数显示和分数显示,以及下一个方块显示。让方块在一定的区域内运动和变形,该区域用一种颜色表明 。还需用另一种颜色把该区域围起来,宽度适中,要实现美感。 3.游戏形状(方块)需求: 良好的方块形状设计,绘制七种见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。 4.输入与输出: 用户根据需要输入上(输出旋转效果)、左右(输出移动效果)、下(输出加速下沉效果)、空格(沉底)、P(暂停)、ESC(退出)。 2.游戏界面需求: 良好的用户界面,有关数显示和分数显示,以及下一个方块显示。让方块在一定的区域内运动和变形,该区域用一种颜色表明 。还需用另一种颜色把该区域围起来,宽度适中,要实现美感。 3.游戏形状(方块)需求: 良好的方块形状设计,绘制七种见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。 4.输入与输出: 用户根据需要输入上(输出旋转效果)、左右(输出移动效果)、下(输出加速下沉效果)、空格(沉底)、P(暂停)、ESC(退出)。
俄罗斯方块是一款经典的游戏,使用C++编写一个俄罗斯方块的程序需要以下几个步骤: 1. 定义方块的形状和颜色,可以使用二维数组来表示方块的形状,使用颜色量来表示方块的颜色。 2. 定义游戏区域,可以使用二维数组来表示游戏区域,每个格子可以用一个数字来表示是否有方块。 3. 定义方块的移动和旋转函数,可以使用键盘事件来控制方块的移动和旋转。 4. 定义方块下落函数,可以使用定时器来控制方块下落速度。 5. 定义消除行的函数,当一行被填满时,将该行消除,并将上面的方块下移一行。 6. 定义游戏结束的函数,当方块无法下落时,游戏结束。 下面是一个简单的C++俄罗斯方块程序的代码示例: ```c++ #include <iostream> #include <conio.h> #include <windows.h> using namespace std; const int WIDTH = 10; const int HEIGHT = 20; const int BLOCK_SIZE = 20; const int COLORS[] = {0x000000, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF}; int board[HEIGHT][WIDTH] = {0}; int shapes[7][4][4] = { {{0,0,0,0}, {1,1,,1}, {0,0,0,0}, {0,0,0,0}}, {{0,0,0,0}, {0,2,2,0}, {0,2,2,0}, {0,0,0,0}}, {{0,0,0,0}, {0,3,3,0}, {3,3,0,0}, {0,0,0,0}}, {{0,0,0,0}, {0,4,4,0}, {0,0,4,4}, {0,0,0,0}}, {{0,0,0,0}, {0,5,0,0}, {5,5,5,0}, {0,0,0,0}}, {{0,0,0,0}, {0,6,0,0}, {0,6,6,0}, {0,0,6,0}}, {{0,0,0,0}, {0,7,0,0}, {0,7,7,7}, {0,0,0,0}} }; struct Point { int x, y; }; void drawBlock(int x, int y, int color) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, color); for (int i = 0; i < BLOCK_SIZE; i++) { for (int j = 0; j < BLOCK_SIZE; j++) { cout << " "; } cout << endl; } SetConsoleTextAttribute(hConsole, 0x0007); } void drawBoard() { for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (board[i][j] != 0) { drawBlock(j * BLOCK_SIZE, i * BLOCK_SIZE, COLORS[board[i][j]]); } } } } bool checkCollision(int shape[4][4], int x, int y) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (shape[i][j] != 0) { int px = x + j; int py = y + i; if (px < 0 || px >= WIDTH || py >= HEIGHT) { return true; } if (py >= 0 && board[py][px] != 0) { return true; } } } } return false; } void placeShape(int shape[4][4], int x, int y, int color) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (shape[i][j] != 0) { int px = x + j; int py = y + i; board[py][px] = color; } } } } void removeShape(int shape[4][4], int x, int y) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (shape[i][j] != 0) { int px = x + j; int py = y + i; board[py][px] = 0; } } } } void rotateShape(int shape[4][4]) { int temp[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { temp[i][j] = shape[i][j]; } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { shape[i][j] = temp[3-j][i]; } } } void clearLines() { int lines = 0; for (int i = HEIGHT-1; i >= 0; i--) { bool full = true; for (int j = 0; j < WIDTH; j++) { if (board[i][j] == 0) { full = false; break; } } if (full) { lines++; for (int k = i; k > 0; k--) { for (int j = 0; j < WIDTH; j++) { board[k][j] = board[k-1][j]; } } for (int j = 0; j < WIDTH; j++) { board[0][j] = 0; } i++; } } } bool gameOver() { for (int j = 0; j < WIDTH; j++) { if (board[0][j] != 0) { return true; } } return false; } int main() { int shapeIndex = rand() % 7; int shape[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { shape[i][j] = shapes[shapeIndex][i][j]; } } Point pos = {WIDTH/2-2, 0}; int color = shapeIndex + 1; bool running = true; while (running) { if (kbhit()) { char key = getch(); if (key == 'a' && !checkCollision(shape, pos.x-1, pos.y)) { pos.x--; } if (key == 'd' && !checkCollision(shape, pos.x+1, pos.y)) { pos.x++; } if (key == 's' && !checkCollision(shape, pos.x, pos.y+1)) { pos.y++; } if (key == 'w') { int temp[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { temp[i][j] = shape[i][j]; } } rotateShape(temp); if (!checkCollision(temp, pos.x, pos.y)) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { shape[i][j] = temp[i][j]; } } } } if (key == 'q') { running = false; } } if (checkCollision(shape, pos.x, pos.y+1)) { placeShape(shape, pos.x, pos.y, color); clearLines(); if (gameOver()) { running = false; } shapeIndex = rand() % 7; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { shape[i][j] = shapes[shapeIndex][i][j]; } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值