7355|2

4

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

C语言helloworld讲解及简单数字拼图源码----献给C语言初学者 [复制链接]

本帖最后由 blacker 于 2016-7-22 20:00 编辑

        曾几何时,我刚学C语言,其实在这之前,也就是高中时候,我还了解过VB。那时候的我,刚刚步入编程的世界,憧憬着自己将来会成为一名出色的IT工程师。
        可是,不论是教程书上还是老师在课上讲的,大部分就是“变量、常量、数组等等的定义及使用” “打印hello world” “九九乘法表” “数组排序”等等。于是我就想啊:“难道以后我精通了C语言以后,就天天用这些玩意就能写出一个像样的软件了?比如QQ、浏览器、杀毒软件、桌面便签等”。
        再后来,随着学习的不断深入,我终于对编程语言有了宏观的认识:概括起来讲,编程语言由参与运算的量(常量变量等)、参与运算的运算符(加减乘除等)、流程控制语句(如C语言的if、while、goto、for等)、函数调用规范四大块构成。前面三块是很基础的了,当然,第四块也是很基础的,但我为什么要把第四块单独列出来呢?因为它是通往编程世界的一扇窗户。没有了函数调用,你只能定义一些变量,然后做做运算、跳转一下、循环几次,其他的什么也干不了了。
        通过调用函数,你可以实现很多很多功能,比如,printf就可以往屏幕上输出一些东西。任何一种编程语言做出来的真正的项目,都是由各种各样的库里的各种各样的函数通过前面三块来堆起来的。拿一个C语言helloworld来举例说明一下:

#include

//上面这句就是一个包含头文件的说明,因为我们要输出helloworld需要调用printf函数,而这个函数在ANSI C标准库中的stdio.h中声明,因此我们要通过该语句来指明printf的出处

int main(void)

//上面这句是helloworld程序的入口点,当我们运行helloworld程序的时候,操作系统就调用这个main函数,以后你学的多了之后,你会知道其实他也是个函数,与程序中其他函数不同的一点是:这个函数由操作系统调用,参数由操作系统命令行传递给main函数,返回值也由操作系统接收。而程序中的函数参数由程序中的语句传递给被调用函数,被调用函数的返回值也由程序中的变量接收。

{

printf("Hello World!\n");

//上面这句完成了我们helloworld最关键的功能:在屏幕上打印输出helloworld字符串。从宏观上讲,这是一个函数,是个函数就有参数以及返回值,在这里,我们传递给printf函数的参数是"Hello World!\n",而我们并不关心这个函数的返回值,所以就没设置变量去接收返回值。

return 0;

//上面这句就是程序的返回值,也就是main函数的返回值,前面我们说了,这个值“0”最终是返回到操作系统中去了,操作系统怎么处理这个值你暂时可以不用关心。

}

看完了helloworld源码解释,你会明白:原来,我要实现XX功能,就要学会XX函数的使用方法。是的,学习一种编程语言,最难的不是学编程语言本身,而是学习能够实现你所需要的功能的函数!任何一种编程语言,无非就是各种量的定义及使用、各种运算符的使用、程序流向控制、函数的调用方法。还是那句话,函数是你通往代码世界的一扇窗。


----------------分割线,以上为helloworld和编程语言宏观讲解-------------------

      很久以前,我上班无聊玩win7桌面小游戏——数字拼图时,突然想到自己编写一个数字拼图游戏,于是……

//------------------------------分割线,以下是源码-------------------------------

//编译环境:VC++6.0,(若用Win TC,可能需要把注释去掉,否则有非法注释的提示)

#include "time.h"
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"


//存储按键码,也就是玩游戏时候按下的“上下左右”方向键的码
char key;
//x、y、i用于循环,x0y0指示当前空位"0",rnd存放随机数值,t标记排序是否成功
int x,y,x0,y0,rnd,i,t=0;

//数字存储矩阵
int matrix[4][4];


//以下为函数声明
void show(void);       //显示当前排序
void initmatrix(void); //初始化随机矩阵
int sett(void);            //判断当前排序是否成功
void up(void);           //向下移动空位(空位下方数字上移)
void down(void);      
void lft(void);
void rght(void);
void iptkey(void);     //接收按键(只接收方向键)

