创建一个Paint程序!


51

介绍

有一天,您正在向孩子展示如何在计算机上绘画。您mspaint.exe在运行栏中键入。令您惊恐的是,“没有符合您搜索条件的项目”。您必须创建一个简单的绘画版本,以便您的孩子可以绘画!

挑战

您必须创建一个简单的绘图程序。为此,请打开白色显示窗口(大于99x99像素)。每当按下鼠标时,请将鼠标打开的像素更改为黑色。

这是,因此最短答案以字节为单位!


8
是否需要像素?还是99x99的正方形?
fəˈnɛtɪk 17-4-20

2
需要运行多长时间?
Rɪᴋᴇʀ

2
当TI-Basic Pen正是这样做时:o
Timtech '17

1
@Riker它应该至少运行10秒,最好永远运行
pydude

1
大于99×99只是为了每个尺寸我们必须使用三位数的十进制表示法吗?99×100或100×99是否有效?
塞巴斯蒂安·西蒙

Answers:


87

8086机器代码,32 31 28 26字节

00000000  b8 0f 00 cd 10 b8 02 10  ba 18 01 cd 10 b8 03 00  |................|
00000010  cd 33 4b b8 01 0c eb f3  3f 00                    |.3K.....?.|
0000001a

假定存在VGA图形卡和任何Microsoft兼容的鼠标驱动程序。

-2个字节感谢@berendi!

屏幕截图

这个怎么运作:

            |   org 0x100
            |   use16
b8 0f 00    |       mov ax, 0x000f      ; set screen mode: 640x350 monochrome
cd 10       |       int 0x10            ; call video bios
b8 02 10    |       mov ax, 0x1002      ; set palette
ba 18 01    |       mov dx, palette     ; pointer to palette data
cd 10       |   @@: int 0x10            ; call video bios
b8 03 00    |       mov ax, 0x0003      ; get mouse position in (CX, DX) and button status in BL
cd 33       |       int 0x33            ; call mouse driver
4b          |       dec bx              ; if no buttons pressed, --BX = 0xFFFF (invalid page)
b8 01 0c    |       mov ax, 0x0c01      ; plot pixel with color AL at (CX, DX) in page BH
eb f3       |       jmp @b              ; repeat
3f 00       |   palette db 0x3f, 0x00   ; palette in 2:2:2 rgb. color 0 = white, 1 = black.
            |                           ; this should be a 17-byte struct, but we only care about the first two colors here

这里的所有都是它的。不涉及魔术,仅需几个函数调用。


1
干净,清晰和聪明的代码。做得非常好!我看不到有任何可以进一步优化尺寸的地方。出于某种原因,当我使用CuteMouse驱动程序尝试此操作时,无需按住鼠标按钮即可绘制图形,但这可能是由于CuteMouse不与Microsoft 100%兼容的问题。您使用哪个驱动程序进行测试?
科迪·格雷

2
嗯 使用调试器(当然,是旧的DEBUG.COM!)运行代码后,看来CuteMouse驱动程序不是问题。没有按下按钮的情况下,INT 33h将在中返回0 BX,这将按预期减少为FFFFh,但仍在画一条线。也许是因为模式11h仅具有一个视频页面,并且无效的页码会自动得到修复?我正在VM VirtualBox上进行测试,所以也许这是其BIOS实施正在做的事情。
Cody Gray

2
看起来像VirtualBox是在这里惹的祸,它只是完全忽略页码:virtualbox.org/browser/vbox/trunk/src/VBox/Devices/Graphics/...
user5434231

2
比尔·阿特金森本人将为此感到自豪。出色的工作。
Wossname

4
-2个字节删除最后一个int 0x10,取而代之的jmp是第二个int 0x10。偏移量jmp保持不变,请调整mov dx
贝伦迪的

25

暂存,10个暂存字节

Scratch实际上是为这样的事情设计的。

在线尝试!


这实际上是像素吗?另外,如果快速单击鼠标与按住鼠标一会儿,它会产生不同的结果(当然不会移动它)。我认为这无效。
Rɪᴋᴇʀ

19
根据我们当前使用的评分,这不是10个暂存字节。
Okx

2
您可能应该使用暂存器应用程序将其转换为文本或SB2文件大小。
马修·罗

2
我使用的是以前的Scratch答案所使用的评分。有人可以将我链接到当前评分吗?@Okx
dkudriavtsev

8
@Mendeleev我不确定,但他可能是指此Scratch评分系统
FreeAsInBeer '17

