12
\$\begingroup\$

You just invited a liberal arts major to your house and you're telling him/her

"You know, I am a great programmer and I can do x and y and z..."

S/he quickly gets bored and asks you:

"If you really are a great programmer, can you make a programme to let me draw, I just need to draw lines on the screen by using the mouse, and selecting different colours in any manner".

Your code may import standard libraries. Your code may require the colours to be selected via the keyboard.

This is ; shortest code wins.

Bullet points

  • The lines are drawn by moving the mouse around while pressing the left button.

  • Bresenham's Line Algorithm is not necessary any built-in algorithm will do the trick

  • If the user can change the line thickness in any way you get a * 0.8 bonus but it is not obligatory.

  • I guess it should be nicer to implement the line-drawing ourselves, but if you want you can import a library for that just say it in the code description.

  • The minimum is 5 different colours (red,green,blue,white,black). If you make them change randomly you get a penalty of *1.2. You may change them in any way you may want (both buttons and key presses are OK).

  • Drawing them pressing the mouse between to points or freehand would be best (i.e. as you do in paint) and gives you a bonus of *0.7 , but any other method is okay: (example) click two points and draw a line between those points?

  • The drawing canvas has to be 600x400

  • Changing the colour should change the colour only of the lines that will be drawn in the future.

  • Implementing a "Clear All " command is not obligatory but if you implement that you get *0.9 bonus.

\$\endgroup\$
  • 2
    \$\begingroup\$ How are lines required to be drawn? Bresenham's Line Algorithm? Do the lines need to be variable thickness? Do we need to implement the line-drawing ourselves? Please specify more. And it is normally assumed that our code may "import standard libraries". How many colors must be choosable? Is 2 okay? Or how about randomly choosing color every time a keyboard button is pressed? \$\endgroup\$ – Justin Nov 20 '14 at 22:40
  • 2
    \$\begingroup\$ Some more clarifications needed: How are the lines drawn? Do you click two points and draw a line between those points? How big does the drawing canvas have to be? How many colors must be supported? Can changing the color also change the color of every other line? Etc. This challenge is currently very underspecified. \$\endgroup\$ – Doorknob Nov 20 '14 at 22:53
  • \$\begingroup\$ @Quincunx I have put a Q & A in the question tell me if it is ok now. \$\endgroup\$ – Caridorc Nov 21 '14 at 10:28
  • 2
    \$\begingroup\$ 1. Please condense the Q&A. Eliminate the Questions and make the Answers stand on their own as bullet points. Note that comments can sometimes get deleted. The Bresenham's Algorithm Point does not make any sense without reading the comment. I assume what you are saying is that Bresenham's algorithm is not required and any algorithm or standard/library function will do. 2. Ultimately winning depends on in what language it is easy to get into the API and access the Right button (instead of the usual left button.) \$\endgroup\$ – Level River St Nov 21 '14 at 12:24
  • 2
    \$\begingroup\$ 1. "Drawing them pressing the mouse between 2 points is best but any other method is ok" What about freehand drawing like with the pencil tool in paint? I suggest you make it clearer, or eliminate the "any other method is ok" altogether. 2. The method of changing colour should be better specified. For example, can it be done from the keyboard, by rotating through the colours with the other mouse button, or does it have to be by clicking an on-screen pallete? \$\endgroup\$ – Level River St Nov 21 '14 at 14:29
8
\$\begingroup\$

HTML + jQuery + CSS - 507 x (0.7 x 0.8 x 0.9) = 255.528

Not as short as I thought it would be, but I like the result.

Features:

  • Click-and-drag drawing mode. (0.7)
  • Seven colors (black + rainbow).
  • Variable brush width (slider control). (0.8)
  • Clear all function. (0.9)

Live Demo: http://jsfiddle.net/onsLkh8y/9/


HTML - 84 bytes

<input id="r" type="range" min="1" max="9"><canvas id="c" width="600" height="400"/>

CSS - 35 bytes

#c{border:1px solid;cursor:pointer}

jQuery - 388 / 446 bytes

W3C compliant browsers (e.g. Chrome) - 388 bytes

var t=c.getContext('2d');$.each('black0red0orange0yellow0green0blue0purple0clear'.split(0),function(k,v){
$(r).before($('<button>'+v+'</button>').click(function(){k>6?t.clearRect(0,0,600,400):t.strokeStyle=v}))})
$(c).mousedown(function(e){t.lineWidth=$(r).val();t.beginPath();t.moveTo(e.offsetX,e.offsetY)})
.mousemove(function(e){if(e.which==1){t.lineTo(e.offsetX,e.offsetY);t.stroke()}})

