11.png

界面很丑旦问题不大,主要还是为了实现功能。

需要用到的头文件:

#include "pch.h"            //这是vs里默认添加的   如果在别的编译器报错就把这句删掉
#include 
#include 
#include "windows.h"
#include  

一些定义:

模型的数量与颜色数量

#define mod_max 7
#define colo_max 8

#define random(x) (rand()%x)//定义随机数范围

定义颜色值

#define blue              0x01
#define green             0x02
#define red               0x04
#define hig               0x08
#define yellow            red|green
#define lightblue         blue|green
#define purple            red|blue
#define white             blue|green|red

定义按键键值

#define dd 80
#define ll 75
#define rr 77
#define uu 72

#define esc 27
#define space 32

获得控制台资源句柄

HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);

颜色表

char colo_tab[colo_max] =
{
    blue,
    green,
    red,
    hig,
    yellow,
    lightblue,
    purple,
    white,
};

7个模型 每个模型4个方向 每个方向5行

char mod[mod_max][4][5] =
{
//mod0
{
    {
        0x80,
        0xc0,
        0x80,
    },
    {
        0x40,
        0xe0,
    },
    {
        0x40,
        0xc0,
        0x40,
    },
    {
        0xe0,
        0x40,
    },
},
//mod1
{
    {
        0xc0,
        0x60,
    },
    {
        0x40,
        0xc0,
        0x80,
    },
    {
        0xc0,
        0x60,
    },
    {
        0x40,
        0xc0,
        0x80,
    },
},
//mod2
{
    {
        0xc0,
        0xc0,
    },
    {
        0xc0,
        0xc0,
    },
    {
        0xc0,
        0xc0,
    },
    {
        0xc0,
        0xc0,
    },
},
//mod3
{
    {
        0x80,
        0x80,
        0x80,
        0x80,
    },
    {
        0xf0,
    },
    {
        0x80,
        0x80,
        0x80,
        0x80,
    },
    {
        0xf0,
    },
},
//mod4
{
    {
        0x20,
        0xe0,
    },
    {
        0xc0,
        0x40,
        0x40,
    },
    {
        0xe0,
        0x80,
    },
    {
        0x80,
        0x80,
        0xc0,
    },
},
//mod5
{
    {
        0x60,
        0xc0,
    },
    {
        0x80,
        0xc0,
        0x40,
    },
    {
        0x60,
        0xc0,
    },
    {
        0x80,
        0xc0,
        0x40,
    },
},
//mod6
{
    {
        0xe0,
        0x20,
    },
    {
        0x40,
        0x40,
        0xc0,
    },
    {
        0x80,
        0xe0,
    },
    {
        0xc0,
        0x80,
        0x80,
    },
},
};

棋盘的缓存

char map[25][25];
void set_colo(char colo)//用于设置字体颜色
{
SetConsoleTextAttribute(hOut, colo | hig);
}

void colo_print(char colo,const char *p)/可以设置颜色的显示
{
SetConsoleTextAttribute(hOut,colo|hig);
printf(p);
SetConsoleTextAttribute(hOut, white | hig);
}
void set_y_x(int y, int x)//设置光标位置
{
COORD pos = { x,y };
SetConsoleCursorPosition(hOut, pos);
}
void y_x_colo_print(int y,int x,char colo,const char *p)//可以设置坐标以及颜色的文件显示
{
set_y_x(y,x);
colo_print(colo,p);
}

到这里驱动部分已经完成了 现在要做的就是写逻辑部分

下面是核心代码:

棋盘显示函数 放在主函数中循环调用棋盘大小是2020 用两个for循环扫描整个棋盘 如果棋盘中有数据就将它显示出来 如果没有就显示空格将之前的缓存刷掉这里要注意"█"这个字符占用两个字节所以把x轴2,填充空格的时候也要填充两个。整个棋盘并不是从0,0开始的所以要加偏移量也就是y+3,x+1.

void dis_map()
{
int y, x;
for (y = 0; y < 20; y++)
{
    for (x = 0; x < 20; x++)
    {
        if (map[y][x] != 0)
        {
            y_x_colo_print(y+3, (x+1)*2, map[y][x], "█");
        }
        else
        {
            y_x_colo_print(y + 3, (x + 1) * 2, map[y][x], "  ");
        }
    }
}
}

把模型放到棋盘里,参数有y,x也就是位置,m是模型,d是方向,最后就是颜色

