俄罗斯方块-----C语言

简介: 俄罗斯方块-----C语言

干货干货,直接上代码啦。。。。。。。。。。。。。。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
#define SPACE 32
#define LEFT  75
#define RIGHT 77
#define DOWN 80
#define ESC 27
#define Wall 2
#define Box 1
#define Kong 0
#define FACE_X 29
#define FACE_Y 20   //界面尺寸
void gotoxy(int x, int y);  //移动光标
int color(int c);   //颜色
void hidden_cursor();  //隐藏光标
void inter_face();  //初始化界面
void init_dia();   //初始化方块信息
void draw_dia(int base, int space_c, int x, int y);   //覆盖方块
void draw_kong(int base, int space_c, int x, int y); //画方块
int pd(int n, int space_c, int x, int y);  //判断是否到底
void start_game();   //开始游戏
int xc();//消除
void read_file();   //读写最高记录
void write_file();  //写最高纪录
int grade = 0;//当前分数
int max = 0;//最高记录
int nn = 0;
struct Face
{
  int data[FACE_X][FACE_Y + 10];    //数值,为1是方块,为0是空格
  int color[FACE_X][FACE_Y + 10];   //对应方块的颜色
}face;
typedef struct Diamonds
{
  int space[4][4];        //4*4矩阵,为1为方块,为0 为空
}Dia;
Dia dia[7][4];  //一维基础7个方块,二维表示旋转次数
int main()
{
  system("cls");
  system("title C语言与程序设计 俄罗斯方块");
  color(7);
  system("mode con cols=60 lines=30");  //窗口宽度高度 
  hidden_cursor();
  srand(time(NULL));
  read_file();
  grade = 0;
  inter_face();
  init_dia();
  nn = rand() % 7;
  while (1)
  {
    start_game();
  }
  return 0;
}
/
void start_game()
{
  int n, ch, t = 0, x = 0, y = FACE_Y / 2 - 2, i, j;
  int space_c = 0;//旋转次数
  draw_kong(nn, space_c, 4, FACE_Y + 3);
  n = nn;
  nn = rand() % 7;    //随机生成下一块
  color(nn);
  draw_dia(nn, space_c, 4, FACE_Y + 3);
  while (1)
  {
    color(n);
    draw_dia(n, space_c, x, y);//画出图形
    if (t == 0)
      t = 15000;
    while (--t)
    {
      if (kbhit() != 0)//有输入就跳出
        break;
    }
    if (t == 0)
    {
      if (pd(n, space_c, x + 1, y) == 1)
      {
        draw_kong(n, space_c, x, y);
        x++;            //向下降落
      }
      else
      {
        for (i = 0; i<4; i++)
        {
          for (j = 0; j<4; j++)
          {
            if (dia[n][space_c].space[i][j] == 1)
            {
              face.data[x + i][y + j] = Box;
              face.color[x + i][y + j] = n;
              while (xc());
            }
          }
        }
        return;
      }
    }
    else
    {
      ch = getch();
      switch (ch)     //移动
      {
      case LEFT: if (pd(n, space_c, x, y - 1) == 1)   //判断是否可以移动
      {
        draw_kong(n, space_c, x, y);
        y--;
      }
             break;
      case RIGHT: if (pd(n, space_c, x, y + 1) == 1)
      {
        draw_kong(n, space_c, x, y);
        y++;
      }
            break;
      case DOWN: if (pd(n, space_c, x + 1, y) == 1)
      {
        draw_kong(n, space_c, x, y);
        x++;
      }
             break;
      case SPACE: if (pd(n, (space_c + 1) % 4, x + 1, y) == 1)
      {
        draw_kong(n, space_c, x, y);
        space_c = (space_c + 1) % 4;
      }
            break;
      case ESC: system("cls");
        gotoxy(FACE_X / 2, FACE_Y);
        printf("---游戏结束!---\n\n");
        gotoxy(FACE_X / 2 + 2, FACE_Y);
        printf("---按任意键退出!---\n");
        getch();
        exit(0);
        break;
      case  'R':
      case  'r':  main();
        exit(0);
      case  'S':
      case  's':  while (1)
      {
        if (kbhit() != 0)//有输入就跳出
          break;
      }
            break;
      }
    }
  }
}
int xc()
{
  int i, j, k, sum;
  for (i = FACE_X - 2; i>4; i--)
  {
    sum = 0;
    for (j = 1; j<FACE_Y - 1; j++)
    {
      sum += face.data[i][j];
    }
    if (sum == 0)
      break;
    if (sum == FACE_Y - 2)   //满一行,减掉
    {
      grade += 100;
      color(7);
      gotoxy(FACE_X - 4, 2 * FACE_Y + 2);
      printf("分数:%d", grade);
      for (j = 1; j<FACE_Y - 1; j++)
      {
        face.data[i][j] = Kong;
        gotoxy(i, 2 * j);
        printf(" ");
      }
      for (j = i; j>1; j--)
      {
        sum = 0;
        for (k = 1; k<FACE_Y - 1; k++)
        {
          sum += face.data[j - 1][k] + face.data[j][k];
          face.data[j][k] = face.data[j - 1][k];
          if (face.data[j][k] == Kong)
          {
            gotoxy(j, 2 * k);
            printf(" ");
          }
          else
          {
            gotoxy(j, 2 * k);
            color(face.color[j][k]);
            printf("■");
          }
        }
        if (sum == 0)
          return 1;
      }
    }
  }
  for (i = 1; i<FACE_Y - 1; i++)
  {
    if (face.data[1][i] == Box)
    {
      char n;
      Sleep(2000); //延时
      system("cls");
      color(7);
      gotoxy(FACE_X / 2 - 2, 2 * (FACE_Y / 3));
      if (grade>max)
      {
        printf("恭喜您打破记录,目前最高纪录为:%d", grade);
        write_file();
      }
      else if (grade == max)
        printf("与纪录持平,请突破你的极限!");
      else
        printf("请继续努力,你与最高记录只差:%d", max - grade);
      gotoxy(FACE_X / 2, 2 * (FACE_Y / 3));
      printf("GAME OVER!\n");
      do
      {
        gotoxy(FACE_X / 2 + 2, 2 * (FACE_Y / 3));
        printf("是否重新开始游戏(y/n): ");
        scanf("%c", &n);
        gotoxy(FACE_X / 2 + 4, 2 * (FACE_Y / 3));
        if (n != 'n' && n != 'N' && n != 'y' && n != 'Y')
          printf("输入错误,请重新输入!");
        else
          break;
      } while (1);
      if (n == 'n' || n == 'N')
      {
        gotoxy(FACE_X / 2 + 4, 2 * (FACE_Y / 3));
        printf("按任意键退出游戏!");
        exit(0);
      }
      else if (n == 'y' || n == 'Y')
        main();
    }
  }
  return 0;
}
//
void read_file()    //读取最高记录
{
  FILE *fp;
  fp = fopen("俄罗斯方块记录.txt", "r+");
  if (fp == NULL)
  {
    fp = fopen("俄罗斯方块记录.txt", "w+");
    fwrite(&max, sizeof(int), 1, fp);
  }
  fseek(fp, 0, 0);
  fread(&max, sizeof(int), 1, fp);
  fclose(fp);
}
void write_file()   //保存最高记录
{
  FILE *fp;
  fp = fopen("俄罗斯方块记录.txt", "r+");
  fwrite(&grade, sizeof(int), 1, fp);
  fclose(fp);
}
///
int pd(int n, int space_c, int x, int y)   //判断是否到底
{
  int i, j;
  for (i = 0; i<4; i++)
  {
    for (j = 0; j<4; j++)
    {
      if (dia[n][space_c].space[i][j] == 0)
        continue;
      else if (face.data[x + i][y + j] == Wall || face.data[x + i][y + j] == Box)
        return 0;
    }
  }
  return 1;
}
void draw_kong(int base, int space_c, int x, int y)
{
  int i, j;
  for (i = 0; i<4; i++)
  {
    for (j = 0; j<4; j++)
    {
      gotoxy(x + i, 2 * (y + j));
      if (dia[base][space_c].space[i][j] == 1)
        printf("  ");
    }
  }
}
void draw_dia(int base, int space_c, int x, int y)
{
  int i, j;
  for (i = 0; i<4; i++)
  {
    for (j = 0; j<4; j++)
    {
      gotoxy(x + i, 2 * (y + j));
      if (dia[base][space_c].space[i][j] == 1)
        printf("■");
    }
  }
}
void init_dia()
{
  int i, j, k, z;
  int tmp[4][4];
  for (i = 0; i<3; i++)
    dia[0][0].space[1][i] = 1;
  dia[0][0].space[2][1] = 1;     //土形
  for (i = 1; i<4; i++)
    dia[1][0].space[i][1] = 1;
  dia[1][0].space[1][2] = 1;    //L形--1
  for (i = 1; i<4; i++)
    dia[2][0].space[i][2] = 1;
  dia[2][0].space[1][1] = 1;    //L形--2
  for (i = 0; i<2; i++)
  {
    dia[3][0].space[1][i] = 1;
    dia[3][0].space[2][i + 1] = 1; //Z形--1
    dia[4][0].space[1][i + 1] = 1;
    dia[4][0].space[2][i] = 1;//Z形--2
    dia[5][0].space[1][i + 1] = 1;
    dia[5][0].space[2][i + 1] = 1;//田字形
  }
  for (i = 0; i<4; i++)
    dia[6][0].space[i][2] = 1;//1形 
                  //基础7个形状
  for (i = 0; i<7; i++)
  {
    for (z = 0; z<3; z++)
    {
      for (j = 0; j<4; j++)
      {
        for (k = 0; k<4; k++)
        {
          tmp[j][k] = dia[i][z].space[j][k];
        }
      }
      for (j = 0; j<4; j++)
      {
        for (k = 0; k<4; k++)
        {
          dia[i][z + 1].space[j][k] = tmp[4 - k - 1][j];
        }
      }
    }
  }
  ///旋转后的21个形状
}
//
void inter_face()//界面
{
  int i, j;
  for (i = 0; i<FACE_X; i++)
  {
    for (j = 0; j<FACE_Y + 10; j++)
    {
      if (j == 0 || j == FACE_Y - 1 || j == FACE_Y + 9)
      {
        face.data[i][j] = Wall;
        gotoxy(i, 2 * j);
        printf("■");
      }
      else if (i == FACE_X - 1)
      {
        face.data[i][j] = Box;
        gotoxy(i, 2 * j);
        printf("■");
      }
      else
        face.data[i][j] = Kong;
    }
  }
  gotoxy(FACE_X - 18, 2 * FACE_Y + 2);
  printf("左移:←");
  gotoxy(FACE_X - 16, 2 * FACE_Y + 2);
  printf("右移:→");
  gotoxy(FACE_X - 14, 2 * FACE_Y + 2);
  printf("旋转:space");
  gotoxy(FACE_X - 12, 2 * FACE_Y + 2);
  printf("暂停: S");
  gotoxy(FACE_X - 10, 2 * FACE_Y + 2);
  printf("退出: ESC");
  gotoxy(FACE_X - 8, 2 * FACE_Y + 2);
  printf("重新开始:R");
  gotoxy(FACE_X - 6, 2 * FACE_Y + 2);
  printf("最高纪录:%d", max);
  gotoxy(FACE_X - 4, 2 * FACE_Y + 2);
  printf("分数:%d", grade);
}
//
void gotoxy(int x, int y) //移动坐标
{
  COORD coord;
  coord.X = y;
  coord.Y = x;
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
//
void hidden_cursor()//隐藏光标
{
  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_CURSOR_INFO cci;
  GetConsoleCursorInfo(hOut, &cci);
  cci.bVisible = 0;//赋1为显示,赋0为隐藏
  SetConsoleCursorInfo(hOut, &cci);
}
int color(int c)
{
  switch (c)
  {
  case 0: c = 9; break;
  case 1:
  case 2: c = 12; break;
  case 3:
  case 4: c = 14; break;
  case 5: c = 10; break;
  case 6: c = 13; break;
  default: c = 7; break;
  }
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色
  return 0;
}

执行结果:

目录
相关文章
|
5月前
|
存储 C语言
C语言实战 | “俄罗斯方块”游戏重构
摘要(Markdown格式): 在之前的游戏中,全局变量的过度使用导致存储浪费和低代码通用性。以“贪吃蛇”为例,显示功能依赖全局变量,限制了函数的复用。通过参数传递代替全局变量,如在“俄罗斯方块”等游戏中控制物体运动的函数,可提升代码重用性和模块化。重构过程中,即使小到变量命名和代码精简的改进,也能逐步带来程序质量的显著提升。
31 0
|
6月前
|
Linux C语言
俄罗斯方块(c语言)
俄罗斯方块(c语言)
|
6月前
|
存储 定位技术 API
c语言——俄罗斯方块
c语言——俄罗斯方块
123 0
|
C语言
C语言小游戏------俄罗斯方块
C语言写的俄罗斯方块小游戏
262 0
|
28天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
18天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
32 10
|
12天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
17天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
43 7
|
17天前
|
存储 编译器 程序员
【c语言】函数
本文介绍了C语言中函数的基本概念,包括库函数和自定义函数的定义、使用及示例。库函数如`printf`和`scanf`,通过包含相应的头文件即可使用。自定义函数需指定返回类型、函数名、形式参数等。文中还探讨了函数的调用、形参与实参的区别、return语句的用法、函数嵌套调用、链式访问以及static关键字对变量和函数的影响,强调了static如何改变变量的生命周期和作用域,以及函数的可见性。
25 4