Tetris [six modes] [c language] [the strongest in history]

--------Write in front --------

        The first time to do a title party, everyone lightly sprayed. This game was independently completed by the blogger during the freshman c language training, and all the content is original. The mini-game took 5 days to complete. In addition to the common single-player mode, cheating mode, double-player mode, time trial and other gameplays have been added, which is really fun. Although it looks very simple now, it was not easy for me at the time. From page design to the selection of game background music to the compilation of key algorithms, every step has condensed my own efforts, and the pictures of the all-night battle are still vivid. in sight. Now sharing it, on the one hand, I hope it can help everyone, and on the other hand, I want to commemorate the wonderful freshman year. The source code address is at the end of the article, everyone can pick it up.

        If it is helpful to you, you can like and support it, it would be even better if you can follow it , thank you all!

-----------------------text-----------------------

final effect

Home

Mode selection

Press 1 to enter single player mode

Press 2 to enter duo mode

Standard Mode: In addition to moving left and right down, direct drop and pause have been added, and level judgment has been added

Hell Mode: Under the premise of standard mode, the falling speed is accelerated, and it is more exciting!

Cheat mode: add dazzling mode, deformation, acceleration and deceleration functions

 Two-Person Standard: An algorithm was devised to determine a winner or loser

Double Hell Survival: Exciting! !

Two-person time trial: set a timer, reset the algorithm for determining the outcome of a draw, and the one with the highest score within the specified time wins!

 end animation

 code section

main.c

#include <stdio.h>
#include <stdlib.h>
#include "game.h"
#include "mywindows.h"
#include <conio.h>

#include <mmsystem.h>
#pragma comment (lib, "winmm.lib")

void chooseMode(){
   if(kbhit()){
         mciSendString("close g",NULL,0,NULL);
        switch(getch()){
        case 49:
        case 97: gameInit(1);break;
        case 50:
        case 98: gameInit(2);break;
         case 51:
        case 99: gameInit(3);break;
        }
   }
}

void chooseMode2(){
    if(kbhit()){
             mciSendString("close g",NULL,0,NULL);
        switch(getch()){
        case 49:
        case 97: gameInit1(1);break;
        case 50:
        case 98: gameInit1(2);break;
         case 51:
        case 99: gameInit1(3);break;
        }
   }
}

int main()
{

    ///初始化句柄,必须放在最开始
    initHandle();
    ///开始动画
    mciSendString("open 俄罗斯方块进入音乐.mp3 alias g",NULL,0,NULL);
     mciSendString("play g repeat",NULL,0,NULL);
    printAnimation();

    if(kbhit()){
            getch();
        chooseWindow();

    }
    if(kbhit()){
        switch(getch()){
        case 49:
        case 97: chooseWindow2();chooseMode();break;
        case 50:
        case 98: chooseWindow3();chooseMode2();break;

        }
    }

   return 0;
}

mywindows.c

#include "mywindows.h"  //尖括号常用于引入系统头文件,双引号常用于引入自己定义的头文件   默认检索顺序不同

HANDLE handle;

//函数定义

void initHandle(){
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
    hideCursor();//游戏启动后隐藏光标位置
    //
}

void setColor(int color){
    SetConsoleTextAttribute(handle,color);
}

void setPos(int x,int y){
    COORD coord = {x*2,y};    //字母abcd:一个字符,汉字:两个字符
    SetConsoleCursorPosition(handle,coord); //设置句柄位置
}

void hideCursor(){
    CONSOLE_CURSOR_INFO info;        //系统的结构体变量名字都是大写
    info.bVisible = FALSE;           //设置光标是否可见
    info.dwSize = 1;                 //设置光标宽度(1-100)
    SetConsoleCursorInfo(handle,&info);//指针取地址符
}

game.c key code

Single mode form printing

void printGradeLevel1(int num){
    switch(num){
        case 1:
            grade1+=10; break;
        case 2:
            grade1+=30; break;
        case 3:
            grade1+=50; break;
        case 4:
            grade1+=80; break;
    }

    if(grade1 < 100){
        level1 = 1;
    }
    else if(grade1 >= 100 && grade1 < 300){
        level1 =2;
    }

    setColor(0x0c);
    setPos(4,8);
    printf("分数:%d",grade1);

    setPos(4,9);
    printf("等级:%d",level1);
}

void printGradeLevel2(int num){
    switch(num){
        case 1:
            grade2+=10; break;
        case 2:
            grade2+=30; break;
        case 3:
            grade2+=50; break;
        case 4:
            grade2+=80; break;
    }

    if(grade2 < 100){
        level2 = 1;
    }
    else if(grade2 >= 100 && grade2 < 300){
        level2 =2;
    }

    setColor(0x09);
    setPos(51,8);
    printf("分数:%d",grade2);

    setPos(51,9);
    printf("等级:%d",level2);
}

Double mode form printing