char dis_mod_in_map(char y,char x,char m,char d,char colo)//返回1正常  2碰壁  4到底
{
char a,b,c,e=1;
    //这里是把每个模型放在5*5的空间里  如果自己添加模型不能大于这个值
for (a = 0; a < 5; a++)//扫描模型的每一行
{    
    c = mod[m][d][a];//获取模型的每一行的数据
    for (b = 0; b < 5; b+=1)
    {
        if (c & 0x80)//通过与最高位的方式获得列数据
        {
            if (colo != 0)//如果是有数据的
            {
                                    //判断有没有超过两边的边界
                if (((b + x) < 0) || ((b + x) > 19)|| (map[a + y][b + x] != 0))                     

{

                    e = e & ~0x01;
                    e = e|2;
                }
                                    //判断有没有到底,到底和碰壁是可以同时存在的
                if (((a + y) == 20) || (map[a + y][b + x] != 0))
                {
                    e = e & ~0x01;
                    e = e | 4;

                }
            }            
        }
        c <<= 1;
    }
}
    //如果到底了就讲模型固定到棋盘
if (e & 1)
{
    for (a = 0; a < 5; a++)
    {
        c = mod[m][d][a];
        for (b = 0; b < 5; b += 1)
        {
            if (c & 0x80)
            {
                if (colo == 0)
                {
                    map[a + y][b + x] = 0;
                }
                else
                {
                    map[a + y][b + x] = colo;
                }
            }
            c <<= 1;
        }
    }

}
return e;
}

12.png
如果单用_getch()会导致程序阻塞,程序会一直等待按键输入,所以在这之前用_kbhit()检查是否有按键按下,这个函数如果有按键被按下会返回1而且不会造成程序阻塞.

char get_key()
{
char a;
if (_kbhit() == 1)
{
    a = _getch();
    return a;
}
return 0;

}

检查是否满一行,程序从最下面一行也就是第19行开始往上扫描(19到0)扫描每一行中每一列是否都有数据,每一行的开始都给flag置1然后开始扫描行的内容只要有一个单位是空(0)就说明这行没满flag置0,如果这行一行扫描完flag还是1说明这行满了 从这行开始把上面的内容往下移然后y+1再扫描一次这一行 这样就可以连续消除满行,最后没消除一行分数加100,分数满1000提升一个等级下落速度加快.

void charackwin()
{
char y, x,flag=0,y2;
for (y = 19; y > 0; y--)
{
    flag = 1;
    for (x = 0; x < 20; x++)
    {
        if (map[y][x] == 0)
        {
            flag = 0;
        }
    }
    if (flag == 1)
    {

        for (y2 = y; y2 > 1; y2--)
        {
            for (x = 0; x < 20; x++)
            {
                map[y2][x] = map[y2 - 1][x];
            }
        }
        score += 100;
        if (score >= 1000)
        {
            score = 0;
            level += 1;
            speed -= 20;
        }
        y += 1;

    }
}
}

有了这些核心代码 剩下的功能随便写

下面是完整代码:

    // 1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include 
#include 
#include "windows.h"
#include

#define mod_max 7
#define colo_max 8

#define random(x) (rand()%x)//定义随机数范围

#define blue              0x01
#define green             0x02
#define red               0x04
#define hig               0x08
#define yellow            red|green
#define lightblue         blue|green
#define purple            red|blue
#define white             blue|green|red

#define dd 80
#define ll 75
#define rr 77
#define uu 72

#define esc 27
#define space 32

HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);

char colo_tab[colo_max] =
{
    blue,
    green,
    red,
    hig,
    yellow,
    lightblue,
    purple,
    white,
};
char mod[mod_max][4][5] =
{
    //mod0
    {
        {
            0x80,
            0xc0,
            0x80,
        },
        {
            0x40,
            0xe0,
        },
        {
            0x40,
            0xc0,
            0x40,
        },
        {
            0xe0,
            0x40,
        },
    },
    //mod1
    {
        {
            0xc0,
            0x60,
        },
        {
            0x40,
            0xc0,
            0x80,
        },
        {
            0xc0,
            0x60,
        },
        {
            0x40,
            0xc0,
            0x80,
        },
    },
    //mod2
    {
        {
            0xc0,
            0xc0,
        },
        {
            0xc0,
            0xc0,
        },
        {
            0xc0,
            0xc0,
        },
        {
            0xc0,
            0xc0,
        },
    },
    //mod3
    {
        {
            0x80,
            0x80,
            0x80,
            0x80,
        },
        {
            0xf0,
        },
        {
            0x80,
            0x80,
            0x80,
            0x80,
        },
        {
            0xf0,
        },
    },
    //mod4
    {
        {
            0x20,
            0xe0,
        },
        {
            0xc0,
            0x40,
            0x40,
        },
        {
            0xe0,
            0x80,
        },
        {
            0x80,
            0x80,
            0xc0,
        },
    },
    //mod5
    {
        {
            0x60,
            0xc0,
        },
        {
            0x80,
            0xc0,
            0x40,
        },
        {
            0x60,
            0xc0,
        },
        {
            0x80,
            0xc0,
            0x40,
        },
    },
    //mod6
    {
        {
            0xe0,
            0x20,
        },
        {
            0x40,
            0x40,
            0xc0,
        },
        {
            0x80,
            0xe0,
        },
        {
            0xc0,
            0x80,
            0x80,
        },
    },
};