Cross-Browser version (fixes for Firefox, Safari, IE) - 446 bytes

var t=c.getContext('2d');$.each('black0red0orange0yellow0green0blue0purple0clear'.split(0),function(k,v){
$(r).before($('<button>'+v+'</button>').click(function(){k>6?t.clearRect(0,0,600,400):t.strokeStyle=v}))})
var d,p=$(c).offset();$(c).mousedown(function(e){d=t.lineWidth=$(r).val();t.beginPath()t.moveTo(e.pageX-p.left,
e.pageY-p.top)}).mousemove(function(e){if(d){t.lineTo(e.pageX-p.left,e.pageY-p.top);t.stroke()}}).mouseup(function(){d=0})

Fixes:

  • FireFox - event.offset[X|Y] are undefined.
  • Safari - event.which and event.buttons are not meaningfully defined on mousemove.
  • Internet Explorer - works with both of the above fixes, although using e.buttons would have been sufficient.
\$\endgroup\$
  • 1
    \$\begingroup\$ $(document).ready in codegolf? \$\endgroup\$ – edc65 Nov 21 '14 at 15:48
  • \$\begingroup\$ you don't need the quotes for id= and maybe others too (haven't done html in a while) \$\endgroup\$ – Cyoce Sep 2 '17 at 6:15
10
\$\begingroup\$

Processing - 93 · 0.9 = 83.7

With next to no overhead for drawing, but a very verbose syntax, in Processing the best score is probably reached without any nice features and only one bonus:

void setup(){
size(600,400);
}
void draw(){
if(mousePressed)line(mouseX,mouseY,pmouseX,pmouseY);
}

Score: 93 · 0.9 = 83.7 (Newlines are for readability only and are not counted in the score.)

However, it's much more fun with all the bonuses in place:

void setup(){
size(600,400);
}
int i,x,y;
void draw(){
stroke(7*i%256,5*i%256,i%256);
strokeWeight(i%9);
if(keyPressed)i++;
if(!mousePressed){x=mouseX;y=mouseY;if(x<0)background(0);}
}
void mouseReleased(){
line(x,y,mouseX,mouseY);
}

Score: 221 · 0.8 · 0.7 · 0.9 = 111.4

It's used like this:

  • Click and drag the mouse to draw a straight line.

  • While clicked, drag the mouse off the left side of the window and release the mouse button to clear the screen.

  • Holding down any key will cycle through the red, green and blue values of the drawing colour and through different stroke thicknesses. Since the cycling periods are different, practically all combinations can be reached (with a bit of trying).

colourful output 1

Edit:

Since freehand drawing gives the 0.7 bonus as well, here is yet another solution:

void setup(){
size(600,400);
}
int i;
void draw(){
stroke(7*i%256,5*i%256,i%256);
strokeWeight(i%9);
if(keyPressed)i++;
if(key>9)background(0);
if(mousePressed)line(mouseX,mouseY,pmouseX,pmouseY);
}

Score: 188 · 0.8 · 0.7 · 0.9 = 94.8

It's used like this:

  • Click and drag to draw freehand lines.

  • Hold the tab key to change the colour and stroke thickness. This can also be done while drawing (see picture).

  • Hit any key but tab and then tab to clear the screen.

colourful output 2

\$\endgroup\$
  • \$\begingroup\$ Freehand also gives you the bonus. \$\endgroup\$ – Caridorc Nov 22 '14 at 19:29
  • \$\begingroup\$ @Caridorc: Ah, great. I will update my answer then. \$\endgroup\$ – Emil Nov 22 '14 at 21:13
  • 2
    \$\begingroup\$ That's going to be hard to beat. \$\endgroup\$ – primo Nov 23 '14 at 9:41
  • \$\begingroup\$ if(key>0) is shorter than if(keyPressed) \$\endgroup\$ – Cows quack Feb 12 '17 at 17:42
9
\$\begingroup\$

Python 2.7 - 339 197 324 * (0.7 * 0.8 * 0.9) = 163

Edit: I discovered pygame can draw lines with variable width so here is an update.

An experiment in using the PyGame modules.

A simple paint program that draws lines from the MOUSEDOWN event (value 5) to the MOUSEUP event (value 6). It uses the pygame.gfxdraw.line() function. Pressing the TAB key will cycle through 8 colours. Pressing the BACKSPACE key will clear the display to a carefully crafted paper white colour. The ENTER key will cycle the brush size through 0-7 pixels in width.

I am new at code-golf so I may have missed some methods of reducing the code size.

