最近花了1天半时间用c实现了现在较火的手机游戏《消灭星星》,亲测无误,在此贴出代码以飨网友,有bug在所难免,欢迎指正!(未经本人同意不得随意转载、复制,谢谢!)
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define false 0
typedef struct node{
int center;//本节点的值
int up;//相邻的上面节点的值
int down;//相邻的下面节点的值
int left;//相邻的左面节点的值
int right;//相邻的右面节点的值
int x;//x下标
int y;//y下标
int flag;//查找匹配标记,0为未查找或不匹配,1表示匹配
}Node;
typedef Node HD[10][10];//10X10随机矩阵,其中center值介于1到5之间
typedef Node HDStack[100];//查找栈
enum Mode{ //node节点的方位指引,用于node节点各分量值的输出
mModeCenter,
mModeUp,
mModeDown,
mModeLeft,
mModeRight,
};
static int myScore = 0;//玩家游戏得分
static int top = 100;//栈顶指针
//static int num = 0;
static int between = 2;
static int sensorship = 54;//关卡数
static int standardScore = 1000;
void pop(HDStack stack);//弹出栈顶元素
void push(HDStack stack,Node value);//将value压入栈顶
Node getTop(HDStack stack);//取栈顶元素
void init(HD hd);//初始化数组
void parseC2UDLR(HD hd);//根据数组hd的已知center值确定up,down,left和right的值
int findInHd(HD hd,HDStack stack,int xindex,int yindex);//在数组中找出和xindex行yindex列的值相同的紧邻的连续相同数字所在位置
void move2Replace(HD hd);//移动center分量为0的上面的数字取代0,若存在整列数字均为0,则该列数字向右各列均向左移一列
void reZero(HD hd);//数组清零
int hasSameNum(HD hd);//判断数组剩余非零数字中是否有连续相同的数字,用于单个关卡是否结束的判断
void print(HD hd,Mode mode);//根据mode打印数组相应的信息
int main(){
printf("**********************************\n");//游戏介绍
printf("++++++++++++++++++++++++++++++++++\n");
printf("+ 游戏须知 +\n");
printf("+ +\n");
printf("+ 在矩阵中确定一个点,与该点相邻 +\n");
printf("+ 或连续相邻且值相等的点将一并 +\n");
printf("+ 消除并置换为0 +\n");
printf("+ 请在'请输入起点'处输入你想输 +\n");
printf("+ 入的合法的矩阵行号和列号 +\n");
printf("+ (均从1开始到10结束) +\n");
printf("+ +\n");
printf("+ 技巧:与所输入的点相邻或连续 +\n");
printf("+ 相邻的点越多得分越高, +\n");
printf("+ 最后剩余的星星越少得 +\n");
printf("+ 越高 +\n");
printf("++++++++++++++++++++++++++++++++++\n\n");
printf(" oooooooooooo\n");
printf(" O|| Game Start ||O\n");
printf(" oooooooooooo\n");
printf("----------------------------------\n");
int cycle = 1;
int bscore[9] = {2,5,9,14,20,27,35,44,54};
for(cycle;cycle <= sensorship;cycle ++){//关卡循环
HD hd;
int x,y,mm,remainNum = 100;
int judge = true;
int find = 0;
init(hd);
parseC2UDLR(hd);
for(int i = 0;i < 9;i++){
if(cycle-1 == bscore[i])
find = 1;
}
if(cycle == 1)
standardScore += 0;
else{//确定每关目标分数
if(find == 1)
standardScore += 3000;
else
standardScore += 2000;
}
print(hd,mModeCenter);
while(judge == true){//单个关卡游戏主程
printf("oooooooooooooooooooooooooooooooooo\n");
printf("|关卡:%2d目标:%6d分数:%6d|\n",cycle,standardScore,myScore);
printf("oooooooooooooooooooooooooooooooooo\n\n");
HDStack stack;
int num = 0;
//print(hd,mModeCenter);
printf(" 请输入起点:");
scanf("%d%d",&x,&y);
while(x > 10 || x < 1 || y > 10 || y < 1 || hd[x-1][y-1].center == 0 || (hd[x-1][y-1].center != hd[x-1][y-1].up && hd[x-1][y-1].center != hd[x-1][y-1].left && hd[x-1][y-1].center != hd[x-1][y-1].right && hd[x-1][y-1].center != hd[x-1][y-1].down)){
printf(" 请重新输入:");
scanf("%d%d",&x,&y); //输入合法性检查
}
num = findInHd(hd,stack,x,y);
if(num == 1)
num = 0;
else
myScore += 5*num*num;//统计得分
remainNum -= num;
///print(hd,mModeCenter);
move2Replace(hd);
parseC2UDLR(hd); //重置
if(num >= 8)
printf("\n 好!\n\n");
if(num >= 15)
printf("\n 酷!\n\n");
if(num >= 18)
printf("\n 你真是吊爆了\n 土豪\n 我们做朋友吧!\n\n");
printf(" AAAAAAAAAAAAAAAAA\n");
printf(" # %d连消+%d分 #\n",num,5*num*num);
printf(" VVVVVVVVVVVVVVVVV\n\n");
print(hd,mModeCenter);
judge = hasSameNum(hd);// 关卡是否结束
if(judge == false){//统计奖励
if(remainNum <= 20){
printf("\n");
printf(" HHHHHHHHHHHHHHHHH\n");
printf(" T 奖励%d分 T\n",remainNum*remainNum*5);
myScore += remainNum*remainNum*5;
printf(" |剩余%d颗星星|\n",remainNum);
printf(" CCCCCCCCCCCCCCCCC\n\n");
}else{
printf("\n");
printf(" HHHHHHHHHHHHHHHHH\n");
printf(" T 奖励%d分 T\n",0);
printf(" |剩余%d颗星星|\n",remainNum);
printf(" CCCCCCCCCCCCCCCCC\n\n");
}
}
if(myScore >= standardScore){//通过关卡
printf(" vvvvvvvvvvv\n");
printf(" }恭喜通关!{\n");
printf(" vvvvvvvvvvv\n");
}
}
reZero(hd);//清零
if(myScore < standardScore)
printf(" 通关失败!\n");
else
printf(" 顺利通关!\n");
printf(" 请选择:\n");
printf("**输入1表示继续下一关**\n**输入2表示退出游戏**\n**输入3表示重新开始游戏**\n_>\n");
scanf("%d",&mm);
switch(mm){//游戏进程选择
case 1:continue;break;
case 2:exit(0);
case 3:cycle--;break;
}
}
printf("----------------------------------\n");
return 0;
}
void init(HD hd){
//初始化数组
int i,j,value;
for(i = 0;i < 10;i++){
for(j = 0;j < 10;j++){
//value = 1+(int)(5.0*rand()/(RAND_MAX+1.0));
value = (int)(rand()%5)+1;
hd[i][j].center = value;
hd[i][j].up = 0;
hd[i][j].down = 0;
hd[i][j].left = 0;
hd[i][j].right = 0;
hd[i][j].x = i;
hd[i][j].y = j;
hd[i][j].flag = 0;
}
}
}
void print(HD hd,Mode mode){
//根据打印数组相应mode的信息
int i,j;
printf(" 1 2 3 4 5 6 7 8 9 0\n");
printf(" \\ - - - - - - - - - - \\\n\n");
for(i = 0;i < 10;i++){
if(i == 9)
printf("%d| ",0);
else
printf("%d| ",i+1);
for(j = 0;j < 10;j++){
switch(mode){
case mModeCenter:printf("%d ",hd[i][j].center);break;
case mModeUp:printf("%d ",hd[i][j].up);break;
case mModeDown:printf("%d ",hd[i][j].down);break;
case mModeLeft:printf("%d ",hd[i][j].left);break;
case mModeRight:printf("%d ",hd[i][j].right);break;
}
}
if(i == 9)
printf(" |0\n");
else
printf(" |%d\n",i+1);
}
printf("\n \\ - - - - - - - - - - \\\n");
printf(" 1 2 3 4 5 6 7 8 9 0\n");
}
void parseC2UDLR(HD hd){
//根据数组hd的已知center值确定up,down,left和right的值
int i,j;
for(i = 0;i < 10;i++){
for(j = 0;j < 10;j++){
hd[i][j].flag = 0;
if(i == 0){//上边界
if(j == 0){//左上角
hd[i][j].up = 0;
hd[i][j].left = 0;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = hd[i+1][j].center;
}else if(j == 9){//右上角
hd[i][j].up = 0;
hd[i][j].right = 0;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].down = hd[i+1][j].center;
}else{//去除顶点剩余上边界
hd[i][j].up = 0;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = hd[i+1][j].center;
}
}else if(i == 9){ //下边界
if(j == 0){//左下角
hd[i][j].up = hd[i-1][j].center;
hd[i][j].left = 0;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = 0;
}else if(j == 9){//右下角
hd[i][j].up = hd[i-1][j].center;
hd[i][j].right = 0;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].down = 0;
}else{//去除顶点剩余下边界
hd[i][j].up = hd[i-1][j].center;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = 0;
}
}else{
if(j == 0){//去除顶点剩余左边界
hd[i][j].up = hd[i-1][j].center;
hd[i][j].left = 0;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = hd[i+1][j].center;
}else if(j == 9){//去除顶点剩余右边界
hd[i][j].up = hd[i-1][j].center;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].right = 0;
hd[i][j].down = hd[i+1][j].center;
}else{//去除边界剩余节点
hd[i][j].up = hd[i-1][j].center;
hd[i][j].left = hd[i][j-1].center;
hd[i][j].right = hd[i][j+1].center;
hd[i][j].down = hd[i+1][j].center;
}
}
}
}
}
void pop(HDStack stack){
//弹出栈顶元素
if(top < 100)
stack[top++].center = 0;
else{
printf("The index beyond out of the boundary!");
exit(0);
}
}
void push(HDStack stack,Node value){
//将value压入栈顶 ;
if(top > 1){
stack[--top] = value;
}
else{
printf("The index below out of the boundary!");
exit(0);
}
}
Node getTop(HDStack stack){
//取栈顶元素
if(top > -1 && top < 101)
return stack[top];
else{
printf("The stack out of the boundary!");
exit(0);
}
}
int findInHd(HD hd,HDStack stack,int xindex,int yindex){
//在数组中找出和xindex行yindex列的值相同的紧邻的连续相同数字所在位置
hd[xindex-1][yindex-1].flag = 1;
int value = hd[xindex-1][yindex-1].center,snum = 0;
push(stack,hd[xindex-1][yindex-1]);
snum++;
Node node = hd[xindex-1][yindex-1];
if(node.up != value && node.down != value && node.left != value && node.right != value){
//hd[getTop(stack).x][getTop(stack).y].center = 0;
pop(stack);
return 1 ;
}else{
while(top < 100){
if(getTop(stack).up == value && hd[getTop(stack).x-1][getTop(stack).y].flag == 0){//向上查找
hd[getTop(stack).x-1][getTop(stack).y].flag = 1;
push(stack,hd[getTop(stack).x-1][getTop(stack).y]);
snum++;
}else if(getTop(stack).left == value && hd[getTop(stack).x][getTop(stack).y-1].flag == 0){//向左查找
hd[getTop(stack).x][getTop(stack).y-1].flag = 1;
push(stack,hd[getTop(stack).x][getTop(stack).y-1]);
snum++;
}else if(getTop(stack).right == value && hd[getTop(stack).x][getTop(stack).y+1].flag == 0){//向右查找
hd[getTop(stack).x][getTop(stack).y+1].flag = 1;
push(stack,hd[getTop(stack).x][getTop(stack).y+1]);
snum++;
}else if(getTop(stack).down == value && hd[getTop(stack).x+1][getTop(stack).y].flag == 0){//向下查找
hd[getTop(stack).x+1][getTop(stack).y].flag = 1;
push(stack,hd[getTop(stack).x+1][getTop(stack).y]);
snum++;
}else{//返回弹出
hd[getTop(stack).x][getTop(stack).y].center = 0;
pop(stack);
}
}
}
return snum;
}
void move2Replace(HD hd){
//移动center分量为0的上面的数字取代0,若存在整列数字均为0,则该列数字向右各列均向左移一列
int i,j,rows = 10;
for(j = 0;j < rows;j++){
int real = 0;
int emptyNum = 0;
int value[10] = {0,0,0,0,0,0,0,0,0,0};
for(i = 9;i >= 0;i--){//非零值归栈
if(hd[i][j].center != 0){
value[real++] = hd[i][j].center;
}else{
emptyNum++;
}
}
for(i = 0;i < 10;i++){//列重置
hd[i][j].center = value[9-i];
}
if(emptyNum == 10){//全零列消除
if(j < 9){
int l = j;
for(l;l < 9;l++){
for(i = 0;i < 10;i++){
hd[i][l].center = hd[i][l+1].center;
}
}
j--;//回扫
rows--;//优化处理
}
int l;
for(l = 0;l < 10;l++){//末列置零
hd[l][9].center = 0;
}
}
}
return ;
}
int hasSameNum(HD hd){
//判断数组剩余非零数字中是否有连续相同的数字,用于单个关卡是否结束的判断
int rows = 10,i,j;
do{
for(i = 9;i >= 0;i--){
for(j = 0;j < rows;j++){
if(i == 9)
if(hd[i][j].center == 0 && hd[i][j].left != 0)//第j+1列往右为空,缩短列访距,优化搜索
rows = j+1;
if(hd[i][j].center != 0 && (hd[i][j].center == hd[i][j].left || hd[i][j].center == hd[i][j].right || hd[i][j].center == hd[i][j].up || hd[i][j].center == hd[i][j].down)){
//出现连续的相邻相同数字
return true;
}
}
}
}while(0);
return false;
}
void reZero(HD hd){
//数组清零
for(int i = 0;i < 10;i++){
for(int j = 0;j < 10;j++){
hd[i][j].center = 0;
}
}
parseC2UDLR(hd);
<p>}
</p>