前两天只是简单复习了下C语言的基础知识,到第三天就采用项目驱动的方式,带着我们一个班的学生做项目----Popstar游戏

其实还是很倾向于项目驱动的方式来学习的,老师在上边一边讲一边敲代码,我们就只要听,和抄下投影仪上的代码。带着我们走过一遍流程以后,再让我们自己写一个小游戏,老师只提供技术难点帮助。

    话不多说,给各位君看看记录的东西。

    首先做了一个控制台下的Popstar,用于测试算法的正确性,由于Popstar涉及到选择附近四个方向的同颜色的星星,因此要用到扩展查找算法。因为是学习,老师展示了递归、非递归方式来实现查找的过程。

    开始定义了一系列的数据对象

    就是想一下需要用到哪些数据对象,头文件要用头文件卫士#ifndef……这是编程规范

 

data.h

 1 #ifndef _DATA_H_//以文件名命名
 2 #define _DATA_H_
 3 
 4 //pragma once
 5 
 6 #include <windows.h>
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <stdlib.h>
10 
11 #define ROW 10
12 #define COLUMN 10
13 
14 typedef struct pos
15 {
16     int _x;
17     int _y;
18 }POS;
19 
20 typedef enum color
21 {
22     RED = 0,
23     BLUE = 1,
24     GREEN = 2,
25     YELLOW = 3,
26     PURPLE = 4
27 }eCOLOR;
28 
29 typedef struct star
30 {
31     eCOLOR _color;//颜色
32     POS _pos;    //位置
33     BOOL _isSelect;
34 }sSTAR;
35 
36 typedef enum directory
37 {
38     UP,
39     DOWN,
40     LEFT,
41     RIGHT
42 }eDIRECT;
43 
44 #endif;

接着写了fun.cpp

定义了一个sSTAR类型的数据对象 g_arrStars[row][column]

并且对数据对象进行了初始化:

void InitDataObj(void)
{
    int row = 0;
    int column = 0;
    srand((unsigned)time(0));

    for(row = 0; row < ROW; row++)
    {
        for(column = 0; column < COLUMN; column++)
        {
            g_arrStars[row][column]._color = (eCOLOR)(rand()%5);
            g_arrStars[row][column]._isSelect = FALSE;
            g_arrStars[row][column]._pos._x = row;
            g_arrStars[row][column]._pos._y = column;
        }
    }
}

判断是否越界:

 1 BOOL IsOutOfBorder(eDIRECT direct,int x,int y)
 2 {
 3     switch(direct)
 4     {
 5     case UP:
 6         case DOWN:
 7         {
 8             if(x<0 || x>ROW-1)
 9             {
10                 return TRUE;
11             }
12             else return FALSE;
13             break;
14         }
15     
16     case LEFT:
17     case RIGHT:
18         {
19             if(y<0 || y>COLUMN-1)
20             {
21                 return TRUE;
22             }
23             else
24             {
25                 return FALSE;
26             }
27             break;
28         }
29     default:
30         {
31             return FALSE;
32             break;
33         }
34     }
35 }

接着用了递归方式实现了选择星星的过程

 1 void SelectStar(const int x,const int y,int* pCount)
 2 {
 3     g_arrStars[x][y]._isSelect = TRUE;
 4     (*pCount)++;
 5 
 6     //如果 没越界 四个方向某个颜色相等  并且没有被选择
 7     //每次递归调用自己 上下左右依次判断
 8     if(!IsOutOfBorder(UP,x-1,y) && 
 9         g_arrStars[x-1][y]._color == g_arrStars[x][y]._color &&
10         g_arrStars[x-1][y]._isSelect == FALSE
11         )
12     {
13         SelectStar(x-1,y,pCount);
14     }
15 
16     if(!IsOutOfBorder(DOWN,x+1,y) && 
17         g_arrStars[x+1][y]._color == g_arrStars[x][y]._color &&
18         g_arrStars[x+1][y]._isSelect == FALSE
19         )
20     {
21         SelectStar(x+1,y,pCount);
22     }
23 
24     if(!IsOutOfBorder(LEFT,x,y-1) && 
25         g_arrStars[x][y-1]._color == g_arrStars[x][y]._color &&
26         g_arrStars[x][y-1]._isSelect == FALSE
27         )
28     {
29         SelectStar(x,y-1,pCount);
30     }
31 
32     if(!IsOutOfBorder(RIGHT,x,y+1) && 
33         g_arrStars[x][y+1]._color == g_arrStars[x][y]._color &&
34         g_arrStars[x][y+1]._isSelect == FALSE
35         )
36     {
37         SelectStar(x,y+1,pCount);
38     }
39 }

这样在main函数中写上这样一段:

 1 int x = 0, y =0, count = 0;
 2     ////初始化数据对象
 3     InitDataObject();
 4     ////显示星星
 5     Display();
 6     ////选取星星
 7     printf("Please Input x And y :");
 8     scanf_s("%d%d", &x, &y);
 9     //SelectStart(x, y, &count);
10     
11     SelectStarMethod1(x,y,&count);
12     printf("%d\n", count);
13     Display();

就可以进行星星的选择了。。。。。。。

 

再接着就忙着用非递归的方式实现扩展查找

非递归方式需要用到栈与队列,因此写了两个版本的栈与队列,一个是C语言版,一个是C++版的模版