char map[25][25];

void set_colo(char colo)
{
    SetConsoleTextAttribute(hOut, colo | hig);
}

void colo_print(char colo,const char *p)
{
    SetConsoleTextAttribute(hOut,colo|hig);
    printf(p);
    SetConsoleTextAttribute(hOut, white | hig);
}
void set_y_x(int y, int x)
{
    COORD pos = { x,y };
    SetConsoleCursorPosition(hOut, pos);
}
void y_x_colo_print(int y,int x,char colo,const char *p)
{
    set_y_x(y,x);
    colo_print(colo,p);
}

void title()
{
    char a;
    y_x_colo_print(0,8,white,"趣  味  俄  罗  斯  方  块");
    y_x_colo_print(2, 2, lightblue, "█");
    y_x_colo_print(3, 2, lightblue, "█");
    y_x_colo_print(3, 4, lightblue, "█");
    y_x_colo_print(4, 2, lightblue, "█");

    y_x_colo_print(3, 10, yellow, "█");
    y_x_colo_print(3, 12, yellow, "█");
    y_x_colo_print(4, 12, yellow, "█");
    y_x_colo_print(4, 14, yellow, "█");

    y_x_colo_print(3, 20, green, "█");
    y_x_colo_print(4, 20, green, "█");
    y_x_colo_print(3, 22, green, "█");
    y_x_colo_print(4, 22, green, "█");

    y_x_colo_print(2, 28, purple, "█");
    y_x_colo_print(3, 28, purple, "█");
    y_x_colo_print(4, 28, purple, "█");
    y_x_colo_print(5, 28, purple, "█");

    y_x_colo_print(3, 38, red, "█");
    y_x_colo_print(4, 34, red, "█");
    y_x_colo_print(4, 36, red, "█");
    y_x_colo_print(4, 38, red, "█");

    for (a = 6; a < 20; a++)
    {
        if (a == 6 || a == 19)
        {
            y_x_colo_print(a, 0, yellow, "============================================");
        }
        else
        {
            y_x_colo_print(a, 0, yellow, "||                                        ||");
        }
    }

    y_x_colo_print(10, 10, red, "1.开始游戏    2.按键说明");
    y_x_colo_print(16, 10, red, "3.游戏规则    4.退出");
}
void flower()
{
    y_x_colo_print(6, 44, purple, "                 (_)");
    y_x_colo_print(7, 44, purple, "               (_) (_)");
    y_x_colo_print(8, 44, purple, "                 (_)");

    y_x_colo_print(8, 44, red,  "        (_)");
    y_x_colo_print(9, 44, red,  "      (_) (_)");
    y_x_colo_print(10, 44, red, "        (_)");

    y_x_colo_print(7, 62, yellow, "@");
    y_x_colo_print(9, 53, yellow, "@");
    y_x_colo_print(8, 59, yellow, "/");
    y_x_colo_print(9, 58, yellow, "|");
    y_x_colo_print(10, 58, yellow, "|");
    y_x_colo_print(10, 57, yellow, "");
    y_x_colo_print(11, 58, yellow, "|");
    y_x_colo_print(11, 59, yellow, "/");
    y_x_colo_print(12, 58, yellow, "|");
    y_x_colo_print(12, 57, yellow, "");
    y_x_colo_print(13, 58, yellow, "|");
    y_x_colo_print(13, 59, yellow, "/");
    y_x_colo_print(14, 58, yellow, "|");

    y_x_colo_print(14, 54, green, "");
    y_x_colo_print(14, 60, green, "//");
    y_x_colo_print(15, 54, green, "^^^^^^^^");
}
void welcome()
{
    y_x_colo_print(21, 8, lightblue, "请选择[1 2 3 4]:[]");
}
void draw_game_frame()
{
    char a;
    y_x_colo_print(0, 10, lightblue, "趣味俄罗斯方块");

    for (a = 0; a < 22; a++)
    {
        if (a == 0||a==21)
        {
            y_x_colo_print(a+2, 0, red,   " = = = = = = = = = = = = = = = = = = = = = ");
        }
        else
        {
            y_x_colo_print(a + 2, 0, red, "|                                         |");
        }
    }

}

