当前位置: 首页 > news >正文

C 实现难度过高的俄罗斯方块

在这里插入图片描述

// 模板 显示Hello World 支持c和c++ 也可以改成main.cpp
#include <stdio.h>
#include <stdlib.h>
#include "raylib.h"#define ROWS 30
#define COLS 20
int grid[ROWS][COLS] = {0};#define CELL_SIZE 30
#define BLOCK_TYPE_COUNT 13
const Color colors_block[BLOCK_TYPE_COUNT + 1] = {
{26,31,40,255},
{47,230,23,255},
{232,18,18,255},
{226,116,17,255},
{237,234,4,255},
{166,0,247,255},
{21,204,209,255},
{212,123,0,255},
{0,123,212,255},
{255,0,200,255},
{255,255,0,255},
{13,64,216,255},
{222,222,222,255},
{0,255,127,255},
};typedef struct Block {int idx;int sz;int shape[4][4];int row,col;} Block;// 当前方块
Block curBlock,nextBlock;// 所有方块
Block allBlocks[BLOCK_TYPE_COUNT] = {{1,2,{{1,1,0,0},{1,1,0,0},        }},{2,3,{{0,0,0},{1,1,0},{0,1,1},}},{3,3,{{0,0,0},{0,1,1},{1,1,0},        }},{4,3,{{0,1,0},{0,1,0},{0,1,1},        }},{5,3,{{0,0,0},{1,1,1},{0,1,0},        }},{6,3,{{0,1,0},{0,1,0},{1,1,0},        }},{7,4,{{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}}},{8,4,{            {0,1,0,1},{0,1,0,1},{0,1,1,1},{0,0,0,0},}},{9,4,{            {1,1,1,1},{1,1,1,1},{0,1,1,0},{0,1,1,0},}},{10,4,{            {1,1,0,0},{1,1,0,0},{1,1,1,1},{1,1,1,1},}},{11,2,{            {1,0},{0,1},}},{12,2,{            {1,1},{0,1},}},{13,1,{            {1},}},};bool leftPressed = false;
bool rightPressed = false;
bool isGameOver = false;// 方块下落速度
float downInterval =0.32f*3;// 方块下落间隔
float curInterval = 0;float downSpeedFactor = 1.0f;// 得分
int score = 0;// 初始化
void init();
// 加载纹理
void loadTextures();
// 初始化游戏
void initGame();
// 处理操作
void checkOperation(float dt);
Vector2 getPosOfRowCol(int row, int col);
// 绘制网格
void drawGrid();// 绘制方块
void drawCurBlock();// 绘制方块下降
void driveCurBlock(float dt);// 判断方块是否可以下落
bool isBlockPositionValid(Block bloock);// 合并方块到网格
void mergeBlockToGrid(Block block);// 检查操作
void checkOperation(float dt);// 旋转方块
void rotateBlockClockwise(Block *block);void rotateBlockRandom(Block *block);// 合并满行
int eliminateFullRows();// 绘制得分
void drawScore();//显示下个方块
void drawNextBlock();// 显示游戏结束画面
void drawGameOver();// 主函数
int main() {init();// 游戏循环while (!WindowShouldClose()) {        float dt = GetFrameTime();                BeginDrawing();ClearBackground((Color){44,44,127,255});               checkOperation(dt);drawGrid();drawCurBlock();driveCurBlock(dt);    drawScore();    drawNextBlock();drawGameOver();EndDrawing();}CloseWindow();return 0;
}void init() {SetConfigFlags(FLAG_WINDOW_HIGHDPI);InitWindow(900, 920, "Tetris");SetTargetFPS(60);loadTextures();initGame();
}void initGame() {for(int i = 0; i < ROWS; i++) {for(int j = 0; j < COLS; j++) {grid[i][j] = 0;}}score = 0;isGameOver = false;curBlock = allBlocks[GetRandomValue(0, BLOCK_TYPE_COUNT - 1)];rotateBlockRandom(&curBlock);curBlock.row = 0;curBlock.col = COLS/2 - curBlock.sz/2;nextBlock = allBlocks[GetRandomValue(0, BLOCK_TYPE_COUNT - 1)];rotateBlockRandom(&nextBlock);}void loadTextures() {}Vector2 getPosOfRowCol(int row, int col) {int x = col * CELL_SIZE + 11 + CELL_SIZE/2;int y = row * CELL_SIZE + 11 + CELL_SIZE/2;return (Vector2){x, y};
}void drawGrid() {// 先绘制所有单元格for (int i = 0; i < ROWS; i++) {for (int j = 0; j < COLS; j++) {Vector2 pos = getPosOfRowCol(i, j);DrawRectangle(pos.x - CELL_SIZE/2, pos.y - CELL_SIZE/2, CELL_SIZE - 1, CELL_SIZE - 1, (Color){0,0,0,255});if (grid[i][j]) {DrawRectangle(pos.x - CELL_SIZE/2 + 1, pos.y - CELL_SIZE/2 + 1, CELL_SIZE - 3, CELL_SIZE - 3, colors_block[grid[i][j]]);}}}// 然后绘制网格线for (int i = 0; i <= ROWS; i++) {DrawLine(11, 11 + i * CELL_SIZE, 11 + COLS * CELL_SIZE, 11 + i * CELL_SIZE, LIGHTGRAY);}for (int j = 0; j <= COLS; j++) {DrawLine(11 + j * CELL_SIZE, 11, 11 + j * CELL_SIZE, 11 + ROWS * CELL_SIZE, LIGHTGRAY);}
}void drawCurBlock(){for (int i = 0; i < curBlock.sz; i++) {for (int j = 0; j < curBlock.sz; j++) {if (curBlock.shape[i][j] == 1) {int row = curBlock.row + i;int col = curBlock.col + j;if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {Vector2 pos = getPosOfRowCol(row, col);// 使用标准 Raylib 函数绘制矩形DrawRectangle((int)(pos.x - CELL_SIZE/2),  // 左上角x(int)(pos.y - CELL_SIZE/2),  // 左上角yCELL_SIZE - 1,               // 宽度CELL_SIZE - 1,               // 高度colors_block[curBlock.idx]   // 颜色);}}}}
}void driveCurBlock(float dt) {curInterval += dt*downSpeedFactor;if (curInterval >= downInterval) {curBlock.row++;curInterval = 0.0f;}if (!isBlockPositionValid(curBlock)) {curBlock.row--;if(curBlock.row<0){isGameOver = true;return ;}mergeBlockToGrid(curBlock);int eliminatedRows = eliminateFullRows();if (eliminatedRows > 0) {score += 100 * (int)pow(2, eliminatedRows - 1);}curBlock =nextBlock;curBlock.row = 0;        curBlock.col = (COLS - curBlock.sz) / 2;nextBlock = allBlocks[GetRandomValue(0, BLOCK_TYPE_COUNT - 1)];rotateBlockRandom(&nextBlock);        if(!isBlockPositionValid(curBlock)){printf("Game Over\n");           }}
}bool isBlockPositionValid(Block bloock){for (int i = 0; i < bloock.sz; i++) {for (int j = 0; j < bloock.sz; j++) {if (bloock.shape[i][j] == 1) {int row = bloock.row + i;int col = bloock.col + j;if((row < 0 || row >= ROWS) || col >= COLS || col < 0) {      printf("row:%d col:%d grid:%d\n",row,col,grid[row][col]);return false;                                            }                if(row>=0&&grid[row][col]!=0){return false;}}}}return true;
}void mergeBlockToGrid(Block block){for (int i = 0; i < block.sz; i++) {for (int j = 0; j < block.sz; j++) {if (block.shape[i][j] == 1) {int row = block.row + i;int col = block.col + j;if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {grid[row][col] = block.idx;}}}}
}void checkOperation(float dt){static float moveAccumulator = 0.0f;static const float moveDelay = 0.1f; // 按键重复延迟(秒)moveAccumulator += dt;if (IsKeyDown(KEY_LEFT)) {if (moveAccumulator >= moveDelay || !leftPressed) {leftPressed = true;curBlock.col--;if(!isBlockPositionValid(curBlock)) {curBlock.col++;}moveAccumulator = 0.0f; // 重置计时器}} else if (IsKeyDown(KEY_RIGHT)) {if (moveAccumulator >= moveDelay || !rightPressed) {rightPressed = true;curBlock.col++;if(!isBlockPositionValid(curBlock)) {curBlock.col--;}moveAccumulator = 0.0f;}    }else if(IsKeyPressed(KEY_UP)){rotateBlockClockwise(&curBlock);if(!isBlockPositionValid(curBlock)){rotateBlockClockwise(&curBlock);rotateBlockClockwise(&curBlock);rotateBlockClockwise(&curBlock);}return;}else if(IsKeyPressed(KEY_SPACE)){while(isBlockPositionValid(curBlock)){curBlock.row++;}return;} if(isGameOver && IsKeyPressed(KEY_R)){initGame();}if(IsKeyDown(KEY_DOWN)){downSpeedFactor = 20.0f;}else{downSpeedFactor = 1.0f;}
}void rotateBlockClockwise(Block *block) {// 1. 先转置(行列互换,只交换上三角部分避免重复)for (int i = 0; i < block->sz; i++) {for (int j = i + 1 ; j < block->sz; j++) {  // j 从 i+1 开始,避免重复交换int temp = block->shape[i][j];block->shape[i][j] = block->shape[j][i];block->shape[j][i] = temp;}}// 2. 再水平翻转每一行(实现顺时针旋转 90°)for (int i = 0; i < block->sz; i++) {for (int j = 0; j < block->sz / 2; j++) {int temp = block->shape[i][j];block->shape[i][j] = block->shape[i][block->sz - 1 - j];block->shape[i][block->sz - 1 - j] = temp;}}
}void rotateBlockRandom(Block *block){int times = GetRandomValue(0, 3);for(int i = 0; i < times; i++){rotateBlockClockwise(block);}
}int eliminateFullRows(){int rowsEliminated = 0;int row = ROWS - 1;while (row >= 0) {bool isFull = true;for (int col = 0; col < COLS; col++) {if (grid[row][col] == 0) {isFull = false;break;}}if (isFull && row > 0) {// 移动当前行上方的行for (int i = row; i > 0; i--) {for (int j = 0; j < COLS; j++) {grid[i][j] = grid[i - 1][j];}}// 重置最上行for (int j = 0; j < COLS; j++) {grid[0][j] = 0;}rowsEliminated++;} else {row--;}}    return rowsEliminated;
}void drawScore(){int left = (COLS + 2)* CELL_SIZE +11 +10;   DrawText("Score",left,15,38,WHITE);DrawRectangleRounded((Rectangle){left-30,55,170,60},0.3,6,(Color){59,85,162,255});char scoreText[10];sprintf(scoreText, "%d", score);drawTextCenter(scoreText,left+55,87,38,WHITE);
}void drawNextBlock(){int left = (COLS + 2)* CELL_SIZE +11 +10;   DrawText("Next",left,175,38,WHITE);DrawRectangleRounded((Rectangle){left-30,215,170,180},0.3,6,(Color){59,85,162,255});int width = nextBlock.sz * CELL_SIZE;int height = nextBlock.sz * CELL_SIZE;int startX = left ;int startY = 245;for (int i = 0; i < nextBlock.sz; i++) {for (int j = 0; j < nextBlock.sz; j++) {if (nextBlock.shape[i][j] == 1) {int x = startX + j * CELL_SIZE;int y = startY + i * CELL_SIZE;DrawRectangle(x, y, CELL_SIZE - 1, CELL_SIZE - 1, colors_block[nextBlock.idx]);}}}
}void drawGameOver(){if(!isGameOver){return;}int left = (COLS + 2)* CELL_SIZE +11 +10;   DrawText("Game Over",left-30,450,38,RED);// 红色字    DrawText("Press R to\n Restart",left-30,550,38,WHITE);
}
http://www.lryc.cn/news/607159.html

相关文章:

  • 数据赋能(371)——数据挖掘——概述
  • LLM Prompt与开源模型资源(1)提示词工程介绍
  • UniApp与WebView双向通信机制及生产级实现方案全解析
  • 计数组合学7.10(舒尔函数的组合定义)
  • Golang 语言 Channel 的使用方式
  • 数据结构:链表(Linked List)
  • 如何通过黑白棋盘进行定位配准融合?(前后安装的两个相机)
  • 【Mysql】联合索引生效分析案例
  • 【科研绘图系列】R语言绘制环状分组显著性柱状堆积图
  • 鹧鸪云:16步精控工商业光伏全流程
  • java8学习笔记-Stream流
  • GitPython08-源码解读
  • 网络编程接口bind学习
  • MySQL时间处理完全指南:从存储到查询优化
  • Java向量化
  • 如何处理Y2K38问题
  • 利用 AI 在 iPhone 上实现 App 文本情绪价值评估(上)
  • 【AI应用】 能源保供战:AI大模型如何守护万家灯火?
  • TGD第十篇:当神经网络遇到TGD特征
  • Qt 开发自动化测试框架搭建
  • 【华为机试】34. 在排序数组中查找元素的第一个和最后一个位置
  • OSPF综合大实验
  • python学智能算法(三十))|SVM-KKT条件的数学理解
  • Git基础命令大全
  • C语言数据结构(3)单链表专题1.单链表概述
  • 【论文学习】KAG论文翻译
  • Redis 中 ZipList 的级联更新问题
  • 一篇文章读懂AI Agent(智能体)
  • Python LRU缓存应用与示例
  • 三维协同:体育场馆设计与渲染的独特挑战