VC++学习笔记01-糖葫芦(数组)及其游戏编程实践

Posted on 2011-11-22 02:06  dodolook  阅读(2764)  评论(22编辑  收藏

  大家好!我们又见面啦!本来是打算一年后再写学习笔记的,结果发现,没写了之后学习效率有所降低,所以毅然决定再累也要继续多写写学习笔记呢!

  糖葫芦!有点酸酸甜甜的美食,但是听说不是很干净,很久都不敢吃了!

  我们知道,最初的程序员没有变量可以使用,直接和内存地址打交道,那些怪怪的地址量让人看到很心烦啊,到后来所以就有了对地址进行抽象了,所以就出现了变量。有了变量后,程序员就不再直接和地址打交道了,这样方便了很多哦!程序员的工作效率也随之提高了很多。但是很多时候,需要操作大量相同类型的数据的时候,单个变量也感觉很繁琐,比如要表示100颗糖果,就需要申请100个糖果类型的变量。有什么办法解决这一难题呢。所以就有了对相同类型的变量进行了抽象,叫数组,一般来说,这些相同类型的变量会连续的存放。

先来看一个例子:

int main(int argc, char* argv[])
{
int a, b, c, d, e, f, g;

a = 1;
b = 1;
c = a + b;
d = b + c;
e = c + d;
f = d + e;
g = e + f;

printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n",a,b,c,d,e,f,g);

return 0;
}

在这个数列中,定义了那么多个变量是不是感觉好烦的。如何要输出100000个数构成的数列那颗呢的非累死不可!所以数组的出现拯救了程序员!(因为数组是连续存储的相同类型的变量,所以数组只要记录首地址,需要访问到哪个元素了,会直接用公式计算出相应的地址值,所以数组元素的访问效率是非常高的!但是如何要删除数组中的某个中间的元素,数组为了保持数组本身的性质,需要挪动后面相应的元素,这一来计算机就要反复的读写,如果数组太大,效率必然会比较低,所以数组这种物理上的连续性也带来了其鲜明的特质。)

修正下上面的程序:

int main(int argc, char* argv[])
{
int a[7];
a[0] = 1;
a[1] = 1;

printf("%d\n%d\n", a[0], a[1]);

for (int i=2; i<7; i++)
{
a[i] = a[i-1] + a[i-2];

printf("%d\n", a[i]);
}
return 0;
}

可以发现啊,在数组的操作中经常和循环一起用,因为用循环可以很方便的进行数组的遍历哦!不过,注意数组的操作千万不要超过范围,因为超过了范围极有可能访问到垃圾值。当然不包括精心构造的越界访问!

  数组的定义其实很简单啦!就是:数据类型 数组名[数组长度],那么二维数组呢,也就是后面多加一个放括弧:数据类型 数组名[数组二维长度][数组一维长度];当然三维的话一次类推。一般数组应用不会超过3维的,因为数组太多,我觉得程序员自己都会搞糊涂了。

  对于一维数组的应用其实比较简单了,上面的例子就是一个典型的应用,当然在以后知识越来越丰富的情况下还有会更多的应用,比如利用一位数组在堆栈区运行程序代码,进行缓冲区溢出攻击等等。

  二维数组呢!仔细想想,虽然数组在内存中是连续存储的,包括二维数组,但是我们可以把连续存储的二维数组进行抽象,抽象成一个面,就像矩形一样,一个面的话,我们就可以对这个面进行一些操作,比如显示一些自己想显示的块,还可以利用显示的块可以模拟移动,喜欢玩游戏的朋友肯定一刻想到了,利用这些好玩的抽象与思考可以写出一些游戏了,比如俄罗斯方块,生命游戏等等。的确是这样,而且很多2D游戏就是这么做的。

  生命游戏!为了进一步加深对于数组的操作,很有必要进行一些编程实践,程序就是要多写才顺啦!那么就拿生命游戏开刀吧!生命游戏的规程很简单的:一个50×50的培养盘,原来里面充满着细胞(注:全部都有细胞)细胞每次都会根据周围的细胞数量而出生或者死亡,如果周围有三个细胞,
则本细胞生,周围有二个细胞则状态不变,其他情况细胞死亡。

  下面就开始写这个游戏啦!先规定一下,我们把细胞的变化次数规定在28次。好!开始行动!

int main()
{
int a[50][50], b[50][50], i, j, k, sum;//定义两个一样的数组,3个整型变量,k表示细胞变化

for (i=0; i<50; i++) //的次数,i,j定义了对数组的处理操作
{
for (j=0; j<50; j++)
{
a[i][j] = 1; //初始化操作,把细胞全部定义为1,表示细胞全部活
}
}

for (k=0; k<28; k++)
{
for (i=1; i<50; i++)
{
for (j=1; j<50; j++)
{
sum=a[i-1][j-1]+a[i-1][j]+a[i-1][j+1]+ //对数组进行抽象,用人容易理解的
a[i][j-1] +a[i][j+1]+ //方式对数组进行矩形的抽象,这样
a[i+1][j-1]+a[i+1][j]+a[i+1][j+1]; //就感觉有了上下左右之分了。
if (3==sum) //做出判断,改变细胞的状态
{
b[i][j] = 1;
}
else if (2==sum)
{
b[i][j] = a[i][j];
}
else
{
b[i][j] = 0;
}
}
}
for (i=1; i<49; i++)
{
for (j=1; j<49; j++)
{
a[i][j] = b[i][j];
}
}
}

for (i=0; i<50; i++)         //输出
{
for (j=0; j<50; j++)
{
if (1==a[i][j])
{
printf("*");
}
else
{
printf("");
}
}

printf("\r\n");
}

return 0;
}
**************************************************
* * * ******* * ****** * ******* * * *
* *
* ** ** *
* * ** ** * *
** * * **
* ** ** ** ** *
** * ** * **
* * **** * *
** ****** **
** **
** **
** * ** ** * **
** * * * * **
** * * * * **
** **
* *** *** *
** **
* * * * * * * * * *
* * * * * *
* ** * * ** *
* ****** ** * * ** ****** *
** * * * * * * * * * * **
** ** ** **
** *** *** **
** *** *** **
** ** ** **
** * * * * * * * * * * **
* ****** ** * * ** ****** *
* ** * * ** *
* * * * * *
* * * * * * * * * *
** **
* *** *** *
** **
** * * * * **
** * * * * **
** * ** ** * **
** **
** **
** ****** **
* * **** * *
** * ** * **
* ** ** ** ** *
** * * **
* * ** ** * *
* ** ** *
* *
* * * ******* * ****** * ******* * * *
**************************************************

上面就是28次后的图像,很漂亮吧!有时候可能一口气写不出来,但是不要急,要从想象转化为代码需要一个过程,多练习就好啦!先在纸上画画,再慢慢的转化为相应的程序代码!多练习,保证一下子就会啦!

  质数筛子!质数是很美丽的!我是听看一部电影里的对白学的,嘿嘿!既然学习了数组,那么就可以用数组来实现这个筛子,把不是质数的数一个筛走啦!我们就做10000以内的数了。首先什么是质数,质数是:只有自己本身与1两个约数的数。首先我们从数组下标2开始,然后将相应的质数的倍数挖掉就好啦!那么10000个数据就只需要进行100次变换就好啦,因为101的倍数已经超过10000了。

int main()
{
bool ss[10000];
int i, j;

for (i=0; i<10000; i++)
{
ss[10000] = true;
}

ss[0] = false;
ss[1] = false;

for (i=2; i<100; i++)
{
if (ss[i])
{
for (j=i*i; j<10000; j+=i)
{
ss[j] = false;
}
}
}

for (i=0; i<10000; i++)
{
if (ss[i])
{
printf("%d\t", i);
}
}

printf("\n");

return 0;
}

  特殊的数组——字符串

  字符串是一种特殊的数组,它特殊在哪里呢,这样,我们来写1个程序,在数组中放入字符组成的串看看呢!

int main()
{
char ch[20];
ch[0] = 'h';
ch[1] = 'e';
ch[2] = 'l';
ch[3] = 'l';
ch[4] = 'o';

printf("%s\r\n", ch);

return 0;
}

输出:hello烫烫烫烫烫烫烫虉
  这是怎么回事呀!哦!仔细一想原来是这样,在调试版下编译器会为申请的数组全部初始化为CC,这个CC就是这个烫,然后字符串有个规则,字符串以\0结束,所以用%s输出的时候,计算机一直在找\0,所以在找到\0之前会有这么几个烫字,因为我们申请的是20个字符空间,如何巧好是申请的是5个字符空间,输出结果可能会正确哦!所以,以后程序出现了烫的输出,多半是问题出在了栈区。如果我们在上面的程序加上一个\0是不是就是正确了!当然啦!肯定正确,因为C语言字符串就是这么规定的。

  字符串加密解密

  以前学过位运算哦!还记得吗!现在来做个小游戏来巩固下字符串以及为运算哦!

#include <string.h>
int main()
{
char ch[20];
char jm[20]="hahahaha";
unsigned int i;

strcpy(ch,"dodolook!");

printf("没有加密之前字符串为:%s\n",ch);

for(i=0;i<strlen(ch);i++)
{
ch[i]^=jm[i];
}

printf("加密后,字符串变为 :%s\n",ch);

for(i=0;i<strlen(ch);i++)
{
ch[i]^=jm[i];
}

printf("解密后,字符串还原为:%s\n",ch);

return 0;
}

这个程序可是很奇怪的哦!计算机还会响一声的哦!到底是什么原因的啊!
这种加密方式叫逐位加密,当然这种加密方式是很简单的,很容易被破解哦!到底如何破解啊!仔细想想,计算机可是大黄牛啊!不怕累的!那么下面这个密文,如何解密呢?!解密出来是什么呢!试试看啊!下次写笔记我发布解密代码啊!


螒貤腿)找殧攽!

记住啊,计算机是不怕累的牛!

永远的乌托邦——脑浊乐队live