//主函数
int main(void)
{

//显示提示信息并暂停 按任意键后开始游戏
printf("Use arrow key to move the numbers,press anykey to start playing.\n");
getch();

//标号 游戏成功后如果按r重玩则跳转至此
start:

//清成功标志,否则一直为成功状态
t=0;

//取随机数初始化
srand((unsigned int)time(0));
initmatrix();

//如果游戏没结束,也就是不满足1-15按顺序排列,则循环等待按下方向键并操作矩阵数字交换
while(!t)
    {
    iptkey();
    t=sett();

//清屏
    system("CLS");
    show();
    }
printf("Congratulations,you win!\n");
printf("Press R to Restart,anykey to Quit,thank you for playing the Game!\n");
key=getch();
system("CLS");
if(key=='R' || key=='r')
    goto start;
else
    ;
getch();
return 0;
}


void initmatrix(void)
    {     
     x0=3;
     y0=3;
     i=0;
     for(y=0;y<4;y++)              //嵌套循环先按成功序列排序1234567891011121314150
         for(x=0;x<4;x++)
         {
             if(y==3 && x==3)
             matrix[y][x]=0;
             else
             matrix[y][x]=1+i++;
         }     
     for(i=0;i<1000;i++)        //一千次循环,每次循环都按随即方向移动
     {
     rnd=rand()%(4);           //取0-3随机数,分别代表上下左右四个方向
     switch(rnd)
        {
        case 0:
            {
            up();
            break;
            }
        case 1:
            {
            down();
            break;
            }
        case 2:
            {
            lft();
            break;
            }
        case 3:
            {
            rght();
            break;
            }
        }
     }
     show();
    }

int sett(void)
    {
    i=0;
    for(y=0;y<4;y++)
        for(x=0;x<4;x++)
            {
            if (matrix[y][x]!=1+i++)
                return (i==16)?1:0;
            }
    }

void iptkey(void)
    {
    key=getch();
    switch(key)
        {
        case 72:
            {
            up();
            break;
            }
        case 80:
            {
            down();
            break;
            }
        case 75:
            {
            lft();
            break;
            }
        case 77:
            {
            rght();
            break;
            }
        }
    }


void up(void)
    {
    if(y0!=3)                                          //移动时要考虑空位"0"是否已经在边界,上下左右各边界各有一个方向不能移动
        {
        matrix[y0][x0]=matrix[y0+1][x0];
        y0++;
        matrix[y0][x0]=0;
        }
    }
void down(void)
    {
    if(y0!=0)
        {
        matrix[y0][x0]=matrix[y0-1][x0];
        y0--;
        matrix[y0][x0]=0;
        }
    }
void lft(void)
    {
    if(x0!=3)
        {
        matrix[y0][x0]=matrix[y0][x0+1];
        x0++;
        matrix[y0][x0]=0;
        }
    }
void rght(void)
    {
    if(x0!=0)
        {
        matrix[y0][x0]=matrix[y0][x0-1];
        x0--;
        matrix[y0][x0]=0;
        }
    }

void show(void)
{
    for(y=0;y<4;y++)
        for(x=0;x<4;x++)
        {
            if(x==3)
                printf("%d\n",matrix[y][x]);       //“\n"保证每行只有四个数显示 满四个数就换行
            else
                printf("%d\t",matrix[y][x]);
        }
}


//-------------------------------分割线,以上是源码-------------------------

程序很简陋,注释也不多,好在都玩过这个游戏,一看代码结构就知道怎样实现的了。


ps:其实这是第二版,第一版的时候,没考虑到数字拼图无解的情况。第一版和第二版的区别在于游戏初始化的时候,各数字位置的随机确定上。第一版的实现方法大概为:从0-15中随机取值,每取出一个值就把它按顺序放到4*4矩阵中,然后从0-15中剔除这个值,防止再次取到它,这样直到16个值全部取完。由于这种方法是“真正”的随机,并没有遵循“保证数字拼图有解”的规则,因此,每次初始化有1/2的概率出现无解的情况。第一版出生后,我自己玩了几次,发现了无解的情况之后,改进了拼图初始化的随机方法:从正确答案(也就是1-15按顺序在矩阵中排列,最后为空位0)开始,随机移动空位0一定次数(我设定的是1000次,空位随机移动1000次,得到的初始化排列足够随机的了)。由于最终初始化结果是由正确答案逆向移动得出来的,那么这个初始化的排列一定是有解的。

pps:关于初始化,你有其他方法吗?欢迎讨论。
此帖出自编程基础论坛

最新回复

学习了。  详情 回复 发表于 2016-10-13 22:44
点赞 关注
 

回复
举报

165

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
每次初始化有1/2的概率出现无解的情况

可以大胆猜想,交换任意两块,从有解变无解,再任意交换两块,有变有解。
如果可以证明猜想,那么偶数次任意交换,显然比移动快。
如果可以证明猜想错误,...

此帖出自编程基础论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
学习了。
此帖出自编程基础论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表