20

HTML + JavaScript(ES6),66 64 62字节

的HTML

<canvas id=c>

的JavaScript

onclick=e=>c.getContext`2d`.fillRect(e.x,e.y,1,1)

感谢Gustavo Rodrigues节省了2个字节,Shaggy节省了2个字节。

onclick=e=>c.getContext`2d`.fillRect(e.x,e.y,1,1)
/* This css isn't needed for the program to work. */
*{margin: 0}
#c{border:1px solid black}
<canvas id=c>


怎么<canvas id=c>
古斯塔沃·罗德里格斯

2
实际上,这不是将点放在光标所在的位置,而是放在箭头的右下角。这是故意的吗?
Anoplexian '17

通过c.从JS开头删除来节省2个字节。@Anoplexian,这是将物体margin扔掉几个像素的默认主体。
Shaggy

4
我该如何工作?我在结果区域中单击,但未执行任何操作。
numbermaniac

1
@Anoplexian这是一个已知问题;没有可靠的方法来获取鼠标光标在元素上的相对位置(缺少大型的,特定于浏览器的功能,这些功能在引入新型CSS填充时会失败)。
wizzwizz4

17

C + Win32中,209个 200 195字节

谢谢,科迪和昆汀!我希望摆脱,#include <windows.h>但这会导致各种错误。至少它可以在多台显示器上正常工作...

#include<windows.h> 
struct{int h,m,w,x:16,y:16;}m;h;main(){for(h=CreateWindow("EDIT","",1<<28,0,0,199,199,0,0,0,0);GetMessage(&m,h,0,0);m.m^513?DispatchMessage(&m):SetPixel(GetDC(h),m.x,m.y,0));}

先前的代码:

#include<windows.h> 
main(){MSG m;HWND h;for(h=CreateWindow("EDIT","",1<<28,0,0,199,199,0,0,0,0);GetMessage(&m,h,0,0);m.message^513?DispatchMessage(&m):SetPixel(GetDC(h),LOWORD(m.lParam),HIWORD(m.lParam),0));}

在此处输入图片说明


2
我现在无法测试,但是我认为您可以将的声明合并hfor初始值设定项中以保存两个字节:)
Quentin

我意识到这是代码高尔夫球场和可能需要在这里,但LOWORDHIWORD正确的方法来提取光标从包装的坐标LPARAM。您应该使用GET_X_LPARAMGET_Y_LPARAM,否则在多台显示器上将得到错误的结果。
科迪·格雷

@Quentin,它将在c ++中起作用,但在c中不起作用。我本可以使用c ++,但后来我会写的int main,它将再增加4个字节。
Johan du Toit

@Cody,公平评论。我没有多显示器系统进行测试,但你觉得用(short)LOWORD()(short)HIWORD()会解决这个问题?
Johan du Toit

Quentin提出的建议在任何现代C语言版本(包括C99)中都可以正常工作。当然,您正在使用Microsoft的C编译器,该编译器因其可变变量作用域规则而滞留在C89 / 90中。C89也是为什么允许您省略main函数的返回类型的原因(由于隐式int规则)。唯一的问题是,省略了return 0;C89和MSVC中未定义行为的原因。在C99和C ++中,您需要为的返回类型main,但返回值return 0;是隐式的,因此是不必要的。嗯,这不是打高尔夫球的语言。:-)
Cody Gray

10

处理中,98 79字节

@dzaima节省了19个字节

void setup(){background(-1);}void draw(){if(mousePressed)point(mouseX,mouseY);}

说明(过时)

void setup() {
  size(100,100);            // size of the sketch
  background(-1);           // set the background to white
                            // 1 byte shorter than background(255);
}

void draw(){}               // required for mousePressed to work

void mousePressed() {       // function that is called whenever the mouse is pressed
  point(mouseX, mouseY);    // draw a point at the mouse's coordinates
                            // the colour is set to black as default
}

点击声


@dzaima我不知道size(100,100);不必提及,谢谢!(同样我也不知道为什么我看不到这个if(mousePressed)位)
Kritixi Lithos 17-4-22

7

JavaScript ES6,126个字节

经过镀铬测试。

onclick=e=>document.body.outerHTML+=`<a style=position:fixed;top:${e.y}px;left:${e.x}px;width:1px;height:1px;background:#000>`

在线尝试!

onclick=e=>document.body.outerHTML+=`<a style=position:fixed;top:${e.y}px;left:${e.x}px;width:1px;height:1px;background:#000>`