void windowPrint2(int x,int y){
     int i,j;  //用来遍历二维数组
    for(i=0;i<25;i++){
        for(j=0;j<58;j++){
            if(windowShape2[i][j] == 1){
                setColor(0xc0);
                setPos(x+j,y+i);  //x是列,y是行
                printf("%2s","");  // <-->  printf("  ");
            }
        }
    }
     for(i=0;i<25;i++){
        for(j=29;j<58;j++){
            if(windowShape2[i][j] == 1){
                setColor(0x90);
                setPos(x+j,y+i);  //x是列,y是行
                printf("%2s","");  // <-->  printf("  ");
            }
        }
    }

}

//操作规则框架
void printInfo(){
    setColor(0x0c);
    setPos(2,2);
    printf("N");
    setPos(2,3);
    printf("E");
    setPos(2,4);
    printf("X");
    setPos(3,3);
    printf("T");
    setPos(3,14);
    printf("红方操作规则");
    setPos(3,15);
    printf("------------");
    setPos(2,16);
    printf("按 a 或 A 左移");
    setPos(2,17);
    printf("按 d 或 D 右移");
    setPos(2,18);
    printf("按 s 或 S 下移");
    setPos(2,19);
    printf("按 w 或 W 变方向");
    setPos(2,20);
    printf("按 q 直接下落");
     setColor(0x03);
     setPos(49,2);
    printf("N");
    setPos(49,3);
    printf("E");
    setPos(49,4);
    printf("X");
    setPos(50,3);
    printf("T");
    setPos(50,14);
    printf("蓝方操作规则");
    setPos(50,15);
    printf("------------");
    setPos(49,16);
    printf("按 ←键 左移");
    setPos(49,17);
    printf("按 →键 右移");
    setPos(49,18);
    printf("按 ↑键 下移");
    setPos(49,19);
    printf("按 ↓键 变方向");
    setPos(49,20);
    printf("按 回车 直接下落");
    setPos(27,1);
    printf("--战况--");
    setPos(27,3);
    printf("--------");
}

square print

void printBlock1(int x,int y,int shape,int status,int color){
    int i,j;
    for(i = 0;i<4;i++){
        for(j = 0;j<4;j++){
            if(block[shape][status][i][j] == 1){
                setColor(color);
                setPos(x+j,y+i);
                printf("■");
            }
        }
    }
}

void printBlock2(int x,int y,int shape,int status,int color){
    int i,j;
    for(i = 0;i<4;i++){
        for(j = 0;j<4;j++){
            if(block[shape][status][i][j] == 1){
                setColor(color);
                setPos(x+j,y+i);
                printf("■");
            }
        }
    }
}

Impact checking

 //碰撞检测基于下一个位置的检测,数组与界面坐标的对应
int crash1(int x,int y,int shape,int status){
    int i,j;
    for(i = 0;i<4;i++){
        for(j = 0;j<4;j++){
            if(block[shape][status][i][j] == 1){
                if(windowShape2[y+i][x+j] == 1){
                      ///发生碰撞
                      if(cur_block1.x == 17 && cur_block1.y == 1){
                        ///游戏结束
                        return -2;
                      }
                      ///方块落到游戏池底部,发生碰撞


                    return -1;
                }

            }
        }

    }
    return 0;
}

Victory judgment


void bottomBlock1(){
    while(crash1(cur_block1.x,cur_block1.y+1,cur_block1.shape,cur_block1.status) != -1&&crash1(cur_block1.x,cur_block1.y+1,cur_block1.shape,cur_block1.status) != -2){

    cur_block1.y += 1;


    }

        if(crash1(cur_block1.x,cur_block1.y+1,cur_block1.shape,cur_block1.status) == -1){
            ///发生碰撞:方块落到游戏池底部
            ///产生新的方块:下一个方块值 -> 当前正在下落的方块,重新产生下一个方块
            save1();
            removeLine1();
//            lineClear();
            updateGame1();
            copyBlock1();

    }
    else if(crash1(cur_block1.x,cur_block1.y+1,cur_block1.shape,cur_block1.status) == -2){
        ///游戏结束

    }
}

Button detection and double win-lose judgment algorithm