import pygame as A,pygame.draw as G
P=A.display
D=P.set_mode((600,400))
C=(0,255)
S=[(r,g,b) for r in C for g in C for b in C]
w=n=1
while n:
 e=A.event.wait()
 t=e.type
 if t==12:n=0
 if t==2:
  if e.key==9:n+=1
  if e.key==13:w+=1
  if e.key==8:D.fill(S[7])
 if t==5:p=e.pos
 if t==6:G.line(D,S[n%8],p,e.pos,w%8)
 P.flip()

Sample picture 1:

Terrible picture of an aircraft

Sample picture 2:

Landscape

\$\endgroup\$
  • 9
    \$\begingroup\$ I now have a file on my computer named ms-paint.py. \$\endgroup\$ – primo Nov 22 '14 at 15:09
  • 1
    \$\begingroup\$ Enjoy the speed and clean GUI. How MS-Paint was meant to be. I hope I don't get sued by a certain large software company... \$\endgroup\$ – Logic Knight Nov 22 '14 at 15:50
5
\$\begingroup\$

C# 519 x 0.7 x 0.8 x 0.9 = 261.6 Using the DrawLine method.

Golfed:

using System;using System.Drawing;using System.Windows.Forms;class f:Form{[STAThread]static void Main(){f F=new f{Width=600,Height=400};Point s=default(Point);sbyte[]c={0,0,0,1};F.MouseDown+=(_,e)=>{s=new Point(e.X,e.Y);};F.MouseUp+=(_,e)=>{F.CreateGraphics().DrawLine(new Pen(Color.FromArgb(255,c[0],c[1],c[2]),c[3]),s.X,s.Y,e.X,e.Y);};F.KeyPress+=(a,e)=>{unchecked{switch(e.KeyChar){case'r':c[0]++;break;case'g':c[1]++;break;case'b':c[2]++;break;case't':c[3]++;break;case'c':F.Invalidate();break;}}};F.ShowDialog();}}

Readable:

using System;
using System.Drawing;
using System.Windows.Forms;

class f : Form
{
    [STAThread]
    static void Main()
    {
        f F = new f { Width = 600, Height = 400 };
        Point s = default(Point);
        sbyte[] c = { 0, 0, 0, 1 };
        F.MouseDown += (_, e) => { s = new Point(e.X, e.Y); };
        F.MouseUp += (_, e) => { F.CreateGraphics().DrawLine(new Pen(Color.FromArgb(255, c[0], c[1], c[2]), c[3]), s.X, s.Y, e.X, e.Y); };
        F.KeyPress += (a, e) =>
        {
            unchecked
            {
                switch (e.KeyChar)
                {
                    case 'r': c[0]++; break;
                    case 'g': c[1]++; break;
                    case 'b': c[2]++; break;
                    case 't': c[3]++; break;
                    case 'c': F.Invalidate();break;
                }

            }
        };
        F.ShowDialog();
    }
}

By holding r, g or b on your keyboard it changes the color of the next line by incrementing an sbyte-array at the corresponding index. It will start at 0 again when overflowing. So this gives us plenty colors. Same goes for thickness of the line which is increased by holding t. Pressing c clears the form.

\$\endgroup\$
5
\$\begingroup\$

Mathematica - 333 x 0.7 x 0.8 x 0.9 = 168

l = {}; c = Black; s = .01;
ColorSetter@Dynamic@c
Dynamic@s~Slider~{0, .02}
Button["Clear", l = {}]
"/" Checkbox@Dynamic@b
EventHandler[
 Dynamic@Graphics@{White, Rectangle@{600, 400}, l},
 {"MouseDown" :> 
   AppendTo[l, p = {}; {c, Thickness@s, Line@Dynamic@p}], 
  "MouseDragged" :> (p = 
     Append[p, MousePosition@"Graphics"][[If[b, {1, -1}, All]]]),
  "MouseUp" :> (l[[-1, 3]] = Line@p)
  }
 ]

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Can this draw lines from point to point? It appears to allow free hand drawing only. \$\endgroup\$ – trichoplax Nov 22 '14 at 12:14
  • \$\begingroup\$ @githubphagocyte Yeah, free hand only at the moment. \$\endgroup\$ – swish Nov 22 '14 at 12:32
  • 1
    \$\begingroup\$ @githubphagocyte Added a straight line option \$\endgroup\$ – swish Nov 22 '14 at 12:47
  • \$\begingroup\$ best answer thus far. \$\endgroup\$ – primo Nov 22 '14 at 14:32
  • \$\begingroup\$ I love the drawing though. \$\endgroup\$ – tomsmeding Nov 22 '14 at 15:46