这里我就忽略实现过程,直接上查找过程的函数了。

 1 int SelectStarMethod2(int x,int y)
 2 {
 3     SEQUEN_QUEUE queue;
 4     SEQUEN_STACK stack;
 5     InitSequenStack(&stack);
 6     InitSequenQueue(&queue);
 7     sSTAR *p = NULL;
 8 
 9     EnQueue(&queue,&g_arr[x][y]);
10     int currx = 0,curry = 0;
11     while(!IsEmptyQueue(&queue))
12     {
13         DelQueue(&queue,&p);
14         Push(&stack,p);
15         p->_isSelect = true;
16 
17         currx = p->_pos._x;
18         curry = p->_pos._y;
19         if(!IsOutOfBorder(UP,currx-1,curry) &&
20             g_arr[currx-1][curry]._color == g_arr[currx][curry]._color &&
21             g_arr[currx-1][curry]._isSelect == false)
22         {
23             EnQueue(&queue,&g_arr[currx-1][curry]);
24         }
25 
26         if(!IsOutOfBorder(DOWN,currx+1,curry) &&
27             g_arr[currx+1][curry]._color == g_arr[currx][curry]._color &&
28             g_arr[currx+1][curry]._isSelect == false)
29         {
30             EnQueue(&queue,&g_arr[currx+1][curry]);
31         }
32 
33         if(!IsOutOfBorder(LEFT,currx,curry-1) &&
34             g_arr[currx][curry-1]._color == g_arr[currx][curry]._color &&
35             g_arr[currx][curry-1]._isSelect == false)
36         {
37             EnQueue(&queue,&g_arr[currx][curry-1]);
38         }
39 
40         if(!IsOutOfBorder(UP,currx,curry + 1) &&
41             g_arr[currx][curry + 1]._color == g_arr[currx][curry]._color &&
42             g_arr[currx][curry + 1]._isSelect == false)
43         {
44             EnQueue(&queue,&g_arr[currx][curry + 1]);
45         }
46     }
47     return GetSequenLength(&stack);
48 }

非递归方式实现扩展查找,其实这里是有一点小问题的,就是当我星星同色的形成一个正方形的时候,选择就会出错。会多几个数字。解决办法就是在 if 判断之后加上

g_arr[currx-1][curry]._isSelect == true

这个扩展查找的非递归方式还是由你们自己去理解吧,在纸上模拟一下进队出队的过程你就明白了

 

还有就是用C++模版写的版本

 1 int SelectStarMethod3(int x,int y)
 2 {
 3     CSequenStack<sSTAR,MAX_SIZE> stack;
 4     SequenQueue<sSTAR,MAX_SIZE> queue;
 5     sSTAR obj;
 6     int currx = 0,curry = 0;
 7     queue.EnQueue(g_arr[x][y]);
 8     
 9     while(!queue.IsEmpty())
10     {
11         queue.DelQueue(obj);
12         currx = obj._pos._x;
13         curry = obj._pos._y;
14         stack.Push(g_arr[currx][curry]);//
15         g_arr[currx][curry]._isSelect = true;//次两处不可以用obj,因为其为值,不为地址引用
16         
17         if(!IsOutOfBorder(UP,currx-1,curry) &&
18             g_arr[currx-1][curry]._color == g_arr[currx][curry]._color &&
19             g_arr[currx-1][curry]._isSelect == false)
20         {
21             queue.EnQueue(g_arr[currx-1][curry]);
22         }
23 
24         if(!IsOutOfBorder(DOWN,currx+1,curry) &&
25             g_arr[currx+1][curry]._color == g_arr[currx][curry]._color &&
26             g_arr[currx+1][curry]._isSelect == false)
27         {
28             queue.EnQueue(g_arr[currx+1][curry]);
29         }
30 
31         if(!IsOutOfBorder(LEFT,currx,curry-1) &&
32             g_arr[currx][curry-1]._color == g_arr[currx][curry]._color &&
33             g_arr[currx][curry-1]._isSelect == false)
34         {
35             queue.EnQueue(g_arr[currx][curry-1]);
36         }
37 
38         if(!IsOutOfBorder(RIGHT,currx,curry + 1) &&
39             g_arr[currx][curry + 1]._color == g_arr[currx][curry]._color &&
40             g_arr[currx][curry + 1]._isSelect == false)
41         {
42             queue.EnQueue(g_arr[currx][curry+1]);
43         }
44     }
45     return stack.GetLength();
46 }

 

 

最后:

    我个人觉得编写软件就像盖一座房子,我们看别人写好的代码,为什么这么难?这时因为别人的代码已经是完成了的一个项目,经过不断重构之后,就像建好的一座

房子,我们外来的人在房子里边跑啊跑啊,想知道这房子到底是怎么盖的啊,从楼上跑到楼下一无所获。看不懂就是这样的一个过程。所以,如果没有人带着你写东西,那么你需要花费更多的精力来将整个房子一点点拆开,理解为什么这样做,这样的一个过程是一个很长的过程。因此看别人构建好的代码不能着急,原著都写了三五天,你想一天就看懂,那怎么能符合逻辑呢?

    对一些新的冷的知识更是如此,如果你一点都看不懂学不会,那么不如去找一下视频,跟着别人学一遍,走一边构建整个房子的流程,那么再写东西,看代码就如鱼得水了。

 

代码下载:点击