转载自:国庆节,我们用代码来画个国旗~ - 知乎 (zhihu.com)
如果你刚好闲的无聊,想想以前每次放假,本来放假前想好出去干啥干啥的,最后都是窝在家里敲代码了。可能很多人还是如此,那么怎样给这一天的代码的添上一点色彩?为何不做点有意思的东西?Use your CODE!
恰巧是国庆,那就让我们以一种不同的方式来庆祝她。庆祝祖国的67岁生日。让我们用不同的语言来编织我们的五星红旗……
第一个:HTML + JavaScript
代码(测试通过):
<html>
<head>
<script>
var col=new Array("red","brown");
var ticker=0;
var step=0;
function drawBackground(){
var g=document.getElementById("background").getContext("2d");
var grd=g.createLinearGradient(-560+ticker, 0, 1400+ticker,0);
for (var i=0; i<10; i++)
grd.addColorStop(i/10,col[(i + step)%col.length]);
ticker=ticker+10;
if (ticker>=196){
ticker=0;
step++;
}
g.fillStyle=grd;
g.fillRect(0,0,1600,700);
}
function preperation(){
setInterval('drawBackground()',100);
}
</script>
<style type="text/css">
#myCanvas{
z-index:2;
position:absolute; left:0px; top:-5px;
}
#background{
z-index:1;
position:absolute;
left:0px;
top:0px;
}
</style>
</head>
<body onLoad="preperation()">
<canvas id="myCanvas" width="900" height="600" >
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="background" width="1600" height="700" ></canvas>
<script>
var x=new Array(0,12,54,18,28,0,-28,-18,-54,-12,0); //五角星样品坐标xx数组
var y=new Array(-53,-17,-17,1,45,19,45,1,-17,-17,-53); //五角星样品坐标y数组
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d"); //获得画笔
//样品数组x轴坐标 a , 和y轴坐标 b
//指定位置[locationX,locationY]
//真实五角星的大小,与样品五角星尺寸之比 f
//五角星画完后,旋转的角度 rotation
function star(a,b,locationX,locationY,f,rotation){
ctx.save();//记录画图(画笔)的初始环境
ctx.translate(locationX,locationY);
ctx.rotate(rotation*Math.PI/180.0);
ctx.beginPath();
ctx.moveTo(Math.round(a[0]*f),Math.round(b[0]*f));
for (var i=1;i<a.length;i++)
ctx.lineTo(Math.round(a[i]*f),Math.round(b[i]*f));
ctx.closePath();
ctx.fillStyle="yellow";
ctx.fill();
ctx.restore();//还原画图(画笔)的初始环境
}
star(x,y,165,165,1.4,0);//画大五角星
star(x,y,301,65,0.5,30);//画小五角星
star(x,y,362,126,0.5,-30);//画小五角星
star(x,y,359,216,0.5,0);//画小五角星
star(x,y,301,273,0.5,30);//画小五角星
</script>
</body>
</html>
运行效果截图:
第二个:Java
代码(测试通过):
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import javax.swing.JFrame;
public class NationalFlag extends JFrame {
private int width = 288,height = width/3*2;
private double maxR = 0.15, minR = 0.05;
private double maxX = 0.50, maxY = 0.50;
private double[] minX = {0.75, 0.85, 0.85, 0.75};
private double[] minY = {0.35, 0.45, 0.60, 0.70};
public NationalFlag() {
setTitle("国旗 - by fants(铂金小鸟)");
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
@Override
public void paint(java.awt.Graphics graphics) {
super.paint(graphics);
java.awt.Graphics2D g = (java.awt.Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//棋面
g.setColor(java.awt.Color.red);
g.fillRect(50, 50, width, height);
g.setColor(java.awt.Color.yellow);
//画大星星
double ox = height*maxX, oy = height*maxY;
g.fill(createPentacle(ox,oy,height*maxR,-Math.PI/2));
//画小星星
for(int idx =0;idx < 4;idx ++){
double sx = minX[idx]*height, sy = minY[idx]*height;
double theta = Math.atan2(oy-sy,ox-sx);
g.fill(createPentacle(sx,sy,height*minR,theta));
}
}
/**
* 创建一个五角星形状. 该五角星的中心坐标为(sx,sy),中心到顶点的距离为radius,其中某个顶点与中心的连线的偏移角度为theta(弧度)
*
* @return pentacle 一个☆
*/
public static java.awt.Shape createPentacle(double sx, double sy, double radius,double theta) {
final double arc = Math.PI / 5;
final double rad = Math.sin(Math.PI / 10) / Math.sin(3 * Math.PI / 10);
GeneralPath path = new GeneralPath();
path.moveTo(1, 0);
for (int idx = 0; idx < 5; idx++) {
path.lineTo(rad * Math.cos((1 + 2 * idx) * arc),rad * Math.sin((1 + 2 * idx) * arc));
path.lineTo(Math.cos(2 * (idx + 1) * arc),Math.sin(2 * (idx + 1) * arc));
}
path.closePath();
AffineTransform atf = AffineTransform.getScaleInstance(radius, radius);
atf.translate(sx / radius, sy / radius);
atf.rotate(theta);
return atf.createTransformedShape(path);
}
public static void main(String[] args) {
NationalFlag flag = new NationalFlag();
flag.setBounds(100, 100, 400, 400);
flag.setVisible(true);
}
}
运行效果截图:
第三个:Python(版本是2.7)
代码(测试通过):
#coding=utf-8
'''
Created on 2014-11-17
@author: Neo
'''
import turtle
import math
def draw_polygon(aTurtle, size=50, n=3):
''' 绘制正多边形
args:
aTurtle: turtle对象实例
size: int类型,正多边形的边长
n: int类型,是几边形
'''
for i in xrange(n):
aTurtle.forward(size)
aTurtle.left(360.0/n)
def draw_n_angle(aTurtle, size=50, num=5, color=None):
''' 绘制正n角形,默认为黄色
args:
aTurtle: turtle对象实例
size: int类型,正多角形的边长
n: int类型,是几角形
color: str, 图形颜色,默认不填色
'''
if color:
aTurtle.begin_fill()
aTurtle.fillcolor(color)
for i in xrange(num):
aTurtle.forward(size)
aTurtle.left(360.0/num)
aTurtle.forward(size)
aTurtle.right(2*360.0/num)
if color:
aTurtle.end_fill()
def draw_5_angle(aTurtle=None, start_pos=(0,0), end_pos=(0,10), radius=100, color=None):
''' 根据起始位置、结束位置和外接圆半径画五角星
args:
aTurtle: turtle对象实例
start_pos: int的二元tuple,要画的五角星的外接圆圆心
end_pos: int的二元tuple,圆心指向的位置坐标点
radius: 五角星外接圆半径
color: str, 图形颜色,默认不填色
'''
aTurtle = aTurtle or turtle.Turtle()
size = radius * math.sin(math.pi/5)/math.sin(math.pi*2/5)
aTurtle.left(math.degrees(math.atan2(end_pos[1]-start_pos[1], end_pos[0]-start_pos[0])))
aTurtle.penup()
aTurtle.goto(start_pos)
aTurtle.fd(radius)
aTurtle.pendown()
aTurtle.right(math.degrees(math.pi*9/10))
draw_n_angle(aTurtle, size, 5, color)
def draw_5_star_flag(times=20.0):
''' 绘制五星红旗
args:
times: 五星红旗的规格为30*20, times为倍数,默认大小为10倍, 即300*200
'''
width, height = 30*times, 20*times
# 初始化屏幕和海龟
window = turtle.Screen()
aTurtle = turtle.Turtle()
aTurtle.hideturtle()
aTurtle.speed(10)
# 画红旗
aTurtle.penup()
aTurtle.goto(-width/2, height/2)
aTurtle.pendown()
aTurtle.begin_fill()
aTurtle.fillcolor('red')
aTurtle.fd(width)
aTurtle.right(90)
aTurtle.fd(height)
aTurtle.right(90)
aTurtle.fd(width)
aTurtle.right(90)
aTurtle.fd(height)
aTurtle.right(90)
aTurtle.end_fill()
# 画大星星
draw_5_angle(aTurtle, start_pos=(-10*times, 5*times), end_pos=(-10*times, 8*times), radius=3*times, color='yellow')
# 画四个小星星
stars_start_pos = [(-5, 8), (-3, 6), (-3, 3), (-5, 1)]
for pos in stars_start_pos:
draw_5_angle(aTurtle, start_pos=(pos[0]*times, pos[1]*times), end_pos=(-10*times, 5*times), radius=1*times, color='yellow')
# 点击关闭窗口
window.exitonclick()
if __name__ == '__main__':
draw_5_star_flag()
运行效果截图:
第四个:R
代码(没有测试):
star<-function(posXY,size=1,theta=0,color="yellow")
{
alpha<-2*pi/5
R<-size
r<-sin(pi/10)*R/sin(7*pi/10)
pointpos<-matrix(0,nrow=10,ncol=2)
Beta<-(pi/10+theta)+(0:4)*alpha
pointpos[seq(1,9,2),]<-cbind(cos(Beta)*R+posXY[1],sin(Beta)*R+posXY[2])
Beta<-(3*pi/10+theta)+(0:4)*alpha
pointpos[seq(2,10,2),]<-cbind(cos(Beta)*r+posXY[1],sin(Beta)*r+posXY[2])
polygon(pointpos,col=color,border=color)
}
#计算小五角星旋转角度的函数
rotTheta<-function(posxy,posXY)
{
atan((posXY[2]-posxy[2])/(posXY[1]-posxy[1]))+pi/2
}
#常量设置
width<-3
height<-2*width/3
d<-width/30
yshift<-height/2
#国旗的坐标
Flag<-cbind(c(0,width,width,0),c(0,0,height,height))
#大五角星坐标
posXY<-c(5*d,yshift+5*d)
#小五角星坐标
posxy<-matrix(c(10,8,12,6,12,3,10,1),ncol=2,byrow=T)*d+matrix(c(0,yshift),nrow=4,ncol=2,byrow=T)
#小五角星旋转角度
rottheta<-rep(0,nrow(posxy))
rottheta<-apply(posxy,1,rotTheta,posXY)
#画红色的国旗底面
plot(Flag,type="n",col="red",axes=F,xlim=c(0,width),ylim=c(0,height),xlab="",ylab="",main="People's Republic of China",asp=1)
polygon(Flag,density=NULL,col="red",border="red")
#画出大五角星
star(posXY,size=3*height/20,theta=0,color="yellow")
#画出四颗小星
for(i in 1:nrow(posxy))
{
star(posxy[i,],size=height/20,theta=rottheta[i],color="yellow")
}
运行效果截图: