界面很丑旦问题不大,主要还是为了实现功能。
需要用到的头文件:
#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;
}
如果单用_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;
}
}