void dis_map()
{
    int y, x;

    //map[0][0] = blue;
    //map[19][39] = blue;
    for (y = 0; y < 20; y++)
    {
        for (x = 0; x < 20; x++)
        {
            if (map[y][x] != 0)
            {
                y_x_colo_print(y+3, (x+1)*2, map[y][x], "█");
            }
            else
            {
                y_x_colo_print(y + 3, (x + 1) * 2, map[y][x], "  ");
            }
        }
    }
}

char dis_mod_in_map(char y,char x,char m,char d,char colo)//返回1正常  2碰壁  4到底
{
    char a,b,c,e=1;
    for (a = 0; a < 5; a++)
    {    
        c = mod[m][d][a];
        for (b = 0; b < 5; b+=1)
        {
            if (c & 0x80)
            {
                if (colo != 0)
                {
                    if (((b + x) < 0) || ((b + x) > 19)|| (map[a + y][b + x] != 0))
                    {
                        e = e & ~0x01;
                        e = e|2;
                    }
                    if (((a + y) == 20) || (map[a + y][b + x] != 0))
                    {
                        e = e & ~0x01;
                        e = e | 4;

                    }
                }            
            }
            c <<= 1;
        }
    }
    if (e & 1)
    {
        for (a = 0; a < 5; a++)
        {
            c = mod[m][d][a];
            for (b = 0; b < 5; b += 1)
            {
                if (c & 0x80)
                {
                    if (colo == 0)
                    {
                        map[a + y][b + x] = 0;
                    }
                    else
                    {
                        map[a + y][b + x] = colo;
                    }
                }
                c <<= 1;
            }
        }

    }
    return e;
}
char get_key()
{
    char a;
    if (_kbhit() == 1)
    {
        a = _getch();
        return a;
    }
    return 0;

}

char ch;         //按键的状态
char state = 0;  //游戏状态
char yy=0, xx=10;//全局坐标
char mm = 0;    //全局模型
char cc = blue;   //全局颜色
char dir= 0;    //全局方向

char next_mm = 0;    //下一个模型
char next_cc = blue;   //下一个颜色
char next_dir = 0;    //下一个方向

int level = 1;
int score = 0;
int speed = 300;
int speed_js = 300;
long move_time;
char zt_flag = 0;
int move_js = 0;

char d_move()
{
    char e=0;
    speed_js = speed;
    if (ch == dd)
    {
        speed_js = 0;
    }

    if (ch == space)
    {
        if (zt_flag == 0)
        {
            zt_flag = 1;
        }
        else
        {
            zt_flag = 0;
        }
    }
    if (ch == uu)
    {
        dis_mod_in_map(yy, xx, mm, dir, 0);
        dir = (dir == 3) ? dir = 0 : ++dir;
        dis_mod_in_map(yy, xx, mm, dir, cc);
    }

    if (ch == rr)
    {
        dis_mod_in_map(yy, xx, mm, dir, 0);
        xx++;        
        if (dis_mod_in_map(yy, xx, mm, dir, cc) & 2)
        {
            //dis_mod_in_map(yy, xx, mm, dir, 0);
            xx--;
            dis_mod_in_map(yy, xx, mm, dir, cc);
        }
    }
    if (ch == ll)
    {
        dis_mod_in_map(yy, xx, mm, dir, 0);
        xx--;
        if (dis_mod_in_map(yy, xx, mm, dir, cc) & 2)
        {
            //dis_mod_in_map(yy, xx, mm, dir, 0);
            xx++;
            dis_mod_in_map(yy, xx, mm, dir, cc);
        }
    }

    if (zt_flag == 0)
    {
        if (clock() > move_time)
        {
            move_time = clock() + speed_js;
            dis_mod_in_map(yy, xx, mm, dir, 0);
            yy += 1;
            if (dis_mod_in_map(yy, xx, mm, dir, cc) & 4)
            {
                if (move_js == 0)
                {
                    e = 2;
                }
                else
                {
                    e = 1;
                    move_js = 0;
                }
                yy--;
                dis_mod_in_map(yy, xx, mm, dir, cc);

            }
            else
            {
                move_js += 1;
            }
        }
    }

    return e;
}