7

Haskell中,189个 184 170 169字节

import Graphics.Gloss.Interface.Pure.Game
main=play FullScreen white 9[]Pictures(#)(\_->id)
EventKey(MouseButton LeftButton)Down _(x,y)#l=Translate x y(Circle 1):l
_#l=l

这将使用Gloss库(v1.11)。它会打开一个全屏窗口,并通过按鼠标左键绘制黑色像素(实际上是半径为1的圆圈)。按ESC退出。

这个怎么运作:

play                 -- handles the whole event handling, screen update, etc. process
    FullScreen       -- use a full screen window
    white            -- use a white background
    9                -- 9 simulation steps per second (see simulation handler below)
    []               -- the initial world state, an emtpy list of circles
    Pictures         -- a function to turn the world state into a picture.
                     -- The world state is a list of translated circles and
                     -- "Pictures" turns this list into a single picture
    (#)              -- event handler, see below
    (\_->id)         -- simulation step handler. Ignore time tick and return the
                     -- world state unchanged. More readable: "\tick world -> world"

EventKey ... # l=... -- if the left mouse button is pressed, add a circle with
                     -- radius 1 translated to the current position of the mouse
                     -- to the world state
_#l=l                -- on all other events do nothing

编辑:@ceased打开了counterclockwis告诉我有关光泽的最新版本,使用全屏窗口时它可以节省5个字节。谢谢!


FullScreen在光泽度> = 1.11时为零,将分数降低了5。(虽然我遇到了错误unknown GLUT entry glutInit,但是我的过剩设置可能无法正常工作;从未在这台机器上使用过。)

@ceasedtoturncounterclockwis:啊,谢谢你的提示。我的系统上有1.10.2.3,现在更新为最新版本。
nimi

5

SmileBASIC 2,52 51字节

在SmileBASIC的爸爸,佩蒂特电脑这一个运行(并且是一个两字节的短。)

PNLTYPE"OFF
GPAGE 1GCLS 15@A
GPSET TCHX,TCHY
GOTO@A

说明:

PNLTYPE"OFF       'turn off keyboard
GPAGE 1           'set graphics to lower screen
GCLS 15           'clear with color 15 (white)
@A                'loop begin
GPSET TCHX,TCHY   'set black pixel at draw location
GOTO@A            'loop

GPSET TCHX,TCHY:GOTO@A由于默认颜色为0(透明),因此可以节省1个字节。
17Me21年

4

Javascript + jQuery 138字节

d=$(document.body).click((e)=>d.append("<div style='background:black;width:5;height:5;position:fixed;top:"+e.pageY+";left:"+e.pageX+"'>"))

在线查看!

添加单击和拖动支持将很简单,您可以设置一个变量,但是,根据说明并为缩短代码,不支持“每次按下鼠标时,将鼠标打开的像素更改为黑色”。 。我将指令解释为click事件。


3
iya!下次,您应该取消删除旧答案,而不要提出新答案。另外,恐怕它必须在指定的环境中工作-如果这是普通的javascript,则您必须在提交中包括jQuery的字节数。您可以将此提交称为“ JavaScript + jQuery”,这很好:您可以假定已安装jQuery。按照目前的答案,它更像是“ HTML”答案,而不是JavaScript。
Conor O'Brien

1
@ ConorO'Brien我会确保下次再做。我根据您的建议更新了答案。
尼尔,

4

SpecBAS- 61 59字节

1 CLS 15 
2 IF MOUSEBTN=1 THEN PLOT MOUSEx,MOUSEy
3 GO TO 2

黑色已经是默认的笔颜色,但是背景通常是令人讨厌的灰色阴影,因此CLS 15请将其设置为亮白色。

在此处输入图片说明


大多数基本变体在该行的命令号和代码之间不需要空格。
Pavel

SpecBAS会在您返回收益(包括GOTO成为GO TO)后添加所有空格
Brian Brian

1
但是您可以删除空格,并且仍然可以正常运行吗?如果是这样,您就不算在内。
帕维尔

如果用户不介意只用黑色绘画,他为什么会介意用灰色背景?
Cees Timmerman

3

SmileBASIC,70 58 53字节

XSCREEN 4GCLS-1@L
TOUCH OUT,X,Y
GPSET X,Y+240,0GOTO@L

解释:

XSCREEN 4 'display one graphics page on both screens
GCLS -1 'fill screen with white
@L 'loop
TOUCH OUT,X,Y 'get touch location
GPSET X,Y+240,0 'draw black pixel at touch position, offset by the height of the top screen.
GOTO @L 'loop

3

Clojure,91 71字节

-20个字节,感谢@cfrick指出我可以使用它use来缩小导入。

(use 'quil.core)(defsketch P :mouse-dragged #(point(mouse-x)(mouse-y)))

使用Quil库。每当拖动鼠标时绘制一个点。

基本上是处理答案,因为Quil是Clojure的处理包装器。

(q/defsketch P ; Start a new drawing

             :mouse-dragged ; Attach a mouse drag listener
             ; that draws a point at the current mouse location
             #(q/point (q/mouse-x) (q/mouse-y))) 

在此处输入图片说明


71:(use 'quil.core)(defsketch P :mouse-dragged #(point(mouse-x)(mouse-y)))
cfrick

@cfrick大声笑,我总是忘记了,use因为它“ 不合适”。谢谢。
Carcigenicate


2

Java 7,353字节

import java.awt.*;import java.awt.event.*;class M{static int x,y;public static void main(String[]a){Frame f=new Frame(){public void paint(Graphics g){g.drawLine(x,y,x,y);}};f.addMouseListener(new MouseAdapter(){public void mousePressed(MouseEvent e){x=e.getX();y=e.getY();f.repaint(x,y,1,1);}});f.setBackground(Color.WHITE);f.resize(500,500);f.show();}}

取消高尔夫:

import java.awt.*;
import java.awt.event.*;

class M {
    //store the last point
    static int x, y;
    public static void main(String[] a) {
        Frame f = new Frame() {
            @Override
            public void paint(Graphics g) {
                g.drawLine(x, y, x, y);
            }
        }
        f.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                x = e.getX();
                y = e.getY();
                //repaint only the "new pixel"
                f.repaint(x, y, 1, 1);
            }
        });
        //default background is grey
        f.setBackground(Color.WHITE);
        f.resize(500, 500);
        f.show();
    }
}

2

Python2 Python3,82个字节(或77个字节)

from turtle import *;up();onscreenclick(lambda x,y: goto(x,y)or dot(1));mainloop()

使用Turtle模块,这还不错:)

取消高尔夫:

import turtle
turtle.up()

def fun(x, y):
    turtle.goto(x,y)
    turtle.dot(1)

turtle.onscreenclick(fun)
turtle.mainloop()

如果可以在点之间有线,则实际上可以节省5个字节:

from turtle import *;onscreenclick(lambda x,y: goto(x,y)or dot(1));mainloop()

从turtle import *; up(); onclick(lambda * x:goto(* x)或dot(1)); done()
innisfree

那是70个字节
innisfree

2

Excel VBA,62字节

匿名VBE立即窗口功能,允许用户通过简单地选择它就可以在任何图纸上绘制

Cells.RowHeight=48:Do:DoEvents:Selection.Interior.Color=0:Loop

样本输出

在此处输入图片说明


1

HTML + JavaScript中,152个 148字节

<body onclick="document.body.innerHTML+='<x style=position:fixed;width:1;height:1;left:'+event.clientX+';top:'+event.clientY+';background:#000;>'"/>

1

图灵,77字节

var x,y,b:int loop mousewhere(x,y,b)if b=1then drawdot(x,y,1)end if end loop

取消高尔夫:

var x,y,b : int      
loop
  mousewhere(x,y,b)  % Set (x,y) to mouse co-ords, and b to 1 or 0 indicating if the button is pressed
  if b=1 then
    drawdot(x,y,1)  % Draw a black pixel at (x,y)
  end if
end loop

1

HTML + CSS + JavaScript(ES6),8 + 31 + 64 = 103字节

CSS的乐趣box-shadow

s='0 0 0',onclick=e=>p.style.boxShadow=s+=`,${e.x}px ${e.y}px 0`
*{margin:0;width:1px;height:1px
<p id=p>

HTML + CSS + JavaScript(ES6),8 + 22 + 69 = 99字节

此人们试图抵消默认margin的的<body>元素,但它可以是不同的浏览器和用户代理样式表不同。已在Chrome中成功测试。

s='0 0 0',onclick=e=>p.style.boxShadow=s+=`,${e.x-8}px ${e.y-16}px 0`
*{width:1px;height:1px
<p id=p>

HTML + CSS + JavaScript(ES6),8 + 18 + 69 = 95字节

在半像素坐标处绘制时,此像素可能显得更大。

s='0 0 0',onclick=e=>p.style.boxShadow=s+=`,${e.x}px ${e.y}px 0 .5px`
*{margin:0;width:0
<p id=p>


1

TI基本(1字节)

Pt-Change(

我敢肯定,大多数使用TI calcs的人都想到了该Pen命令,但事实证明,它没有标记,因此将其计为3个字节是最有意义的。您可以Pt-Change(http://tibasicdev.wikidot.com/pt-change上了解有关交互式版本的信息。


据我所知,这不能解决挑战:TI calcs无法处理鼠标输入。
Grimmy

2
@Grimy如果您坚持要使用USB鼠标输入,则始终可以使用usb8x库。但是我确信默认的光标导航就足够了。
Timtech

1

Lua(love2d框架),180字节

高尔夫版

l=love v,g,m,p=255,l.graphics,l.mouse,{}d=m.isDown function l.draw()g.setBackgroundColor(v,v,v)if d(1)or d(2)then p[#p+1],p[#p+2]=m.getPosition()end g.setColor(0,0,0)g.points(p)end

不打高尔夫球

l=love 
v,g,m,p=255,l.graphics,l.mouse,{}
d=m.isDown 
function l.draw()
  g.setBackgroundColor(v,v,v)
  if d(1)or d(2)then 
    p[#p+1],p[#p+2]=m.getPosition()
  end 
  g.setColor(0,0,0)
  g.points(p)
end

相当容易。首先进行一些初始化,以简化操作。在它之后,它将检查单击了mous,并将点保存到数组中。之后,它绘制点。还将颜色设置为黑白,原因是默认情况下是这样:)
这是图片:

在此处输入图片说明


1
信不信由你,我来这里是使用Love2d发布答案的,因为我是最近才发现并喜欢它的,所以+1以加倍努力!无论如何,我认为您可以像这样将其缩短一些时间:l=love v,g,m,p=255,l.graphics,l.mouse,{}function l.draw()g.setBackgroundColor(v,v,v)if m.isDown(1)then p[#p+1],p[#p+2]=m.getPosition()end g.setColor(0,0,0)g.points(p)end这将导致169个字节!
DimP

1
我来这里是出于同样的原因,很高兴看到这里还有其他人知道:D谢谢:)
Lycea


1

glslsandbox 232字节

旧帖子,但发现这很有趣。
由于处理已经完成,因此我决定做一些不同的事情。

这将绘制是否按下鼠标,因此不是pydude要求的,而是几乎。

#ifdef GL_ES
precision lowp float;
#endif
uniform float time;uniform vec2 mouse,resolution;uniform sampler2D t;void main(){vec2 f=gl_FragCoord.xy,r=resolution;gl_FragColor=vec4(time<2.||length(f-mouse*r)>2.&&texture2D(t,f/r).x>.1);}

在glslsandbox上尝试


0

处理中,93个字节,如果不计空格,则为91个字节

void setup(){size(100,100);background(-1);}void draw(){if(mousePressed) point(mouseX,mouseY);}

1
在PPCG中,如果未在挑战中提及,则空格和所有内容均视为正常值(作为所选编码中的字节,默认为UTF-8)。因此,您的分数将是92个字节,因为第一个空格不能在不中断程序的情况下被删除,但是第二个空格可以被安全地删除。
dzaima

0

带有wxWidgets的UCBlogo,65个字节

setbg 7
setpc 0
ht
pu
make "buttonact[setpos clickpos pd fd 1 pu]

说明(buttonact每次单击按钮都会执行分配给变量的代码):

SetBackground 7 ; white
SetPenColor 0 ; black
HideTurtle
PenUp
make "buttonact [
  SetPos ClickPos
  PenDown
  Forward 1
  PenUp
]

至少,我认为这可行。它应该根据文档,但是显然buttonact变量只能在wxWidgets构建中工作,而我正在努力在现代Linux上使用wxWidgets构建UCBLogo(wandaamean,您无法int向后投射指针吗?)。

不带wxWidgets的UCBlogo,73个字节

要查看预期的效果,可以使用无限循环运行此较长的版本。

setbg 7 setpc 0 ht pu
while[1=1][setpos mousepos if[button?][pd] fd 1 pu]

但这会ucblogo在我的机器上崩溃...看起来像是在竞争。

UCBlogo,实际上在我的机器上工作,80字节

setbg 7 setpc 0 ht pu
while[1=1][setpos mousepos if[button?][pd] fd 1 pu wait 1]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.