目录
设计一个简单的推箱子游戏
该游戏是通过控制人的走向来移动箱子,箱子只能向前推,不能向后拉,且一次只能推动一个箱子。
功能设计要求:
- 人机操控平台:启动程序后,系统提供给用户一个操作界面,以便用户有效操作游戏。
- 创建并绘制地图:推箱子游戏需要创建不同的地图以增加游戏的趣味性。
- 选择地图:系统应提供两个及以上不同难度的地图以供用户选择。
- 移动操作:本游戏主要通过人或人和箱子的移动来进行的。系统接收用户输入一个字符(按键)来控制人的走向,并且可以在允许的情况下推动箱子。
- 移动步数和得分:移动步数是统计从开始游戏到游戏结束(通关)所走的总步数,在游戏过程中这是实时变化的。得分是统计每将一个箱子移动到目的地所获得的分数,只有当把所有箱子移动到指定目标位置后游戏结束(通关)。
- 游戏操作说明:系统给用户提供地图元素组成、操作规则等信息
代码实现
基础代码在用C语言实现推箱子小游戏基础程序_Cheat_Meric的博客-CSDN博客中实现。
在用C语言实现推箱子小游戏基础程序_Cheat_陈十一的博客-CSDN博客中的解释较为详细细致,在这里不再对代码进行过多的解释,下面直接介绍代码。
在上一代码的基础上,增加了菜单界面以及关卡选择
在上一代码中提出的代码优化中,提出的旋转矩阵+上移操作以达成左右下移操作,在编写程序过程中发现虽然代码量减少,但是运行时长是之前的数十倍。
数据定义头文件data_def.h
#ifndef __DATA_DEF_H__ #define __DATA_DEF_H__ #define Box_Size 60 #define Box_Num 9 #define Round_Num 3 //记录玩家位置 struct Player { int x; int y; }; Player player; enum Element { empty, wall, role, target, box, achieve, data_bg, role_target }; //1表示墙,0表示空地,2表示玩家位置,3目标位置,4箱子位置,5表示achieve,6表示data_bg,7表示role_target int origin_Round[Round_Num][Box_Num][Box_Num + 1] = { { {1,1,1,1,1,1,1,1,1,6}, {1,1,0,0,0,1,1,1,1,6}, {1,1,0,0,0,1,0,0,1,6}, {1,1,1,0,0,0,0,3,1,6}, {1,1,1,0,1,1,1,3,1,6}, {1,0,4,0,1,1,1,3,1,6}, {1,0,4,4,1,1,1,1,1,6}, {1,2,0,0,1,1,1,1,1,6}, {1,1,1,1,1,1,1,1,1,6}, }, { {1,1,1,1,1,1,1,1,1,6}, {1,1,1,3,3,5,3,1,1,6}, {1,1,1,3,4,0,0,1,1,6}, {1,1,1,1,0,4,0,1,1,6}, {1,1,1,1,4,0,1,1,1,6}, {1,1,1,2,4,0,1,1,1,6}, {1,1,1,1,0,0,0,1,1,6}, {1,1,1,1,1,1,1,1,1,6}, }, { {1,1,1,1,1,1,1,1,1,6}, {1,1,target,0,0,0,box,0,1,6}, {1,1,target,box,0,0,1,0,1,6}, {1,1,target,1,0,1,0,0,1,6}, {1,1,1,1,0,1,0,1,1,6}, {1,1,1,0,box,0,0,1,1,6}, {1,1,1,role,0,1,1,1,1,6}, {1,1,1,1,1,1,1,1,1,6}, }, }; //last_step[Box_Num][Box_Num + 1]用于悔棋,记录上一步操作 //First_Round[Box_Num][Box_Num + 1]每一关的矩阵 int last_step[Box_Num][Box_Num + 1], First_Round[Box_Num][Box_Num]; /* * targetNum目标数量 * achievementNum箱子推到目标的成功数量 * steps记录步数 * level当前关卡 */ int targetNum = 0, achievementNum = 0, steps, level; /* * Menu_Opt菜单选择 * Begin开始游戏的flag * quit_flag退出判定 */ int Menu_Opt = 0, Begin = 0, quit_flag = 0; #endif // !__DATA_DEF_H__
一些会用到的数据的定义,由于origin_Round关卡数组比较多,所以单独存放在一个头文件中。
窗口设置头文件WindowsSet.h
#ifndef __WINDOWSSET_H__ #define __WINDOWSSET_H__ #ifndef __DATA_DEF_H__ #define __DATA_DEF_H__ #include "data_def.h" #endif // !__DATA_DEF_H__ int check_lose_win(void);//检查游戏是否结束 void Windows_Init(void);//窗口初始化 void Windows_Show(void);//展示游戏窗口 void Flash_Frame(void);//游戏帧轮询 void Next_Round(void);//下一关 void Start_Up(void);//开始界面 void clear_opt(void);//菜单界面选择的覆盖,覆盖之前的'@' void Menu_Flash_Frame(void);//菜单界面帧 void matrix_up(void);//上移操作 void matrix_rotate(int m);//矩阵顺时针旋转m次 #endif // !__WINDOWSSET_H__
WindowsSet.cpp
可以直接跳到最后一条总代码页看总代码
上移函数
//上移操作 void matrix_up(void) { int role_x, role_y; role_x = player.x - 1; if (First_Round[role_x][player.y] == empty) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role; player.x = role_x; steps++; } else if (First_Round[role_x][player.y] == target) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role_target; player.x = role_x; steps++; } else if ((First_Round[role_x][player.y] == box || First_Round[role_x][player.y] == achieve) && (First_Round[role_x - 1][player.y] == empty || First_Round[role_x - 1][player.y] == target))//判断有wall { if (First_Round[role_x][player.y] == box) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role; player.x = role_x; if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve { First_Round[role_x - 1][player.y] = achieve; achievementNum++; } else First_Round[role_x - 1][player.y] = box; } else if (First_Round[role_x][player.y] == achieve) { achievementNum--; if (First_Round[player.x][player.y] == role)//此位置是玩家位置 First_Round[player.x][player.y] = empty;//此位置变为空 else //此位置是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role_target; //将box从target中推走,则此位置变成role_target player.x = role_x; if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve { First_Round[role_x - 1][player.y] = achieve; achievementNum++; } else First_Round[role_x - 1][player.y] = box; } steps++; } }
矩阵旋转函数
player结构体也要随着矩阵的旋转而旋转
可以看到旋转矩阵操作要遍历多次数组
顺时针旋转m阶矩阵就是将a[i][j]放在(j,m-i-1)处,所以使用temp来进行临时存储。
这里也可以将matrix_rotate函数化为左移右移和下移函数
#左移函数:行列交换后进行上移操作再换回
#下移函数:按行倒序
#右移函数:行列交换后的下移操作
代码量比上一程序少且比这一程序的时间少,属于折中。
//矩阵顺时针旋转m次 //那么左移旋转1次,右移旋转3次,下移旋转2次 void matrix_rotate(int m) { int temp[Box_Num][Box_Num]; int temp_player_x, temp_player_y; for (int i = 0; i < m; i++)//旋转次数 { for (int j = 0; j < Box_Num; j++)//行 { for (int k = 0; k < Box_Num; k++)//列 { temp[k][Box_Num - j - 1] = First_Round[j][k]; } } for (int j = 0; j < Box_Num; j++) { for (int k = 0; k < Box_Num; k++) { First_Round[j][k] = temp[j][k]; } } temp_player_x = player.y; temp_player_y = Box_Num - player.x - 1; player.x = temp_player_x; player.y = temp_player_y; } }
游戏帧
相应的,Flash_Frame函数的代码量显著减少
//游戏帧,轮询键盘 void Flash_Frame(void) { char input; //_kbhit检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 if (_kbhit()) { input = _getch(); switch (input) { case('w')://上移 matrix_up(); break; case('s')://下移 matrix_rotate(2); matrix_up(); matrix_rotate(2); break; case('a')://左移 matrix_rotate(1); matrix_up(); matrix_rotate(3); break; case('d')://右移 matrix_rotate(3); matrix_up(); matrix_rotate(1); break; case('r')://重玩 Windows_Init(); break; default: break; } } }
菜单设置
菜单设置还是用到基础的操作
//菜单界面 //暂未实现作者信息功能 void Start_Up(void) { //背景色 setfillcolor(RGB(255, 255, 255)); fillrectangle(0, 0, Box_Num * Box_Size + 200, Box_Num * Box_Size); //菜单界面方块按钮样式 setfillcolor(RGB(0x6f,0xf6,0xeb)); setlinecolor(RGB(150, 150, 150)); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 120, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 70); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 10); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 50); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 + 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 110); settextstyle(20, 0, _T("宋体")); outtextxy(Box_Size * Box_Num + 5, Box_Num * Box_Size / 2 + 150, _T("确定:空格")); //菜单界面的展示 wchar_t level_str[3]; setbkmode(OPAQUE); settextcolor(RGB(0, 0, 0)); settextstyle(40, 0, _T("宋体")); _stprintf_s(level_str, _T("%d"), level+1); outtextxy(Box_Size * Box_Num/2 + 30, Box_Num * Box_Size / 2 - 115, _T("开始游戏")); outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 - 55, _T("关卡选择")); outtextxy(Box_Size * Box_Num - 40, Box_Num * Box_Size / 2 - 55, level_str); outtextxy(Box_Size * Box_Num / 2, Box_Num * Box_Size / 2 + 5, _T("查看作者信息")); outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 + 65, _T("结束游戏")); switch (Menu_Opt)//标识选择的位置 { case(0): break; case(1): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 115, _T("@")); break; case(2): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 55, _T("@")); break; case(3): outtextxy(Box_Size * Box_Num / 2 - 20, Box_Num * Box_Size / 2 + 5, _T("@")); break; case(4): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 + 65, _T("@")); break; default: break; } FlushBatchDraw(); }
void Menu_Flash_Frame(void) { char input; if (_kbhit()) { input = _getch(); switch (input) { case('w')://选择按钮上移 clear_opt(); Menu_Opt--; if (Menu_Opt <= 0) Menu_Opt = 4; break; case('s')://选择按钮下移 clear_opt(); Menu_Opt++; if (Menu_Opt > 4) Menu_Opt = 1; break; case(' ')://确定按钮 switch (Menu_Opt) { case(1):Begin = 1; Windows_Init(); break;//如果在'开始游戏'按钮处确定,则开始游戏 case(2)://关卡选择 level++;//关卡增加 if (level >= Round_Num)//关卡越界则回到第一关 level = 0; break; case(3):break;//作者信息界面 case(4):quit_flag = 1; break;//退出程序 default: break; } break; default: break; } Start_Up(); } }
//菜单界面选择的覆盖,覆盖之前的'@' void clear_opt(void) { switch (Menu_Opt) { case(0): break; case(1): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 115, _T(" ")); break; case(2): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 55, _T(" ")); break; case(3): outtextxy(Box_Size * Box_Num / 2 - 10, Box_Num * Box_Size / 2 + 5, _T(" ")); break; case(4): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 + 65, _T(" ")); break; default: break; } }
总代码
#include <stdio.h> #include <graphics.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include "data_def.h" #include "WindowsSet.h" //上移操作 void matrix_up(void) { int role_x, role_y; role_x = player.x - 1; if (First_Round[role_x][player.y] == empty) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role; player.x = role_x; steps++; } else if (First_Round[role_x][player.y] == target) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role_target; player.x = role_x; steps++; } else if ((First_Round[role_x][player.y] == box || First_Round[role_x][player.y] == achieve) && (First_Round[role_x - 1][player.y] == empty || First_Round[role_x - 1][player.y] == target))//判断有wall { if (First_Round[role_x][player.y] == box) { if (First_Round[player.x][player.y] == role)//如果此处是role First_Round[player.x][player.y] = empty; else//如果此处是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role; player.x = role_x; if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve { First_Round[role_x - 1][player.y] = achieve; achievementNum++; } else First_Round[role_x - 1][player.y] = box; } else if (First_Round[role_x][player.y] == achieve) { achievementNum--; if (First_Round[player.x][player.y] == role)//此位置是玩家位置 First_Round[player.x][player.y] = empty;//此位置变为空 else //此位置是role_target First_Round[player.x][player.y] = target; First_Round[role_x][player.y] = role_target; //将box从target中推走,则此位置变成role_target player.x = role_x; if (First_Round[role_x - 1][player.y] == target)//如果box和target重叠,合为achieve { First_Round[role_x - 1][player.y] = achieve; achievementNum++; } else First_Round[role_x - 1][player.y] = box; } steps++; } } //矩阵顺时针旋转m次 //那么左移旋转1次,右移旋转3次,下移旋转2次 void matrix_rotate(int m) { int temp[Box_Num][Box_Num]; int temp_player_x, temp_player_y; for (int i = 0; i < m; i++)//旋转次数 { for (int j = 0; j < Box_Num; j++)//行 { for (int k = 0; k < Box_Num; k++)//列 { temp[k][Box_Num - j - 1] = First_Round[j][k]; } } for (int j = 0; j < Box_Num; j++) { for (int k = 0; k < Box_Num; k++) { First_Round[j][k] = temp[j][k]; } } temp_player_x = player.y; temp_player_y = Box_Num - player.x - 1; player.x = temp_player_x; player.y = temp_player_y; } } //菜单界面选择的覆盖,覆盖之前的'@' void clear_opt(void) { switch (Menu_Opt) { case(0): break; case(1): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 115, _T(" ")); break; case(2): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 - 55, _T(" ")); break; case(3): outtextxy(Box_Size * Box_Num / 2 - 10, Box_Num * Box_Size / 2 + 5, _T(" ")); break; case(4): outtextxy(Box_Size * Box_Num / 2 + 20, Box_Num * Box_Size / 2 + 65, _T(" ")); break; default: break; } } //菜单界面帧 void Menu_Flash_Frame(void) { char input; if (_kbhit()) { input = _getch(); switch (input) { case('w')://选择按钮上移 clear_opt(); Menu_Opt--; if (Menu_Opt <= 0) Menu_Opt = 4; break; case('s')://选择按钮下移 clear_opt(); Menu_Opt++; if (Menu_Opt > 4) Menu_Opt = 1; break; case(' ')://确定按钮 switch (Menu_Opt) { case(1):Begin = 1; Windows_Init(); break;//如果在'开始游戏'按钮处确定,则开始游戏 case(2)://关卡选择 level++;//关卡增加 if (level >= Round_Num)//关卡越界则回到第一关 level = 0; break; case(3):break;//作者信息界面 case(4):quit_flag = 1; break;//退出程序 default: break; } break; default: break; } Start_Up(); } } //菜单界面 //暂未实现作者信息功能 void Start_Up(void) { //背景色 setfillcolor(RGB(255, 255, 255)); fillrectangle(0, 0, Box_Num * Box_Size + 200, Box_Num * Box_Size); //菜单界面方块按钮样式 setfillcolor(RGB(0x6f,0xf6,0xeb)); setlinecolor(RGB(150, 150, 150)); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 120, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 70); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 - 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 - 10); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 50); fillrectangle(Box_Num * Box_Size / 2 - 50, Box_Num * Box_Size / 2 + 60, Box_Num * Box_Size / 2 + 300, Box_Num * Box_Size / 2 + 110); settextstyle(20, 0, _T("宋体")); outtextxy(Box_Size * Box_Num + 5, Box_Num * Box_Size / 2 + 150, _T("确定:空格")); //菜单界面的展示 wchar_t level_str[3]; setbkmode(OPAQUE); settextcolor(RGB(0, 0, 0)); settextstyle(40, 0, _T("宋体")); _stprintf_s(level_str, _T("%d"), level+1); outtextxy(Box_Size * Box_Num/2 + 30, Box_Num * Box_Size / 2 - 115, _T("开始游戏")); outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 - 55, _T("关卡选择")); outtextxy(Box_Size * Box_Num - 40, Box_Num * Box_Size / 2 - 55, level_str); outtextxy(Box_Size * Box_Num / 2, Box_Num * Box_Size / 2 + 5, _T("查看作者信息")); outtextxy(Box_Size * Box_Num / 2 + 30, Box_Num * Box_Size / 2 + 65, _T("结束游戏")); switch (Menu_Opt)//标识选择的位置 { case(0): break; case(1): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 115, _T("@")); break; case(2): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 - 55, _T("@")); break; case(3): outtextxy(Box_Size * Box_Num / 2 - 20, Box_Num * Box_Size / 2 + 5, _T("@")); break; case(4): outtextxy(Box_Size * Box_Num / 2 + 10, Box_Num * Box_Size / 2 + 65, _T("@")); break; default: break; } FlushBatchDraw(); } //检查是否成功或失败 int check_lose_win(void) { int i, j; for (i = 1; i < Box_Num - 1; i++) { for (j = 1; j < Box_Num - 1; j++) { if (First_Round[i][j] == box && (First_Round[i + 1][j] == wall && First_Round[i][j + 1] == wall || First_Round[i - 1][j] == wall && First_Round[i][j - 1] == wall)) return 0;//lose else if (First_Round[i][j] == box && (First_Round[i + 1][j] == wall && First_Round[i][j - 1] == wall || First_Round[i - 1][j] == wall && First_Round[i][j + 1] == wall)) return 0; } } if (achievementNum == targetNum) return 1;//win return -1; } /* * 游戏界面初始化 * 用于重玩 */ void Windows_Init(void) { initgraph(Box_Num * Box_Size + 150, Box_Num * Box_Size); setbkcolor(RGB(255, 255, 255)); BeginBatchDraw(); Start_Up(); int i, j; targetNum = 0; //遍历第level关关卡给first_round for (i = 0; i < Box_Num; i++) { for (j = 0; j < Box_Num; j++) { First_Round[i][j] = origin_Round[level][i][j]; if (origin_Round[level][i][j] == role) { player.x = i; player.y = j; } else if (origin_Round[level][i][j] == target) targetNum++; } } achievementNum = 0; steps = 0; } //在游戏win之后可以进入下一关卡 void Next_Round(void) { while (1) { if (_kbhit()) { char n; n = _getch(); if (n == 'n') { level++; Windows_Init(); break; } } } } //游戏场景 void Windows_Show(void) { int i, j; cleardevice(); //遍历二维关卡数据 for (i = 0; i < Box_Num; i++) { for (j = 0; j < Box_Num; j++) { //空格子或数据背景色 if (First_Round[i][j] == empty || First_Round[i][j] == data_bg) { setfillcolor(RGB(255, 255, 255)); setlinecolor(RGB(255, 255, 255)); fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size); } else if (First_Round[i][j] == wall)//墙样式 { setfillcolor(RGB(0x93, 0x84, 0x5c)); setlinecolor(RGB(255, 255, 255)); fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size); } else if (First_Round[i][j] == role || First_Round[i][j] == role_target)//角色和角色与目标重合的样式 { setfillcolor(RGB(0xf5, 0xc3, 0x42)); setlinecolor(RGB(255, 255, 255)); fillcircle((j + 0.5) * Box_Size, (i + 0.5) * Box_Size, 0.5 * Box_Size); } else if (First_Round[i][j] == box)//盒子样式 { setfillcolor(RGB(0, 0, 255)); setlinecolor(RGB(255, 255, 255)); fillrectangle(j * Box_Size, i * Box_Size, (j + 1) * Box_Size, (i + 1) * Box_Size); } else if (First_Round[i][j] == target)//目标样式 { setfillcolor(RGB(0, 255, 150)); setlinecolor(RGB(255, 255, 255)); fillrectangle((j + 0.3) * Box_Size, (i + 0.3) * Box_Size, (j + 0.7) * Box_Size, (i + 0.7) * Box_Size); } else if (First_Round[i][j] == achieve)//成功的目标样式 { setfillcolor(RGB(15, 99, 60)); setlinecolor(RGB(255, 255, 255)); fillcircle((j + 0.5) * Box_Size, (i + 0.5) * Box_Size, 0.5 * Box_Size); } } } //OPAQUE不透明 //SetBkMode函数来设置DrawText函数的输出方式 wchar_t step_str[10], score_str[10]; setbkmode(OPAQUE); settextcolor(RGB(0, 0, 0)); settextstyle(30, 0, _T("宋体")); outtextxy(Box_Size * Box_Num + 5, 40, _T("操作:wsad")); outtextxy(Box_Size * Box_Num + 5, 80, _T("重玩:r")); outtextxy(Box_Size * Box_Num + 5, 160, _T("steps:")); _stprintf_s(step_str, _T("%d"), steps); outtextxy(Box_Size * Box_Num + 100, 160, step_str); outtextxy(Box_Size * Box_Num + 5, 200, _T("score:")); _stprintf_s(score_str, _T("%d"), achievementNum); outtextxy(Box_Size * Box_Num + 100, 200, score_str); if (check_lose_win() == 0) { //TRANSPARENT透明 setbkmode(TRANSPARENT); settextcolor(RGB(255, 0, 0)); settextstyle(80, 0, _T("宋体")); outtextxy(80, 200, _T("lose")); } else if (check_lose_win() == 1) { setbkmode(TRANSPARENT); settextcolor(RGB(0, 0, 0)); settextstyle(80, 0, _T("宋体")); outtextxy(120, 150, _T("win")); settextstyle(40, 0, _T("宋体")); outtextxy(80, 220, _T("press 'n'to next round")); } FlushBatchDraw(); } //游戏帧,轮询键盘 void Flash_Frame(void) { char input; //_kbhit检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 if (_kbhit()) { input = _getch(); switch (input) { case('w')://上移 matrix_up(); break; case('s')://下移 matrix_rotate(2); matrix_up(); matrix_rotate(2); break; case('a')://左移 matrix_rotate(1); matrix_up(); matrix_rotate(3); break; case('d')://右移 matrix_rotate(3); matrix_up(); matrix_rotate(1); break; case('r')://重玩 Windows_Init(); break; default: break; } } }
main函数
#include <stdio.h> #include <graphics.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include "WindowsSet.h" extern int Begin, quit_flag;//引入外部变量 int main() { Windows_Init(); while (1) { if (Begin)//开始游戏,游戏界面轮询 { Windows_Show(); if (check_lose_win() == 1) Next_Round(); Flash_Frame(); } else//菜单界面轮询 { Menu_Flash_Frame(); } if (quit_flag)//退出游戏 { break; } }; return 0; }
这里必须要用extern声明外部变量,否则无法引用
暂时还没有查询到为什么在#include "data_def.h"后还是显示未声明变量。
成果
将各个总代码整合便可得到最终成果