void dis_next_mod()
{
    char map_buff[5][5];
    char y, x, c;
    for (y = 0; y < 5; y++)
    {
        for (x = 0; x < 5; x++)
        {
            map_buff[y][x] = 0;
        }
    }
    for (y = 0; y < 5; y++)
    {
        c = mod[next_mm][next_dir][y];
        for (x = 0; x < 5; x++)
        {
            if (c & 0x80)
            {
                map_buff[y][x] = next_cc;
            }
            c <<= 1;
        }
    }
    for (y = 0; y < 5; y++)
    {
        for (x = 0; x < 5; x++)
        {
            y_x_colo_print(10 + y, (25 + x) * 2, map_buff[y][x], "  ");
            if (map_buff[y][x] != 0)
            {
                y_x_colo_print(10 + y, (25 + x) * 2, map_buff[y][x], "█");
            }
        }
    }
}
void dis_data()
{
    set_colo(red);
    set_y_x(3,48);
    printf("level:%d", level);
    set_y_x(5, 48);
    printf("score:%d", score);
    set_y_x(7, 48);
    printf("speed:%dms", speed);
    y_x_colo_print(9,48,green,"**********");
    y_x_colo_print(9, 58, lightblue, "下一个出现方块:");

    y_x_colo_print(15, 48, green, "**********");

    y_x_colo_print(17, 48, yellow, "Esc:退出游戏");
    y_x_colo_print(19, 48, yellow, "↑键旋转");
    y_x_colo_print(21, 48, yellow, "空格:暂停游戏");

    dis_next_mod();

}

void end()
{
    y_x_colo_print(0, 0, red, "           ████    █      █    ██");
    y_x_colo_print(1, 0, red, "           █          ██    █    █  █");
    y_x_colo_print(2, 0, red, "           ████    █  █  █    █   █");
    y_x_colo_print(3, 0, red, "           █          █    ██    █  █");
    y_x_colo_print(4, 0, red, "           ████    █      █    ██");

    y_x_colo_print(20, 0, yellow, "我想重新玩一局--------1    不玩了,退出吧--------2");

}

void charackwin()
{
    char y, x,flag=0,y2;
    for (y = 19; y > 0; y--)
    {
        flag = 1;
        for (x = 0; x < 20; x++)
        {
            if (map[y][x] == 0)
            {
                flag = 0;
            }
        }
        if (flag == 1)
        {

            for (y2 = y; y2 > 1; y2--)
            {
                for (x = 0; x < 20; x++)
                {
                    map[y2][x] = map[y2 - 1][x];
                }
            }
            score += 100;
            if (score >= 1000)
            {
                score = 0;
                level += 1;
                speed -= 20;
            }
            y += 1;

        }
    }
}
int main()
{
    //系统初始化
    char game_mod = 0;
    char d_flag;
    char y, x;
    title();
    flower();
    welcome();
    srand((int)time(0));                    //设置随机数种子
    while (1)
    {
        //游戏初始化
        ch = _getch();
        if (ch == 49)
        {
            game_mod = 1;
            printf("starn");
            system("cls");
            draw_game_frame();
        }
        ch = 0;
        while(game_mod)
        {
            ch=get_key();
            if (ch == esc)
            {
                return 0;
            }
            switch (state)
            {
            case 0:
                yy = 0;
                xx = 10;

                mm = next_mm;
                cc = next_cc;
                dir = next_dir;
                next_mm = random(mod_max);
                next_cc = colo_tab[random(colo_max)];
                next_dir= random(4);
                draw_game_frame();
                charackwin();
                dis_mod_in_map(yy, xx, mm, dir, cc);

                state = 1;
                break;
            case 1:   //下落状态
                d_flag = d_move();
                dis_data();
                if (d_flag ==1)
                {
                    state = 0;
                }
                dis_map();                        
                if (d_flag == 2)
                {
                    system("cls");
                    state = 2;
                }            
                break;
            case 2:
                end();
                ch = _getch();
                if (ch == 49)
                {
                    for (y = 0; y < 25; y++)
                    {
                        for (x = 0; x < 25; x++)
                        {
                            map[y][x] = 0;
                        }
                    }
                    level = 1;
                    score = 0;
                    speed = 300;
                    system("cls");
                    state = 0;
                }
                else
                {
                    return 0;
                }
                break;
            default:
                break;
            }
        }

        //return 0;
    }
}
最后修改:2020 年 08 月 24 日
声明:无闻风博客|版权所有,违者必究|如未注明,均为原创| 转载:转载请注明原文链接