4
\$\begingroup\$

Tcl/Tk, 252

x 0,8 x 0,7 x 0,9

= 127,008

253 x 0,8 x 0,7 x 0,9= 127,512

254 x 0,8 x 0,7 x 0,9= 128,016

255 x 0,8 x 0,7 x 0,9= 128,52

grid [canvas .c -w 600 -he 400]
set c red
incr t
lmap k {1
B1-Motion
3
MouseWheel
2} s {{set L [.c cr l %x %y %x %y -f $c -w $t]}
{.c coo $L "[.c coo $L] %x %y"}
{set c [tk_chooseColor]}
{if $t|%D>0 {incr t [expr %D/120]}}
{.c de all}} {bind . <$k> $s}

Tcl/Tk, 267

x 0,8 x 0,7 x 0,9

= 134,568

grid [canvas .c -w 600 -he 400]
set c red
set t 0
bind .c <1> {set L [.c cr l %x %y %x %y -f $c -w $t]}
bind .c <B1-Motion> {.c coo $L "[.c coo $L] %x %y"}
bind .c <3> {set c [tk_chooseColor]}
bind .c <MouseWheel> {if $t||%D>0 {incr t [expr %D/120]}}
bind .c <2> {.c de all}

To use it:

  • Left mouse button behaves as question requests
  • The initial color is red. Right mouse shows a dialog which allows the user to choose the color which will be used the next time. Always press OK button, otherwise color will be undefined. I could fix this, but it would consume bytes
  • To adjust the thickness of the line that will be used next time, you can rotate the mouse wheel: Up=thicker, Down=thinner
  • To clear the image press the middle mouse button

A simple test:

enter image description here

\$\endgroup\$
2
\$\begingroup\$

DarkBASIC Pro - 318 x 0.7 x 0.9 = 200.34

The most interesting thing here is using some bitwise logic on the current keyboard scancode to change the color. I use two different bits from the scancode for each channel - so almost any 6-bit color is possible.

  • Hold down any key on your keyboard to use a color (on my American keyboard: White=F5, Black=no key, Red=2, Green=- (minus), Blue=b)
  • Right-click to clear

Here is a compiled EXE: Download

#constant a set current bitmap
set display mode 800,400,32
create bitmap 1,800,400
do
s=scancode()
ink rgb((s&&3)*85,((s/4)&&3)*85,((s>>4)&&3)*85),0
m=mousex()
n=mousey()
o=mouseclick()
if o*(d=0) then d=1:x=m:y=n
a 1
if (o=0)*d then d=0:line x,y,m,n
if o=2 then cls
a 0
cls
copy bitmap 1,0
if d then line x,y,m,n
loop
\$\endgroup\$
1
\$\begingroup\$

BBC BASIC - 141 no bonuses

My first programming language and generally never used by me anymore :)

SYS "SetWindowPos",@hwnd%,0,0,0,600,400,6:VDU 26
1 MOUSE X,Y,b
IF b=4 THEN GOTO 4
GOTO 1
4 MOUSE x,y,b
IF b=0 THEN LINE X,Y,x,y:GOTO 1
GOTO 4
\$\endgroup\$
1
\$\begingroup\$

Python 2.7 - 384 * .8 * .7 = 215.04

from Tkinter import*;o=1
a='0f';C=['#'+r+g+b for r in a for g in a for b in a]
def i(a):global o;o+=1
def d(a):global o;o-=1
def I(a):global u;u+=1
def D(a):global u;u-=1
m=Tk();u=0;c=Canvas(width=600,height=400);c.bind("<B1-Motion>",lambda x:c.create_rectangle((x.x,x.y,x.x+o,x.y+o),fill=C[u],outline=C[u]));m.bind("q",i);m.bind("w",d);m.bind("x",D);m.bind("z",I);c.pack();mainloop()

With all bonuses: 462 * .9 * .8 * .7 = 232.848

from Tkinter import*;o=1
a='0f';C=['#'+r+g+b for r in a for g in a for b in a]
def i(a):global o;o+=1
def d(a):global o;o-=1
def I(a):global u;u+=1
def D(a):global u;u-=1
m=Tk();u=0;c=Canvas(width=600,height=400);c.bind("<B1-Motion>",lambda x:c.create_rectangle((x.x,x.y,x.x+o,x.y+o),fill=C[u],outline=C[u]));m.bind("q",i);m.bind("w",d);m.bind("x",D);m.bind("z",I);m.bind("m",lambda _:c.create_rectangle((0,0,602,402),fill=C[7],outline=C[5]));c.pack();mainloop()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.