本帖最后由 flashbang 于 2013-2-9 12:40 编辑
#15t大家好, 这里是新米程序猿小轮回.
#23t说是新人其实我马上都要毕业了, 刚去三星实习2个月觉得工作太无聊撤退回家赋闲。
不扯了,上见面礼。
如题,是一个炸弹人累死的小游戏。初版大约用了3天,第一个可运行jar是一周左右,然后就天天在机房跟同学一起玩儿233。
本来是有局域网对战的,起初设定是支持4人对战,然后就,坑了。然后就懒得再做了。然后就没了
图1:主界面,有3个地图来着?忘了懒得去看,联网模块已经关掉了,因为性能太差。以后再说~
图2:改键,其实也没啥可改的,P1和P2的上下左右还有放雷。
图3:玩儿的部分...好吧, 我美术老师死得早,画面粗糙见谅。(或者说根本就是猎奇!?)
本体附件(我也不确定能不能传上来, jre无)
度:【http://pan.baidu.com/share/link?shareid=314010&uk=671539592】
就是这么个小游戏啦,炸弹人也没什么可介绍的。新人拜区,欢迎各位大大指教。以上。
[查看全文]
本帖最后由 Whisper1166 于 2012-12-21 12:59 编辑
[mw_shl_code=cpp,true]
#include "stdio.h"
#include "windows.h"
#include "conio.h"
#include "stdlib.h"
#include "time.h"
#include "string.h"
//因为我也是新手,真的,才学C语言一学期不到..所以没有高手写的那么难懂...目前在写printf写得跟狗一样...
//想必在大神面前这些结构体就像蓝天白云一样清晰明了
struct Snake //谁知道这些都是什么意思? (知道的去死!!!)
{ //蛇的结构体,xy是蛇身体的某一部分的坐标,*next是链表里的指针..
int x;
int y;
char body;
struct Snake *next;
}*front,*rear,*p,*q;
struct food//这是禁果(喂)的坐标
{
int x;
int y;
}a;
int main()
{
int i,j,score=0,time=10000,flag;//i j是对二维数组赋值和输出用的,time是画面停滞时间,flag是判断是否需要生成禁果(你够了)
char c,dir,Amatrix[30][80],name[15],love[]={"XXX"};//c是获取键盘输入,dir表示蛇移动方向,name只是game over以后记录名字用的 XXX我屏蔽掉了
loop:front=(struct Snake*)malloc(sizeof(struct Snake));//就是动态分配内存,通过指针front和rear指向蛇头和蛇尾
rear=(struct Snake*)malloc(sizeof(struct Snake));
front->body='H';//蛇头是H,蛇尾是X ←这是老师要求的
rear->body='X';
front->x=1,front->y=2;//设定初始蛇头蛇尾的坐标
rear->x=1,rear->y=1;
front->next=rear;
rear->next=NULL;//当然链表的末端的指针要清空
flag=0;
for(i=0;i<24;i++)
{
for(j=0;j<70;j++)
Amatrix[j]=' ';//先让二维数组全为空格
}
for(i=0,j=0;i<24;j++)
{
Amatrix[j]='-';
if(70==j)
{
j=0;i+=23;
}
}
for(i=0;i<24;i++)
Amatrix[70]='\0';
for(i=1;i<23;i++){
Amatrix[0]='|';Amatrix[69]='|';}//画框框
Amatrix[10][30]='o';
Amatrix[front->x][front->y]=front->body;//把对应位置的蛇身体的部分赋值给数组
Amatrix[rear->x][rear->y]=rear->body;// 这样后面输出二维数组就能表现出蛇的移动了
for(i=0;i<24;i++)
puts(Amatrix);//因为printf比较复杂,输出数组的时候快闪瞎我狗眼了,所以用puts
printf("↑=w,↓=s,←=a,→=d不能穿墙,吃自己或者走反方向必死,界面渣勿喷");
while(1)
{
c=getch();//dir跟c其实是一个意思,都是从键盘上读取输入,获取蛇的移动方向
dir=c;
if(('w'==dir)&&(Amatrix[front->x-1][front->y]!='-')&&(Amatrix[front->x-1][front->y]!='X'))//如果蛇没撞墙或者吃到自己
{
if(Amatrix[front->x-1][front->y]=='o')//吃到禁果,就创造新结点,让它的所有值等于蛇头,并把蛇头移位,蛇头的指针指向新结点
{ //蛇尾不变,这样蛇就变长了
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x--;
Sleep(30); //保持竖直方向的速度与水平方向的速度平衡
score++;
flag=1;
}
else
{ //没吃禁果,同样创造新结点重复上面步骤,但是要把蛇尾去掉,这样蛇就不会变长
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x--;
Sleep(30);
for(p=front;p!=rear;q=p,p=p->next);//让p指向rear,q指向rear前的一个结点
Amatrix[p->x][p->y]=' ';//把原来尾部的位置变成空格
free(p); //销毁尾部
rear=q; //尾部前移
q->next=NULL; //清空指针
p=q=NULL; //下面其他方向的就雷同了,其实能把重复的部分写成一个函数,看起来也简单点,不过撸主懒..
}
}
else if(('s'==dir)&&(Amatrix[front->x+1][front->y]!='-')&&(Amatrix[front->x+1][front->y]!='X'))
{
if(Amatrix[front->x+1][front->y]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x++;
Sleep(30);
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x++;
Sleep(30);
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(('a'==dir)&&(Amatrix[front->x][front->y-1]!='|')&&(Amatrix[front->x][front->y-1]!='X'))
{
if(Amatrix[front->x][front->y-1]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y--;
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y--;
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(('d'==dir)&&(Amatrix[front->x][front->y+1]!='|')&&(Amatrix[front->x][front->y+1]!='X'))
{
if(Amatrix[front->x][front->y+1]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y++;
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y++;
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(((dir=='d')&&(Amatrix[front->x][front->y+1]=='|')||(Amatrix[front->x][front->y+1]=='X'))||((dir=='a')&&(Amatrix[front->x][front->y-1]=='|')||(Amatrix[front->x][front->y-1]=='X'))||((dir=='s')&&(Amatrix[front->x+1][front->y]=='-')||(Amatrix[front->x+1][front->y]=='X'))||((dir=='w')&&(Amatrix[front->x-1][front->y]=='-')||(Amatrix[front->x-1][front->y]=='X')))
{//撞墙或者吃到自己就死
system("cls");//清屏
printf("******************************************************************************\n");
printf("* *\n");
printf("* *\n");
printf("* *\n");
printf("* GAME OVER *\n");
printf("* *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf(" Your score is %d \n",score);
printf(" 屌丝梦工厂出品 (ˉ﹃ˉ) copyright by Frost.\n");
printf("请输入你的名字:");
scanf("%s",name);
if(strcmp(name,love)==0)
printf(" 我喜欢你。 \n");//这是我给女神的末日表白,虽然她没玩这游戏就是了
else
printf("%s ,战斗力只有5的孩子呀你威武雄壮!!(`_ ′)ゝ 5s后重开\n",name);
if(score>=20)
printf("话说你是开挂的吧?\n");
Sleep(5000);//game over 五秒后重开
goto loop;//跳到开头重新游戏
}
for(p=front;p!=NULL;p=p->next)
Amatrix[p->x][p->y]=p->body;//把蛇对应位置的部分赋值给数组
if(flag==1)//如果已经吃了禁果就得重新生成一个
{
a.x=rand()%20+1;//保证禁果不越界 随机生成禁果的坐标
a.y=rand()%65+1;
if((a.x==0)||(Amatrix[a.x][a.y]=='X')||(Amatrix[a.x][a.y]=='H'))
a.x=10;
if((a.y==0)||(Amatrix[a.x][a.y]=='X')||(Amatrix[a.x][a.y]=='H'))
a.y=30;
Amatrix[a.x][a.y]='o';
flag=0;
}
while(!kbhit())//如果没有输入,就按之前移动的方向继续前进
{
Sleep(50);
if(('w'==dir)&&(Amatrix[front->x-1][front->y]!='-')&&(Amatrix[front->x-1][front->y]!='X'))
{
if(Amatrix[front->x-1][front->y]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x--;
Sleep(30);
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x--;
Sleep(30);
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(('s'==dir)&&(Amatrix[front->x+1][front->y]!='-')&&(Amatrix[front->x+1][front->y]!='X'))
{
if(Amatrix[front->x+1][front->y]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x++;
Sleep(30);
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->x++;
Sleep(30);
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(('a'==dir)&&(Amatrix[front->x][front->y-1]!='|')&&(Amatrix[front->x][front->y-1]!='X'))
{
if(Amatrix[front->x][front->y-1]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y--;
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y--;
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(('d'==dir)&&(Amatrix[front->x][front->y+1]!='|')&&(Amatrix[front->x][front->y+1]!='X'))
{
if(Amatrix[front->x][front->y+1]=='o')
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y++;
score++;
flag=1;
}
else
{
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=front->x;p->y=front->y;p->body='X';p->next=front->next;
front->next=p;front->y++;
for(p=front;p!=rear;q=p,p=p->next);
Amatrix[p->x][p->y]=' ';
free(p);
rear=q;
q->next=NULL;
p=q=NULL;
}
}
else if(((dir=='d')&&(Amatrix[front->x][front->y+1]=='|')||(Amatrix[front->x][front->y+1]=='X'))||((dir=='a')&&(Amatrix[front->x][front->y-1]=='|')||(Amatrix[front->x][front->y-1]=='X'))||((dir=='s')&&(Amatrix[front->x+1][front->y]=='-')||(Amatrix[front->x+1][front->y]=='X'))||((dir=='w')&&(Amatrix[front->x-1][front->y]=='-')||(Amatrix[front->x-1][front->y]=='X')))
{
system("cls");
printf("******************************************************************************\n");
printf("* *\n");
printf("* *\n");
printf("* *\n");
printf("* GAME OVER *\n");
printf("* *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf(" Your score is %d \n",score);
printf(" 屌丝梦工厂出品 (ˉ﹃ˉ) copyright by Frost.\n");
printf("请输入你的名字:");
scanf("%s",name);
if(strcmp(name,love)==0)
printf(" 我喜欢你。 \n");
else
printf("%s ,不再来一发吗,少年(■ ▽■)y-~~ 5s后重开\n",name);
if(score>=20)
printf("话说你是开挂的吧?\n");
Sleep(5000);
goto loop;
}
if(flag==1)
{
a.x=rand()%20+1;
a.y=rand()%60+1;
if((a.x==0)||(Amatrix[a.x][a.y]=='X')||(Amatrix[a.x][a.y]=='H'))
a.x=10;
if((a.y==0)||(Amatrix[a.x][a.y]=='X')||(Amatrix[a.x][a.y]=='H'))
a.y=30;
Amatrix[a.x][a.y]='o';
flag=0;
}
for(p=front;p!=NULL;p=p->next)
Amatrix[p->x][p->y]=p->body;
system("cls");//把刚才的屏幕上的东西抹掉,再重新输出数组,就能产生蛇移动的效果
for(i=0;i<24;i++)
{
puts(Amatrix);
}
printf("↑=w,↓=s,←=a,→=d撞墙、自食或者逆行必死,按d开始,渣画面勿喷");
}
system("cls");
for(i=0;i<24;i++)
{
puts(Amatrix);
}
printf("↑=w,↓=s,←=a,→=d撞墙、自食或者逆行必死,按d开始,渣画面勿喷");
}
return 0;
}[/mw_shl_code]
求糖.....#im
[查看全文]
本帖最后由 foodszhu 于 2012-11-23 00:28 编辑
经过上两篇姬宅百度贴吧的自动签到菜鸟脚本教程(一)登陆篇,[url=姬宅百度贴吧的自动签到菜鸟脚本教程(二)签到篇 https://www.gn00.com/t-162458-1-1.html]姬宅百度贴吧的自动签到菜鸟脚本教程(二)签到篇[/url]。基本的脚本我们已经彻底完成了,也完成了一键签到的功能,
但是如果我们有一段时间不能用电脑,或者晚上懒得12点才睡去抢签怎么办?这里简单介绍一下如何将程序部署到google app engine上并使用cron job计划任务帮我们自动执行。
当然大家可以直接去看google给的教程,比我讲的好很多,不过中文教程还是python2.5的。。如果要用2.7还是看英文的
首先我们需要去google申请一个账户,并登陆appengine.google.com来创建自己的第一个应用,一旦创建好我们就有一个免费的二级域名来对我们的应用进行访问。申请好后去GAE 的SDK下载页面下载最新的SDKhttps://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Python,然后配置下环境变量就可以开始了。。
对于我们这种几乎几乎全后台的脚本。。如果不写前端的话还是很容易的。。
先写app.yaml,对于我而言,我的应用名叫autologin-foodszhu.
[mw_shl_code=text,true]application: autologin-foodszhu
version: 2
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /all
script: loginAll.py[/mw_shl_code]
这个loginAll.py就是我们写的一键签到的脚本
然后再完成cron.yaml来完成定时任务[mw_shl_code=text,true]
cron:
- description: daily login job
url: /all
schedule: every 1 mins from 0:00 to 0:20
timezone: Asia/Shanghai
- description: every mouth clear job
timezone: Asia/Shanghai[/mw_shl_code]
这个cron我们在schedule种定义每天0:00到0:20每过一分钟,都运行一次loginAll的脚本。因为害怕如果只在0:00运行一次,很容易超时,而gae每个响应至多只能有30s时间,超过就会错误。。所以我们在这段时间内多次运行。
然后用appcfg.py将自己的应用部署上去即可
这就算简单的完成了,如果没什么特殊要求。。这样做一般可以保证每日都会签到。。但是如果你要签到的贴吧数较多,而百度每日只允许签到100个贴吧,但是你用程序签到并不管你这个真的签到成功与否,反正执行一次,便多记录你你签到贴吧数目一个。这样,在0:00至0:20中多达20次的请求很容易将100个名额用完。这时我们便要将已经签到过的贴吧保存下来,下次签到时不再签到。。这也是为什么qiandaoAll方法会有一个except_list的原因。
由于GAE不允许本地文件的写入,所以我们必须用它给的数据存储区功能,好吧。。。其实我也只是照着写。。。没有仔细研究过。。
首先引入数据存储区的模块[mw_shl_code=python,true]from google.appengine.ext import db[/mw_shl_code]
在qiandao模块中,我们加入一个数据存储模型
[mw_shl_code=python,true]class QiandaoResult(db.Expando):
name=db.StringProperty()
no=db.IntegerProperty()
isQiandao=db.BooleanProperty()
time=db.DateTimeProperty()[/mw_shl_code]
提供了几个简单的属性,name为名字,no为返回代码,isQidandao记录是否签到成功,time记录本次签到的时间。因为我们不希望只记录下这几个信息,所以我们从db.Expando
DateTimeProperty 属性类支持tzinfo来对时区进行转换,数据存储区的数据自动转换为UTC时区,但是我们毕竟还是Asia/Shanghai的时区,所以我们要自己转换。
datetime模块中的tzinfo只是一个抽象类,并没有具体实现,所有我们可以采用一个第三方模块pytz,来帮我们转换,不过第三方模块部署时要一并附在应用目录下。pytz只有2mb大小,不算大,如果实在嫌大,可将pytz下zoneinfo中无关文件全部删掉。。只留我们需要的时区。
这时可以对我们的analyseQiandaoResult方法进行一定修改
[mw_shl_code=applescript,true]def analyseQiandaoResult(self,tieba_name,response):
now=datetime.datetime.now(pytz.timezone('Asia/Shanghai'))
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
dataStore=QiandaoResult(name=self.name,no=no,isQiandao=True,time=now)
for key,value in result.iteritems():
dataStore.__setattr__(key,value)
else:
result=tieba_name,error
dataStore=QiandaoResult(name=self.name,no=no,isQiandao=False,time=now)
dataStore.error=error
dataStore.tieba_name=tieba_name
if no == 1101 or no == 1007:
dataStore.isQiandao=True
dataStore.put()
return no,result[/mw_shl_code]
[mw_shl_code=python,true]now=datetime.datetime.now(pytz.timezone('Asia/Shanghai'))[/mw_shl_code]
来申明一个datetime对象记录在'Asia/Shanghai下的当前时间
[mw_shl_code=python,true]dataStore=QiandaoResult(name=self.name,no=no,isQiandao=True,time=now)
for key,value in result.iteritems():
dataStore.__setattr__(key,value)[/mw_shl_code]
初始化实体并添加动态属性方便我们日后提取调用。。
[mw_shl_code=python,true]dataStore.put()[/mw_shl_code]
提交实体。。
在loginAll里对已存储的实体进行查询
[mw_shl_code=applescript,true]today=datetime.datetime.combine(datetime.date.today(),datetime.time(tzinfo=pytz.timezone('Asia/Shanghai')))
jishuzhai=qiandao.JishuzhaiQiandao()
jishuzhai.login()
if not db.GqlQuery("SELECT * FROM QiandaoResult WHERE name = :1 AND isQiandao = True",jishuzhai.name).get():
jishuzhai.qiandao()
baidu=qiandao.TiebaQiandao()
baidu.login()
qbaidu=list(db.GqlQuery("SELECT * FROM QiandaoResult WHERE name = :1 AND isQiandao = True AND time >= :2",baidu.name,today))
response_list=baidu.qiandaoAll(*[item.tieba_name for item in qbaidu])[/mw_shl_code]
定义一个每天0:00的datetime对象,通过对这个对象的不等式查询,来确定今天的已签到的贴吧,最后对未签到的贴吧进行签到。。可以减少签到次数
但是实际应用对签到速度的提升并不明显。。。关键在于每晚gae对百度登陆都很卡。。姬宅的完全无压力。。。贴吧签到就只能慢慢跑了。。最后放上自己在gae部署的程序,大家自己改下appid和用户名密码什么就可以用了。。
[查看全文]
本帖最后由 foodszhu 于 2012-11-21 00:23 编辑
继续前一篇的内容,姬宅百度贴吧的自动签到菜鸟脚本教程(一)登陆篇
(一)准备
其实经过上一篇所讲,签到也是一个类似的过程
这次我们用firefox的firebug插件为例来探究下签到的过程
1.姬宅签到:
因为自己自从写了这个脚本之后就真的自动签到了。。所以新建了一个号来截图。。不过用户组在loading下无法完成签到,不过仍可以登陆进签到中心,来查看提交的表单,跟在主页签到完全一样。进入页面打开firebug,进入网络分页,点击保持按钮保证处于保持状态,然后选好参数,这里我选择不想填写,签到心情是慵懒。单击开始签到
同登陆时一样,是一个post表单,url是https://www.gn00.com/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&inajax=1,qdmode是签到模式,貌似1是自己填写,3是不想填写,2是什么不清楚,qdxq是签到心情,yl是慵懒。。好吧都是拼音。。
这些都是可以固定下来或者随机选取的。而唯一看似重要的formhash是什么呢?我们打开页面的源代码进行搜索。。
表单处理那发现这么一行[mw_shl_code=html,true]<form id="qiandao" method="post" action="plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1">
<input type="hidden" name="formhash" value="05bdef8b">[/mw_shl_code]
明显为我们所需。。在登陆的基础上,签到明显是个简单活动
2.贴吧签到
以bilibili吧为例
登陆bilibili吧,单击签到,
也是post表单,url为http://tieba.baidu.com/sign/add,三个参数也十分简单
ie估计是编码格式,kw为贴吧名称,tbs估计为贴吧的代码,打开源代码进行搜索
[mw_shl_code=html,true] *本站禁止HTML标签噢*
PageData.tbs = "483101895300e4521353410592";[/mw_shl_code]
可查到这么一行,说明tbs也可从本页面直接获取。
需要注意的是,中文贴吧名在转化为url时,必须是由gbk码转换成url。才能正常访问
把所需要的数据放在qiaodao.ini中方便读取
[mw_shl_code=text,true]#qiandao.ini
[技术宅]
url=https://www.gn00.com
qiandao_url=https://www.gn00.com/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&sign_as=1&inajax=1
fastreply=0
formhash=
qdmode=3
qdxq=fd
todaysay=
[百度]
url=http://www.baidu.com
qiandao_url=http://tieba.baidu.com/sign/add
ie=utf-8
kw=
tbs=[/mw_shl_code]
不过单纯一个贴吧的签到当然无法满足我们,我们要尝试下签到所有喜欢的贴吧,第一步,就要找出自己的喜爱的贴吧。
这里我提供两种方案
1.通过http://www.baidu.com/p/用户名?from=tieba进入到百度个人主页的我在贴吧子页,从中获取我最喜爱的吧。
2.在登陆状态下,通过http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=用户名进入到个人的i贴吧,从中提取我爱逛的贴吧。
具体操作稍后再讲
相比登陆方面,签到简直是没有任何难度。。。所以我们就要在脚本上下点功夫了
(二)脚本先上总脚本,这个签到本来是一件非常简单的事,但是不比登陆,我们往往需要获得一些签到返回的信息,所以对返回信息稍作处理
[mw_shl_code=python,true]#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# qiandao.py
import login,re,urllib,urllib2,json,threading
import ConfigParser as cp
class Qiandao(login.Login):
def __init__(self,name):
super(Qiandao,self).__init__(name)
self.loadIni('qiandao.ini',name,self.data,'url','qiandao_url')
def qiandao(self):
data = urllib.urlencode(self.data)
req = urllib2.Request(self.qiandao_url,data,self.headers)
response = self.opener.open(req)
self.qiandao_response=response
self.qiandao_response_read=response.read().decode('utf-8')
return self.qiandao_response_read
class TiebaQiandao(Qiandao,login.BaiduLogin):
def __init__(self,name='百度'):
self.result_list={u'cont_sign_num':u'连续签到天数', u'cout_total_sing_num':u'本月累计签到天数',u'user_sign_rank':u'个人签到排名',u'tieba_name':u'贴吧'}
super(TiebaQiandao,self).__init__(name)
def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t
def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response
def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list
def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[]
for i in j:
l.append(i['name'].encode('utf-8'))
print i['name'].encode('utf-8')
return l
def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result
def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''
class JishuzhaiQiandao(Qiandao,login.JishuzhaiLogin):
def __init__(self,name='技术宅'):
super(JishuzhaiQiandao,self).__init__(name)
def getFormHash(self):
buf=self.opener.open(self.url).read().decode('utf-8')
r=r'formhash=\w+'
s=re.findall(r,buf)[0].split('=')[1]
return s
def qiandao(self):
self.setData(formhash=self.getFormHash())
response = super(JishuzhaiQiandao,self).qiandao()
return response
def analyseQiandaoResult(self):
r=r'<div class="c">\r\n(.*?) </div>'
result=re.findall(r,self.qiandao_response_read)[0]
if u'成功' in result:
no=0
else:
no=1
return no,result
def printQiandaoResult(self):
no,result=self.analyseQiandaoResult()
print '技术宅社区:'
if no == 0:
print '签到成功:'
else:
print '签到失败:'
print result
print ''
def main(name):
if name=='技术宅':
website=JishuzhaiQiandao()
website.login()
website.qiandao()
website.printQiandaoResult()
elif name=='百度':
tieba_name=raw_input("输入您想签到的贴吧名称(如果想签到所有喜欢贴吧请打all):").lower()
website=TiebaQiandao()
website.login()
if tieba_name != 'all':
website.printQiandaoResult(*website.analyseQiandaoResult(*website.qiandao(tieba_name)))
else:
response_list=website.qiandaoAll()
for item in response_list:
website.printQiandaoResult(*website.analyseQiandaoResult(*item))
else:
print '没有填写配置文件!'
return 1
return 0
if __name__ == '__main__':
name=raw_input('输入您想登陆的网站名称(确保您已填写配置文件):')
main(name)
[/mw_shl_code]
[mw_shl_code=python,true]import login,re,urllib,urllib2,json
import ConfigParser as cp[/mw_shl_code]
依旧是首先引入模块,这里需要引入上篇我们写的登陆模块。。
[mw_shl_code=python,true]class Qiandao(login.Login):
def __init__(self,name):
super(Qiandao,self).__init__(name)
self.loadIni('qiandao.ini',name,self.data,'url','qiandao_url')
def qiandao(self):
data = urllib.urlencode(self.data)
req = urllib2.Request(self.qiandao_url,data,self.headers)
response = self.opener.open(req)
self.qiandao_response=response
self.qiandao_response_read=response.read().decode('utf-8')
return self.qiandao_response_read[/mw_shl_code]
同样是先构造签到的基类,由于签到是基于登陆完成,且两者有很多共同之处,所以将Login类设为Qiandao类的基类,可以省下很多操作
初始化时多一步读取qiandao.ini的内容作为表单值。
定义新的方法qiandao作为签到的实际做法,不过跟登陆的做法极为类似,只是换掉了登陆的url而已,不过这个qiandao必须在已登陆的前提下再进行签到。
[mw_shl_code=python,true]class TiebaQiandao(Qiandao,login.BaiduLogin):
def __init__(self,name='百度'):
self.result_list={u'cont_sign_num':u'连续签到天数', u'cout_total_sing_num':u'本月累计签到天数',u'user_sign_rank':u'个人签到排名',u'tieba_name':u'贴吧'}
super(TiebaQiandao,self).__init__(name)
def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t
def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response
def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list
def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[]
for i in j:
l.append(i['name'].encode('utf-8'))
print i['name'].encode('utf-8')
return l
def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result
def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''
[/mw_shl_code]
当签到的基类构造好时我们就要构造下一步的子类了,但是在登陆基类我们已经派生出两个子类BaiduLogin和JishuzhaiLogin,来分别处理百度与姬宅的登陆,所以我们既需要从登陆的两个子类中继承需要的功能,又需要从签到基类中继承所需要的功能,所以我们采用多继承的方法。
在我们的TiebaQiandao类中,我们既继承了BaiduLogin类,又继承了Qiandao类,为了防止共同父类方法的多次调用,我们采用super来调用父类的方法。
super是采用mro方式处理多继承中共同方法的多次调用的问题的,所以为了运行良好,我们必须将所有的调用父类的形式都改为super
同时,由于新型类中,mro顺序是广度优先的,所以同层间的相同方法最好使用相同的参数个数,否则就可能报错,而且达不到我们想要的结果。关于这部分的讨论,搜索一下python的多继承
[mw_shl_code=python,true]def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t[/mw_shl_code]
这两个函数是为了得到签到的表单项之一的tbs,我们从该贴吧的页面中获取信息,所以得先进入这个贴吧,
而贴吧url形式为http://tieba.baidu.com/f?kw=贴吧名,当然贴吧名需要处理为url能识别的形式,而且得从gbk码转换而来,由于我编码的统一为utf-8,所以要做进一步转换
同样用正则表达式将tbs挑捡出来
[mw_shl_code=python,true]def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[i['name'].encode('utf-8') for i in j]
return l[/mw_shl_code]
getAllTiebaList是获取喜爱贴吧的方法,其中我注释的部分是我在准备篇中所说的第一种方法,即进入到个人主页中提取。。其中包含在target=_blank title=后面的即是贴吧名,不过后面多了一个吧字,在这里我们用rstrip将其消掉,字符串rstrip方法用于消去共同后缀,rstrip消去共同前缀,使用默认参数时消去空格
第二种方法,即在登陆前提下,进入个人的i贴吧,从中获取贴吧信息,而这个部分信息较为混杂,我们仔细查看,发现在响应的末尾有一组以脚本形式存储的信息,以$_likeForum开头的数据
我们先用re模块将字符串提取出来,注意$需要转义所以加\,然后用json模块将字串转化为我们能够直接用的对象,在这里面会生成一组列表,列表中每一项都是一个字典,包括了爱逛的贴吧的信息,这里我们暂且只用name这一对键值,同时用了列表推导的技巧生成了这个列表
[mw_shl_code=python,true]def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response[/mw_shl_code]
qiandao方法是对父类的签到方法的具体实现,对于贴吧签到而言,我们不仅需要登陆百度,而且还需要知道所要签到的贴吧名,在加上贴吧的tbs后,发送表单完成签到
同时返回贴吧名与响应的元组
[mw_shl_code=python,true]def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result[/mw_shl_code]
analyseQiandaoResult方法正是为了分析qiandao方法返回响应的方法,它所需参数正好是签到返回的结果,而这个响应结果,直接是以json形式存储的,所以我们可以用json模块直接提取出来,其中no是返回代码,0即登陆成功,1101代表已经登陆,1007代表今天签到次数超过100次,error即错误说明。
如果签到成功,响应中data对应值即是一些个人排名啊,贴吧排名,贴吧目录等项,uinfo代表个人信息,我们这里只取个人信息保存。最终返回响应代码与一个打包好的字典作为返回结果
[mw_shl_code=python,true]def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''[/mw_shl_code]
从分析结果中我们最终打印出我们需要的结果。。这块就不多说了。
[mw_shl_code=python,true]def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list[/mw_shl_code]
qiandaoAll方法用于签到所有爱逛的贴吧,参数中except_list用于设定无需签到的贴吧,这里其实可以用多线程,不过仔细想想还是觉得略麻烦而且在gae上部署也很麻烦多以就放弃了
姬宅的签到与贴吧签到类似,只需要加上一个formhash即可提交。当然两者都需要先login,再qiandao
最后我们就可以来个一键签到了[mw_shl_code=python,true]#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# 一键签到.py
#
import qiandao,os
def main():
jishuzhai=qiandao.JishuzhaiQiandao()
baidu=qiandao.TiebaQiandao()
jishuzhai.login()
baidu.login()
jishuzhai.qiandao()
jishuzhai.printQiandaoResult()
response_list=baidu.qiandaoAll()
for item in response_list:
baidu.printQiandaoResult(*baidu.analyseQiandaoResult(*item))
return 0
if __name__ == '__main__':
main()[/mw_shl_code]
将这个代码文件设为可执行,需要签到时运行即可
自动签到的主体部分就到此结束了。。。下来一篇就是将如何将这个脚本部署在gae上,并且用计划任务在12点附近进行签到。。。不过gae要求只能有最多30s的响应时间所以12点刚过那阵贴吧签到各种Deadline exceeded。。。。几乎到快到20才能勉强签上。。不知为何。。暂时也没有用多线程。。难道只有用多线程才能改进一下么
恩恩。。下一篇就是部署到gae上,并进行少量优化
发帖果然理会的人不多啊。。。而且自己话也说不太清楚。。。自己第一次写教程也请各位见谅。。再。。求发糖#18t
[查看全文]
顺便博客求关注:http://bimania.org/
在stackoverflow上看到一个有趣的问题:给定一张图片,如何表示并解决图片上的迷宫。
自己也写了一下,稍微用qt做了个界面。其实并没有用到什么很难的算法,只是一个简单的BFS。
当然迷宫上会有一个入口和出口,首先需要自己对图片做下预处理,把入口和出口封住,否则最后算出的最短路径将是从迷宫外面的空白区域绕过去的。另外程序运行之后还要用鼠标确定起点和终点,剩下就是从起点开始进行BFS,直到到达终点。另外需要注意的是边界和路径的区分,这个是通过计算像素点的灰度值,将灰度值超过一定限度的作为边界,低于的作为可以通过的区域。
[mw_shl_code=python,true]import sys
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from collections import deque
class State:
def __init__(self, x, y, pre=None):
self.x = x
self.y = y
self.pre = pre
def __str__(self):
return "(%d, %d)" % (self.x, self.y)
class MazeLabel(QLabel):
def __init__(self, pixmap, path, parent=None):
QLabel.__init__(self, parent)
self.setPixmap(pixmap)
self.path = path
self.p1 = None
self.p2 = None
def isWhite(self, c):
if abs(qGray(c) - qGray(qRgb(255, 255, 255))) < 30:
return True
else:
return False
def solve(self, img):
q = deque()
q.append(State(self.p1.x(), self.p1.y()))
img.setPixel(self.p1.x(), self.p1.y(), qRgb(0, 0, 0))
print len(q)
#cnt = 100
while len(q) > 0:
s = q.popleft()
#print s
if s.x == self.p2.x() and s.y == self.p2.y():
return s
for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
nx, ny = s.x + dx, s.y + dy
if nx >= 0 and nx < img.width() and ny >= 0 and ny < img.height() and self.isWhite(img.pixel(nx, ny)):
q.append(State(nx, ny, s))
img.setPixel(nx, ny, qRgb(0, 0, 0))
#cnt = cnt - 1
print "no solution!"
def mousePressEvent(self, ev):
if self.p1 == None:
self.p1 = ev.pos()
else:
self.p2 = ev.pos()
print self.p1
print self.p2
image = self.pixmap().toImage()
sol = self.solve(image)
image = self.pixmap().toImage()
it = sol
while it != None:
image.setPixel(it.x, it.y, qRgb(255, 0, 0))
it = it.pre
self.setPixmap(QPixmap.fromImage(image))
self.update()
fileName, fileExt = os.path.splitext(self.path)
newFileName = fileName + "_solved" + fileExt
self.pixmap().save(newFileName)
if __name__ == "__main__":
app = QApplication(sys.argv)
scrollArea = QScrollArea()
pixmap = QPixmap(sys.argv[1])
imageLabel = MazeLabel(pixmap, sys.argv[1])
scrollArea.setWidget(imageLabel)
scrollArea.show()
app.exec_()
[/mw_shl_code]
下面是一个迷宫的例子,非常复杂,入口在左上角,出口在右下角
不过用程序,很容易能得出啊答案,下面是程序给出的解
[查看全文]
本帖最后由 基叔 于 2012-11-1 21:56 编辑
前言
开发android应用当然要直接在android手机上开发,
集开发调试于一身。多方便。 不需要在电脑上安装什么东西,简单粗暴。
这次就是给大家带来两个手机上的应用,
一个是编码器,一个是我自己弄的应用Run!
可以让你直接在手机上开发运行并调试应用,工作原理是基于phonegap
这个东西我在下次介绍如何发布我们的应用时一起说明。
正文
重复一遍好了:我们这次是介绍在手机上开发!
搭建的是开发与调试和运行环境,发布应用的环境以后讲。
1:环境搭建 下载这玩意儿安装在你android手机里 戳我 run.apk 这个就是我们依赖的环境了,
还有这个东西 我们的编辑器 Droidedit 一起安装
2:下载这个www.zip,把里面的东西解压到你sdcard根目录。没有外置卡的同学解压到手机内部存储的根目录就可以了
3:戳开手机上的Run!应用
现在你可以玩一下那个应用。开始讲开发啦
点开Droideidt 输入这个
编写里面的内容 如下
[mw_shl_code=xhtml,true] *本站禁止HTML标签噢* hello world</h1>[/mw_shl_code]
保存起来,命名为index.html,扔进之前的www文件夹,覆盖掉原来的index.html
然后重新戳开那个Run! 看看有什么变化捏
恩恩这个就是简单的hello world 了....由于前言写太多了,其他的教程部分下次写吧
布置一下作业,比如自己写不一样的index.html放进去,看看是什么样子呢~
下次讲怎么完善和怎么发布应用。拜拜
[查看全文]
本帖最后由 秋声赋 于 2012-6-4 11:57 编辑
简单易懂的现代魔法:C#编程教程(五)简单计算器示例很久没写了,主要是觉得4篇之后没什么人关注了...
本帖是很久以前就完成了的,只是一直没找到时间来发,乘着现在有时间,把这个帖子发出来.
本帖将带你们用C#做一个简单的计算器程序.
就像Windows自带的那样,当然只包括标准版,学会了标准版的做法,做其他类型的计算器就不难了,希望大家能举一反三把剩余的功能做出来.
本帖要求有基本的VS2010使用能力和知道C#的基本语法,就是前面的帖子说的那些,这算一个综合应用.
先说明一点,我会把源代码在附上,但是我更希望大家手打这些代码到编辑器中.手打的过程中能发现很多自己没注意的问题,而且代码并不多.
相应代码的逻辑,我会在代码中用注释表示出来,不会用文字写在帖子里面.
所以在介绍各个部分的时候,我会用图片的形式贴上代码,还一个原因就是论坛的代码高亮功能实在脑残,如果只有一种颜色,看代码会有些吃力.//====================================================================================\\首先我们来介绍一下我们要做的这个计算器的功能和大概思路.上面是程序的界面,由2个文本框(TextBox)和23个按钮(Button)控件所构成.如字面所说,他具有一个简单计算器的功能,可以通过按钮和键盘输入,上面一个文本框是显示当前的计算式,下面是结果.如果还有不明白的可以打开Windows自带的计算器试验一下.思路如下:1. 我们需要一个枚举来记录我们当前的操作符.2. 分为3种按钮:数字,操作符,退格键.分别对应3个响应函数.3. 通过读取按钮上的文字来判断各个按钮的功能.4. 因为输入全为个位整数,用小数点和小数点后面的数的数目表示小数.5. 通过下面的文本框记录和传递所输入的数字了解了这些,我们就可以开始制作我们的计算器了.
首先打开VS2010建一个C#的Windows窗体应用程序(WinForm)
然后从工具箱中拖出2个TextBox控件和23个Button控件摆放如下图:
并为每一个控件命名和修改Text属性(显示的字符),为了增加程序的可读性,
为每一个按钮和文本框都取上代表其含义的名字.具体可以看后面我发的源代码.
这是系统自动生成的代码,最后面就是按钮的名字,不要吐槽我的英语,一直在及格边缘徘徊.
然后就进入代码编辑页面.根据上面的分析,我们首先要一个枚举来标识运算符(其实只用数字也能记录,但是为了程序的可读性和安全性,我们选择枚举来记录).定义如下然后我们需要几个变量来帮助我们记录当前的状态.(无视图片中全局2个字)Operators是我们刚刚定义的枚举噢.
接着是完成4个消息响应函数,这是整个程序的核心,他们分别是:数字按钮消息响应函数(number_click),操作符按钮响应函数(button_Oper_Click),退格键按钮响应函数(BT_BACK_Click),文本框键盘消息响应函数(TB_FORMULA_KeyDown).首先在按钮的[属性]—[事件]处为每一个按钮添加相应的事件.并双击函数名进入代码编辑状态.注意不要用自动生成的函数!要自己取函数名,且响应的按钮类别对应响应的响应函数.
最先讲下数字按钮消息响应函数(number_click).这个函数的目的是处理用户按下按钮的Click事件,记录按下按钮对应的数字,并根据当前的状态(是否有小数点)来保存数字,并修改文字框TB_FORMULA所显示的数字.代码和原理如下所示:然后是最复杂的操作符按钮响应函数,这个函数的目的是响应用户按下的操作符按钮,当一个操作符按钮被按下时,系统要根据上一个运算符来对当前的数字进行一定的操作.并根据按钮的文本判断是那种操作符,并记录下来,不同的操作符也对应了不同的操作.主要用到了Case分支语句,代码如下:接下来是退格键响应函数(BT_BACK_Click),他的作用是响应退格键,并从2个文本框里面删除最后一位,并更新记录输入数据的变量.代码如下:最后是键盘响应函数,首先为我们的TB_EXPRESSIION文本框添加一个KeyDown事件的消息响应函数TB_FORMULA_KeyDown.如下图所示.那怎么发生相应的消息呢?我们是用模拟用户点击按钮的方法实现.首先判断用户按的是那个键,再调用相应的按钮响应函数,并把相应的按钮当做参数发送给响应函数.例如当用户按下小键盘的1时,因为他是数字按钮,我们就调用number_click函数,并把他的第一个参数(objectsende)设置为BT_1表示用户按了1的按钮.至于第二个参数,因为我们不要用他,把他设为null就行.代码如下:其中Keys里面有所有键盘按键对应的代码,例如NumPad1就是小键盘1的意思.
到这里我们的计算器就做好了,大家可以编译并运行试一下效果.如果有不懂的地方可以回帖问我.下面布置个作业:做出Windows自带的计算器的科学型.[查看全文]