int gameInit1(int mode){
    if(mode == 1){
         mciSendString("open 双人标准.mp3 alias d",NULL,0,NULL);
     mciSendString("play d repeat",NULL,0,NULL);
    }
    if(mode == 2){
        mciSendString("open 双人地狱.mp3 alias e",NULL,0,NULL);
     mciSendString("play e repeat",NULL,0,NULL);
    }
    if(mode == 3){
        mciSendString("open 双人限时.mp3 alias f",NULL,0,NULL);
     mciSendString("play f repeat",NULL,0,NULL);
    }
    int counter = 180;
    float speed ;
    if(mode == 1){
        speed = 0.45;
    }
    else if(mode == 2){
        speed = 0.25;
    }
    else if(mode == 3){
        speed = 1;
    }
    ///初始化句柄,必须放在最开始
    initHandle();
    ///打开音乐文件

    windowPrint2(0,0);
      printInfo();
    printGradeLevel1(0);
    printGradeLevel2(0);
    ///游戏开始时间
    clock_t startTime = clock();



    ///定时器
    clock_t time1,time2;
    time1 = clock();


    startBlock1();
    startBlock2();
    nextBlock1();
    nextBlock2();



    while(1){
        //按键驱动
        ///检测是否有按键按下
        if(kbhit()){
            switch(getch()){
            case 'w':
            case 'W':
               changeStatusBlock1();break;
            case 'a':
            case 'A':
                leftBlock1();break;
            case 'd':
            case 'D':
                rightBlock1();break;
            case 's':
            case 'S':
                downBlock1();break;
            case 72:
               changeStatusBlock2();break;
            case 75:
                leftBlock2();break;
            case 77:
                rightBlock2();break;
            case 80:
                downBlock2();break;
            case 32:
                bottomBlock1();break;
            case 13:
                bottomBlock2();break;
            }
        }

        time2 = clock();



if(mode == 1|| mode == 2){
        ///每0.45秒下落一次
        if((float)(time2-time1)/CLOCKS_PER_SEC > speed){

                setPos(27,2);
            if(downBlock1() == -2) {
                    if(grade2>grade1){
                            printf("蓝 方 胜!");break;
                        }
                        else if(downBlock2() == -2){
                            if(grade1==grade2){
                            printf("平     局");break;
                            }
                            else{
                            printf("红 方 胜!");break;
                            }
                        }
                    }
                setPos(27,3);
            if(downBlock2() == -2) {
                  if(grade1>grade2){
                            printf("红 方 胜!");break;
                        }
                        else if(downBlock1() == -2){
                            if(grade1==grade2){
                            printf("平     局");break;
                            }
                            else{
                            printf("蓝 方 胜!");break;
                            }
                        }

            }
            time1 = time2;
        }

    }

else if(mode == 3){
        setPos(2,10);
        printf("剩余时间:%3dS",counter);
        setPos(50,10);
        printf("剩余时间:%3dS",counter);
   if((float)(time2-time1)/CLOCKS_PER_SEC > speed){
                counter--;
                setPos(27,2);
                if(counter == 0){
                    if(grade2>grade1){
                            printf("蓝 方 胜!");break;
                        }
                    if(grade1==grade2){
                            printf("平     局");break;
                    }
                    else{
                            printf("红 方 胜!");break;
                        }
                }

            if(downBlock1() == -2) {
                    if(grade2>grade1){
                            printf("蓝 方 胜!");break;
                        }
                        else if(downBlock2() == -2){
                            if(grade1==grade2){
                            printf("平     局");break;
                            }
                            else{
                            printf("红 方 胜!");break;
                            }
                        }
                    }
                setPos(27,3);
            if(downBlock2() == -2) {
                  if(grade1>grade2){
                            printf("红 方 胜!");break;
                        }
                        else if(downBlock1() == -2){
                            if(grade1==grade2){
                            printf("平     局");break;
                            }
                            else{
                            printf("蓝 方 胜!");break;
                            }
                        }

            }
            time1 = time2;


    }

}
}
 if(mode == 1){
         mciSendString("close d",NULL,0,NULL);

    }
    if(mode == 2){
        mciSendString("close e",NULL,0,NULL);

    }
    if(mode == 3){
        mciSendString("close f",NULL,0,NULL);

    }
Sleep(1150);
printOver();
printFinish(mode);
}

Initial interface animation printing

void printStart(int x,int y){
     //随机产生颜色
    int color = rand()%0x10;
    //处理黑色的情况
    if(color == 0x00)
    {
        color = 0x0f;
    }

    setColor(color);
    setPos(x,y);
    printf("■■■■■  ■■■■■  ■■■■■  ■■■■  ■■■  ■■■■");
    setPos(x,y+1);
    printf("    ■      ■              ■      ■    ■    ■    ■");
    setPos(x,y+2);
    printf("    ■      ■■■■        ■      ■■■      ■      ■■■");
    setPos(x,y+3);
    printf("    ■      ■              ■      ■  ■      ■          ■");
    setPos(x,y+4);
    printf("    ■      ■■■■■      ■      ■    ■  ■■■  ■■■");

    setPos(25,14);
    printf("按任意键开始游戏!");
    setPos(50,30);
    printf("author 赵敬轩");
    }

game.c complete code

Source address

gitee:https://gitee.com/i-dream-code/Tetris/

github:https://github.com/zhaojingxuan123/StrongestTetris

Baidu Cloud Disk: Link: https://pan.baidu.com/s/1dJeANXcNqChrXf7zuRQRWw Extraction code: geee

import method

The blogger uses codeblocks, a very useful compiler

Network disk link: Link: https://pan.baidu.com/s/1JkgUL8852lwx87j1NK2nsw Extraction code: qqfm

After installing codeblocks, drag 20200705.cbp directly to the left panel of codeblocks

Above build=>run to run

 Summarize

        Looking back now, this project has many problems, such as bloated code, poor reusability, no use of design patterns, and repeated creation of many wheels. In addition, some function settings are not reasonable enough, such as not returning to the previous menu, switching modes can only be entered by recompiling the game. The game is a one-time game, and adding a scoreboard to store the player's highest score can also increase the gaming experience. There will be an opportunity to improve it in the future.

        "Self-discipline in prosperity, self-healing in depression", in a trance, looking back on the years, I am calm.

Guess you like

Origin blog.csdn.net/weixin_45660485/article/details/122706747