去年年底写的代码,有点意思
一些控制台函数
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo; //设置控制台用的
void windows_init()
{
GetConsoleCursorInfo(hOut, &CursorInfo); //获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOut, &CursorInfo); //设置控制台光标状态
srand(time(0));
}
void myprint(int y, int x, char colo,char color, const char* p)//
{
COORD pos = { x,y };
SetConsoleCursorPosition(hOut, pos);
SetConsoleTextAttribute(hOut, colo+(color*0x10));
printf(p);
}
char get_key() //获得按键键值
{
char a;
if (_kbhit() == 1) //由于单使用 _getch()会导致程序堵塞,所以用先用_kbhit()获得是否有按键按下
{
a = _getch();
return a;
}
return 0;
}
long HAL_GetTick()
{
return clock();
}
void HAL_Delay(long a)
{
long b;
b = HAL_GetTick() + a;
while (b> HAL_GetTick());
}
主程序
int map[4][4] = //棋盘
{
{0,2,4,8,},
{16,32,64,128,},
{256,512,1024,2048,},
{4096,8192,0,0,},
};
int colo_tab[14] =//颜色表
{
0,
blue| hig,
green| hig,
red|hig,
yellow|hig,
lightblue|hig,
purple|hig,
white|hig,
blue,
green,
red,
yellow,
lightblue,
purple,
};
int dpow(int d)//计算颜色表中的第几个颜色
{
int a;
if (d == 0)
{
return 0;
}
for (a = 0; a < 14; a++)
{
if (pow(2, a) == d)
{
return a;
}
}
}
void dis_map()
{
char y = 0, x = 0;
int z;
char buff[7];
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
z = map[y][x];
sprintf(buff,"% 5d", z);
myprint((y * 3), x * 5, 0, colo_tab[dpow(z)], " ");
myprint((y * 3) + 1, x * 5, 0, colo_tab[dpow(z)], buff);
myprint((y * 3)+2, x * 5, 0, colo_tab[dpow(z)], " ");
}
}
for (y = 0; y < 12; y++)
{
myprint(y, 20, white, 0, "|");
}
myprint(12, 0, white, 0, "---------------------");
}
#define random(x) (rand()%x)//定义随机数范围
int game_mod = 0; //游戏模式
char ch; //按键状态
unsigned int best = 0, score = 0;//分数
char move_jc_buff = 0; //是否可以移动
void clear_map() //清空棋盘
{
char y, x;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
map[y][x] = 0;
}
}
}
unsigned int move(char dir) //返回值最高位为1表示可以移动 剩下的位表示移动的分数
{
char move_flag = 0; //移动标志
int y = 0, x = 0, y2, x2;
unsigned int fs = 0; //分数
//一共4个方向
if (dir == uu) //向上
{
for (x = 0; x < 4; x++) //从左往右扫描
{
for (y = 0; y < 4; y++) //从上往下扫描
{
if (map[y][x] != 0) //如果扫到不为空
{
y2 = y; //避免改变y
while (((y2 - 1) >= 0)) //扫描这一条 直到碰边
{
if ((map[y2 - 1][x] == 0)) //如果往上的一个位置是空的
{
map[y2 - 1][x] = map[y2][x];//把当前的向上移
map[y2][x] = 0; //清空当前
move_flag = 1; //成功移动了
}
if (map[y2 - 1][x] == map[y2][x])//如果当前与往上一个位置是相等的
{
map[y2 - 1][x] = map[y2][x] + map[y2 - 1][x];//加起来
fs = fs + map[y2 - 1][x]; //分数加上
map[y2][x] = 0; //清空当前
move_flag = 1; //成功移动了
}
y2 -= 1; //扫描下一格
}
}
}
}
}
if (dir == dd)
{
for (x = 0; x < 4; x++)
{
for (y = 3; y >= 0; y--)
{
if (map[y][x] != 0)
{
y2 = y;
while (((y2 + 1) <= 3))
{
if ((map[y2 + 1][x] == 0))
{
map[y2 + 1][x] = map[y2][x];
map[y2][x] = 0;
move_flag = 1;
}
if (map[y2 + 1][x] == map[y2][x])
{
map[y2 + 1][x] = map[y2][x] + map[y2 + 1][x];
fs = fs + map[y2 + 1][x];
map[y2][x] = 0;
move_flag = 1;
}
y2 += 1;
}
}
}
}
}
if (dir == ll)
{
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if (map[y][x] != 0)
{
x2 = x;
while (((x2 - 1) >= 0))
{
if ((map[y][x2 - 1] == 0))
{
map[y][x2 - 1] = map[y][x2];
map[y][x2] = 0;
move_flag = 1;
}
if (map[y][x2 - 1] == map[y][x2])
{
map[y][x2 - 1] = map[y][x2] + map[y][x2 - 1];
fs = fs + map[y][x2 - 1];
map[y][x2] = 0;
move_flag = 1;
}
x2 -= 1;
}
}
}
}
}
if (dir == rr)
{
for (y = 0; y < 4; y++)
{
for (x = 3; x >= 0; x--)
{
if (map[y][x] != 0)
{
x2 = x;
while (((x2 + 1) <= 3))
{
if ((map[y][x2 + 1] == 0))
{
map[y][x2 + 1] = map[y][x2];
map[y][x2] = 0;
move_flag = 1;
}
if (map[y][x2 + 1] == map[y][x2])
{
map[y][x2 + 1] = map[y][x2] + map[y][x2 + 1];
fs = fs + map[y][x2 + 1];
map[y][x2] = 0;
move_flag = 1;
}
x2 += 1;
}
}
}
}
}
if (move_flag == 1)
{
fs |= 0x8000; //如果移动了把返回值分数的最高位置一
}
else
{
fs &= ~0x8000;
}
return fs;
}
char move_jc() //检测是否可以移动
{
char y, x, a, e = 0;
int map_buff[4][4];
char move_tab[4] = //方向表
{
uu,
dd,
ll,
rr,
};
for (y = 0; y < 4; y++)//先备份当前棋盘
{
for (x = 0; x < 4; x++)
{
map_buff[y][x] = map[y][x];
}
}
for (a = 0; a < 4; a++) //检测4个方向
{
if (move(move_tab[a]) & 0x8000)//最高位为1移动成功
{
e = 1; //标记置一
break; //跳出for
}
}
for (y = 0; y < 4; y++) //还原棋盘
{
for (x = 0; x < 4; x++)
{
map[y][x] = map_buff[y][x];
}
}
return e; //返回结果
}
void rand_dot() //随机放一个2
{
char y, x;
do
{
x = random(4); //获得随机数范围0-4
y = random(4);
} while (map[y][x]); //坐标不合法 再获一次
map[y][x] = 2; //坐标合法 放2
}
int main()
{
windows_init();
unsigned int jg;
char buff[10];
while (1)
{
ch = get_key(); //获取键值
switch (game_mod)
{
case 0:
if (ch == space) //如果空格被按下
{
clear_map(); //清空棋盘
map[2][3] = 2; //2默认初始位置
srand((int)time(0)); //设置随机数种子
game_mod = 1; //游戏开始
}
break;
case 1:
move_jc_buff = move_jc(); //获取是否还能移动
if (move_jc_buff == 0) //如果不能移动游戏结束
{
game_mod = 2; //游戏结束
}
else
{
if (ch ==uu|| ch == dd || ch == ll || ch == rr) //否则判断是否有按键按下
{
jg = move(ch); //获取移动结果
if (jg & 0x8000) //如果move的返回值最高位为1 成功移动
{
jg &= ~0x8000; //去掉最高位的1
score += jg; //加给分数
rand_dot(); //随机坐标给一个2
}
}
}
break;
case 2:
if (ch == space) //按下空格
{
if (score > best) //如果破纪录了
{
best = score; //更新最高记录
}
score = 0; //当前分数清零
game_mod = 0; //回到欢迎界面
}
break;
case 3:
break;
default:
break;
}
myprint(13,0,white,0,"2048小游戏,空格开始");
sprintf(buff, "当前分数:%05d", score);
myprint(14, 0, white, 0, buff);
sprintf(buff, "最高分数:%05d", best);
myprint(15, 0, white, 0, buff);
myprint(18, 0, white, 0, "吴文峰 2019-12-12");
dis_map();
}
}