C语言实现俄罗斯方块游戏

文章目录

    • 1 前言
    • 2 游戏截图
    • 3 源代码

1 前言

本文介绍的是我空闲时间用C语言写的一个俄罗斯方块游戏,整个程序只有一个文件,实现了基本的游戏功能,但还是有些缺陷,希望有心之士能够继续完善,感谢各位!

2 游戏截图

请注意!a、d、s、w都是小写

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3 源代码

/*
author: New_Teen
time: 2023.11.2 20:14 周四
IDE: visual studio 2019
俄罗斯方块
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <stdbool.h>
#include <conio.h>#define BOARD_CUBE ' '
#define WIDTH 15
#define HEIGHT 15
#define FLUSH_RATE 200char curr_cube;
int curr_square;
int curr_x, curr_y;
int score = 0;
int start_number = 0;
char board[HEIGHT][WIDTH];
int tmp[4][2];
int square[5][4][4] = { {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},{{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}} };void init_board(); //初始化游戏面板
void clear_board(); //清空控制台
void delay_board(); //延时
void print_board(); //打印游戏面板
void init_square(); //初始化方块
void drop_square(); //方块默认下落
void update_board(); //更新游戏面板
bool is_collision_left(); //检测方块左侧是否碰撞
bool is_collision_right(); //检测方块右侧是否碰撞
bool is_collision_bottom(); //检测方块下方是否碰撞
bool is_collsion_rotate(); //检测方块是否可以旋转
bool is_game_over(); //检测游戏是否结束
void rotate(); //旋转方块
void rush_board(); //消除成层方块(得分)
void start_game(); //游戏开始面板int main() {srand((unsigned)time(NULL)); //根据程序执行时间产生随机数种子start_game();init_board();while (1) {init_square();if (is_game_over())break;for (;;) {if (!is_collision_bottom())drop_square();elsebreak;if (_kbhit()) {char ch = _getch();if (ch == 'a' && !is_collision_left())curr_x--;else if (ch == 'd' && !is_collision_right())curr_x++;else if (ch == 's' && !is_collision_bottom())curr_y++;else if (ch == 'w' && !is_collsion_rotate())rotate();}update_board();rush_board();print_board();delay_board();clear_board();}}printf("Game over!!\nYour score is %d\n", score);return 0;
}void init_board() {for (int i = 0; i < HEIGHT; ++i)for (int j = 0; j < WIDTH; ++j)board[i][j] = BOARD_CUBE;
}void clear_board() {system("cls");
}void delay_board() {Sleep(FLUSH_RATE);
}void print_board() {for (int i = 0; i < HEIGHT; ++i) {for (int j = 0; j < WIDTH; ++j)putchar(board[i][j]);puts("#");}puts("################");printf("score: %d\n", score);
}void init_square() {curr_cube = "ABCDEFGH"[rand()%8];start_number == 1 ? curr_square = 0 : curr_square = rand() % 5;curr_x = WIDTH / 2, curr_y = -4;int count = 0;for (int i = 0; i < 4; ++i)for (int j = 0; j < 4; ++j)if (square[curr_square][i][j]) {tmp[count][0] = curr_y + i;tmp[count][1] = curr_x + j;count++;}
}void drop_square() {curr_y++;
}void update_board() {//清除之前位置的方块int row, col;for (int i = 0; i < 4; ++i) {row = tmp[i][0];col = tmp[i][1];if (row >= 0 && row < HEIGHT&& col >= 0 && col < WIDTH)board[row][col] = BOARD_CUBE;}int count = 0;//画出现在位置的方块,并更新tmpfor (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {row = curr_y + i;col = curr_x + j;if (square[curr_square][i][j]) {tmp[count][0] = row;tmp[count][1] = col;count++;if (row >= 0 && row < HEIGHT&& col >= 0 && col < WIDTH)board[row][col] = curr_cube;}}}
}bool is_collision_left() {for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)if (square[curr_square][i][j]) {//检测方块与面板左墙壁的碰撞if (curr_x + j <= 0)return true;//检测方块与左侧方块的碰撞if (j == 0) {if (board[curr_y + i][curr_x + j - 1] != BOARD_CUBE)return true;}else {if (!square[curr_square][i][j - 1] && board[curr_y + i][curr_x + j - 1] != BOARD_CUBE)return true;}}return false;
}bool is_collision_right() {for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)if (square[curr_square][i][j]) {//检测方块与面板右墙壁的碰撞if (curr_x + j >= WIDTH-1)return true;//检测方块与右侧方块的碰撞if (j == 3) {if (board[curr_y + i][curr_x + j + 1] != BOARD_CUBE)return true;}else {if (!square[curr_square][i][j + 1] &&board[curr_y + i][curr_x + j + 1] != BOARD_CUBE)return true;}}return false;
}bool is_collision_bottom() {//找到当前方块的最下层int low = -99;for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++)if (square[curr_square][i][j] == 1)low = i;//如果达到面板最底部if(curr_y + low >= HEIGHT-1)return true;for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {//考虑方块下面有方块的情况if (i < 3) {if (square[curr_square][i][j] && !square[curr_square][i + 1][j]&& (curr_y + i + 1 >=0) && board[curr_y + i + 1][curr_x + j] != BOARD_CUBE)return true;}else {if (square[curr_square][i][j] && (curr_y + i + 1 >= 0) && board[curr_y + i + 1][curr_x + j] != BOARD_CUBE)return true;}}}return false;
}bool is_collsion_rotate() {int middle[4][4] = { 0 };//暂存旋转后方块for (int i = 0; i < 4; ++i)for (int j = 0; j < 4; ++j)middle[i][j] = square[curr_square][j][i];//旋转后方块是否与面板已有方块重叠for (int i = 0; i < 4; ++i)for (int j = 0; j < 4; ++j)if (!square[curr_square][i][j] && middle[i][j]&& board[curr_y + i][curr_x + j] != BOARD_CUBE)return true;return false;
}void rotate() {//清除之前位置的方块int row, col;for (int i = 0; i < 4; ++i) {row = tmp[i][0];col = tmp[i][1];if (row >= 0 && row < HEIGHT&& col >= 0 && col < WIDTH)board[row][col] = BOARD_CUBE;}//旋转方块int rotate_tmp[4][4] = { 0 };memcpy(rotate_tmp, square[curr_square], 16 * sizeof(int));for (int i = 0; i < 4; ++i)for (int j = 0; j < 4; ++j)square[curr_square][i][j] = rotate_tmp[j][i];int count = 0;//画出现在位置的方块,并更新tmpfor (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {row = curr_y + i;col = curr_x + j;if (square[curr_square][i][j]) {tmp[count][0] = row;tmp[count][1] = col;count++;if (row >= 0 && row < HEIGHT&& col >= 0 && col < WIDTH)board[row][col] = curr_cube;}}}
}bool is_game_over() {for (int j = 0; j < WIDTH; ++j)if (board[0][j] != BOARD_CUBE)return true;          return false;
}void rush_board() {int count, floor;floor = 0;for (int i = HEIGHT - 1; i >= 0; --i) {count = 0;for (int j = 0; j < WIDTH; ++j)if (board[i][j] != BOARD_CUBE)count++;if (count == WIDTH)floor++;elsebreak;}//得到floor后,面板下移floor层if (floor != 0) {for (int i = HEIGHT - 1 - floor; i >= 0; --i)for (int j = 0; j < WIDTH; ++j)board[i + floor][j] = board[i][j];score += floor;}
}void start_game() {printf("----------------俄罗斯方块----------------\n");printf("\n游戏规则:a:左移  d:右移  s:下移  w:旋转\n");printf("\n输入1:全程长条方块     输入2:经典随机方块\n");while (start_number != 1 && start_number != 2) {\printf("\n请输入序号(1或者2): ");scanf_s("%d", &start_number);}clear_board();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/178819.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据基础平台】星环TDH社区集群版本部署

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f…

Spring-Spring 之底层架构核心概念解析

BeanDefinition BeanDefinition表示Bean定义&#xff0c;BeanDefinition中存在很多属性用来描述一个Bean的特点。比如&#xff1a; class&#xff0c;表示Bean类型scope&#xff0c;表示Bean作用域&#xff0c;单例或原型等lazyInit&#xff1a;表示Bean是否是懒加载initMeth…

【云备份|| 日志 day3】服务端配置信息模块

云备份day3 使用文件配置加载一些程序的运行关键信息可以让程序的运行更加灵活&#xff0c;且当需要修改部分内容时&#xff0c;不需要在代码上修改&#xff0c;只需要修改配置文件&#xff0c;然后重启服务器即可。 配置信息 热点判断时间文件下载URL前缀路径压缩包后缀名称…

模电学习路径

交流通路实质 列出电路方程1&#xff0c;方程1对时刻t做微分 所得方程1‘ 即为 交流通路 方程1对时刻t做微分&#xff1a;两个不同时刻的方程1相减&#xff0c;并 令两时刻差为 无穷小 微分 改成 差 模电学习路径&#xff1a; 理论 《电路原理》清华大学 于歆杰 朱桂萍 陆文…

学习 SpringMVC 必备的 4 大知识点

一、什么是 SpringMVC 前面我们了解了Spring、SpringBoot&#xff0c;那么 Spring MVC 又是什么呢&#xff1f;关于三者&#xff0c;我们可以这样理解&#xff1a;Spring MVC 是 Spring 框架的核心模块&#xff0c;而 Spring Boot 是 Spring 的脚手架。 Spring MVC 又称作 Sp…

【特殊矩阵的压缩存储】

文章目录 特殊矩阵的压缩存储特殊的矩阵 特殊矩阵的压缩存储 矩阵&#xff1a;一个由m x n个元素排成的m行n列的表。 矩阵的常规存储&#xff1a; 将矩阵描述为一个二维数组。 矩阵的常规存储的特点&#xff1a; 可以将元素进行随机存取&#xff1b; 矩阵运算非常简单&#xf…

linux查看文件夹使用情况以及查看文件大小

1、ls ls 命令是 Linux 中最常用的文件和目录列表命令之一。它可以显示文件的各种属性&#xff0c;包括文件大小。 ls -l <文件名>上述命令会显示文件的详细信息&#xff0c;其中包括文件的大小。文件大小以字节为单位显示&#xff0c;并且在输出中的第 5 列。4096 表示…

我做云原生的那几年

背景介绍 在2020年6月&#xff0c;我加入了一家拥有超过500人的企业。彼时&#xff0c;前端团队人数众多&#xff0c;有二三十名成员。在这样的大团队中&#xff0c;每个人都要寻找自己的独特之处和核心竞争力。否则&#xff0c;你可能会沉没于常规的增删改查工作中&#xff0…

【C++】C++11【下】lambda表达式|thread线程库

目录 1、lambda表达式 1.1 lambda表达式的引入 1.2 lambda表达式的语法 1.3 lambda表达式的原理 2、线程库 2.1thread类的介绍 2.2 线程函数参数 2.3 原子性操作库(atomic) 2.4 使用场景 应用场景1&#xff1a; 应用场景2: 应用场景3&#xff1a; 应用场景4&#xf…

在Qt中解决opencv的putText函数无法绘制中文的一种解决方法

文章目录 1.问题2.查阅资料3.解决办法 1.问题 在opencv中&#xff0c;假如直接使用putText绘制中文&#xff0c;会在图像上出现问号&#xff0c;如下图所示&#xff1a; 2.查阅资料 查了一些资料&#xff0c;说想要解决这个问题&#xff0c;需要用到freetype库或者用opencv…

Java--多线程--Thread类+Runnable接口

1.多进程与多线程 1.1多进程&#xff1a; 一个进程是一个包含自身地址的程序&#xff0c;每个独立执行的程序都称为进程&#xff0c;也就是正在执行的程序&#xff0c;系统可以分配给每个进程一段有限的使用CPU的时间&#xff08;CPU时间片&#xff09;&#xff0c;CPU在这个时…

Django实战项目-学习任务系统-查询列表分页显示

接着上期代码框架&#xff0c;6个主要功能基本实现&#xff0c;剩下的就是细节点的完善优化了。 接着优化查询列表分页显示功能&#xff0c;有很多菜单功能都有查询列表显示页面情况&#xff0c;如果数据量多&#xff0c;不分页显示的话&#xff0c;页面展示效果就不太好。 本…

pytorch 笔记:GRU

1 介绍 对于输入序列中的每个元素&#xff0c;每一层都计算以下函数&#xff1a; ht​ 是t时刻 的隐藏状态xt​ 是t时刻 的输入ht−1​ 是 t-1时刻 同层的隐藏状态或 0时刻 的初始隐藏状态rt​,zt​,nt​ 分别是重置门、更新门和新门。σ 是 sigmoid 函数∗ 是 Hadamard 乘积。…

OpenCV 笔记(4):图像的算术运算、逻辑运算

Part11. 图像的算术运算 图像的本质是一个矩阵&#xff0c;所以可以对它进行一些常见的算术运算&#xff0c;例如加、减、乘、除、平方根、对数、绝对值等等。除此之外&#xff0c;还可以对图像进行逻辑运算和几何变换。 我们先从简单的图像加、减、逻辑运算开始介绍。后续会有…

【Git企业开发】第四节.Git的分支管理策略和bug分支

文章目录 前言一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 1.2 企业分支管理策略二、bug分支三、删除临时分支四、总结总结 前言 一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 通常合并分支时&#xff0c;如果可能&#xff0c;Git 会…

61. 旋转链表、Leetcode的Python实现

博客主页&#xff1a;&#x1f3c6;李歘歘的博客 &#x1f3c6; &#x1f33a;每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点&#xff0c;以及职场小菜鸡的生活。&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知识点&am…

基于GEE云平台一种快速修复Landsat影像条带色差的方法

这是之前关于去除遥感影像条带的另一篇文章&#xff0c;因为出版商推迟了一年发布&#xff0c;所以让大家久等了。这篇文章的主要目的是对Landsat系列卫星因为条带拼接或者镶嵌产生的条带来进行的一种在线修复方式。 原文连接 一种快速修复Landsat影像条带色差的方法 题目&a…

ffmpeg命令帮助文档

一&#xff1a;帮助文档的命令格式 ffmpeg -h帮助的基本信息ffmpeg -h long帮助的高级信息ffmpeg -h full帮助的全部信息 ffmpeg的命令使用方式&#xff1a;ffmpeg [options] [[infile options] -i infile] [[outfile options] outfile] 二&#xff1a;将帮助文档输出到文件 …

【IDEA】设置sql提示

第一步&#xff1a;注入SQL语言 1.首先选择任意一条sql语句&#xff0c;右击&#xff0c;选择 ‘显示上下文操作’ 2.选择 ‘注入语言或引用’ 3. 往下翻&#xff0c;找到MySQL 第二步&#xff1a;配置MySQL数据库连接 1.首先点击侧边的数据库&#xff0c;再点击上面的加号 2…

中兴路由器、小米路由器无线信号强度对比

最近小米新推出的路由器小米AX3000T非常火&#xff0c;在网上看到有好多人都在安利&#xff0c;引起了我的兴趣&#xff0c;刚好老家的路由器用了这么久也是时候要换一个了&#xff0c;毕竟我妈老说上网卡??所以我立马就在PDD搞了一台回来&#xff0c;打算和我现在家里用的中…