Зеҳн
Алгоритмсозӣ ва барномасозӣ дар забони Go

Китоби таълимии забони Go барои мактабиён, донишҷӯён ва омӯзгорон: аз алгоритм ва блок-схемаҳо то веб-сервер ва боти Телеграм. Таҷдиди китоби А. П. Назаров «Алгоритмсозӣ ва барномасозӣ дар забони Бейсик» (2009).

Агенти Зеҳнӣ · 26 октябри 2026 · 15 саҳифа

МаорифБарномасозӣТехнология
Аз аввал хондан

Боби 11. Графика ва тасвир дар Go

Боби 11. Графика ва тасвир дар Go

Дар китоби кӯҳнаи Бейсик як боби калон ба графика бахшида шуда буд, ки дар он бо ёрии фармонҳои кӯҳнаи экрани DOS (SCREEN 2, LINE, CIRCLE, PAINT) расмҳо кашида мешуданд. Имрӯз он реҷаҳои кӯҳнаи экран дигар дар компютерҳои муосир вуҷуд надоранд. Аммо оё дар забони Go метавон графикҳо ва тасвирҳо сохт? Албатта! Дар ин боб шумо меомӯзед, ки чӣ тавр графикҳои функсияҳои риёзиро дар консол кашед ва чӣ тавр бо истифода аз китобхонаи стандартии Go расмҳои воқеии PNG ва графикҳои вектории SVG-ро ба таври худкор тавлид намоед.

Дар ин боб меомӯзем

  • Сохтани графикҳои матнии функсияҳо дар терминали компютер.
  • Сохтори тасвирҳои рақамӣ: пикселҳо, координатаҳо ва ранги RGBA.
  • Истифодаи бастаҳои стандартии image ва image/png (бе ниёз ба ягон насби иловагӣ!).
  • Алгоритмҳои кашидани хатҳо (алгоритми Брезенҳэм) ва доираҳо дар сатҳи пикселҳо.
  • Офаридани файлҳои воқеии тасвирии .png ва нигоҳ доштани онҳо дар диски компютер.
  • Тавлиди расмҳои вектории SVG барои намоиш дар веб-браузер.

1. Графикаи консолӣ: Кашидани графики функсия дар терминал

Роҳи содатарин ва зудтарин барои дидани рафтори функсияи риёзӣ — ин инъикоси он бо аломатҳо дар худи терминали матнӣ мебошад (мисли §38-и китоби аслӣ).

Биёед параболаи y = x²-ро дар фосилаи аз −4 то 4 тасвир кунем. Барои соддагӣ тири x-ро ба поён (аз сатр ба сатр) ва тири y-ро ба тарафи рост равона мекунем:

package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("Графики функсияи Y = X^2 дар терминал:")
	fmt.Println("---------------------------------------")

	for x := -4; x <= 4; x++ {
		y := x * x // ҳисоби қимати функсия

		// Барои ҳар як воҳиди y як фосила мегузорем ва дар охир ситорача мегузорем
		fosila := strings.Repeat(" ", y)
		fmt.Printf("x = %2d | %s*\n", x, fosila)
	}
}

Агар ин кодро иҷро кунед, дар экран параболае аз ситорачаҳо ҳосил мешавад, ки ба паҳлӯ хобидааст:

Графики функсияи Y = X^2 дар терминал:
---------------------------------------
x = -4 |                 *
x = -3 |          *
x = -2 |     *
x = -1 |  *
x =  0 | *
x =  1 |  *
x =  2 |     *
x =  3 |          *
x =  4 |                 *

2. Эҷоди тасвирҳои воқеии PNG бо бастаи image

Тасвири растрӣ аз тӯри дученакаи нуқтаҳои хурд — пикселҳо — иборат аст. Дар тасвири мо координатаҳои ҳар пиксел чунин муайян мешаванд:

  • X аз чап ба рост (аз 0 то «бар − 1»)
  • Y аз боло ба поён (аз 0 то «баландӣ − 1»)

Ранги ҳар пиксел бо чор адад муайян мешавад: R (сурх), G (сабз), B (кабуд) ва A (ношаффофӣ, alpha: 0 — комилан шаффоф, 255 — комилан ношаффоф). Ҳар як ҷузъ (канал) аз 0 то 255 қимат мегирад.

Забони Go дар китобхонаи стандартии худ бастаҳои олии image, image/color, image/draw ва image/png-ро дорад. Ин маънои онро дорад, ки шумо метавонед бе насб кардани ягон барномаи беруна файлҳои воқеии графикии .png созед!

Барномаи нахустини сохтани файли расм

Биёед расми заминааш сафедро бо андозаи 400 × 400 пиксел созем ва дар он хати моил кашем:

package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"os"
)

func main() {
	pahno := 400
	balandi := 400

	// 1. Сохтани майдони нави холӣ бо ранги RGBA
	rasm := image.NewRGBA(image.Rect(0, 0, pahno, balandi))

	rangiSafed := color.RGBA{R: 255, G: 255, B: 255, A: 255}
	rangiSurx := color.RGBA{R: 220, G: 20, B: 60, A: 255}

	// 2. Ранг кардани тамоми замина бо ранги сафед (бо як фармон)
	draw.Draw(rasm, rasm.Bounds(), &image.Uniform{C: rangiSafed}, image.Point{}, draw.Src)

	// 3. Кашидани хати моили сурх аз (0, 0) то (399, 399)
	for i := 0; i < pahno; i++ {
		rasm.Set(i, i, rangiSurx)
	}

	// 4. Сабти расм ба файли "xatti_surx.png"
	fayl, err := os.Create("xatti_surx.png")
	if err != nil {
		log.Fatal(err)
	}
	defer fayl.Close()

	if err := png.Encode(fayl, rasm); err != nil {
		log.Fatal(err)
	}
}

Пас аз иҷрои фармони go run main.go, дар ҷузвдони шумо файли ҳақиқии xatti_surx.png пайдо мешавад, ки онро метавонед бо ҳар гуна барномаи тамошои расмҳо ё дар браузер боз намоед!

Диққат: Ҳангоми сабти файл хатогиҳоро санҷед: os.Create метавонад аз набудани иҷозат ва png.Encode ҳангоми навиштани додаҳо ноком шаванд. defer fayl.Close() бастани файлро ҳангоми баргаштан аз функсияи ҷорӣ ба нақша мегирад; агар барнома бо os.Exit ё log.Fatal қатъ шавад, defer иҷро намешавад.


3. Алгоритми кашидани хат (LINE): алгоритми Брезенҳэм

Хати моили боло осон буд, зеро ҳар қадам x ва y якбора як воҳид меафзуданд. Аммо чӣ тавр хатро байни ду нуқтаи дилхоҳ (x₀, y₀) ва (x₁, y₁) кашем, вақте ки пикселҳо танҳо координатаҳои бутун доранд? Барои ин алгоритми Брезенҳэм (Bresenham, 1962) истифода мешавад: дар ҳар қадам мо як воҳид пеш меравем ва бо ёрии тағйирёбандаи «хатогӣ» (xato) муайян мекунем, ки оё вақти як пиксел баланд ё паст шудан расидааст. Алгоритм танҳо бо ададҳои бутун кор мекунад ва барои ҳамин хеле тез аст.

package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"os"
)

// abs қимати мутлақи адади бутунро бармегардонад
func abs(n int) int {
	if n < 0 {
		return -n
	}
	return n
}

// xatKashidan хатро аз (x0, y0) то (x1, y1) бо алгоритми Брезенҳэм мекашад
func xatKashidan(img *image.RGBA, x0, y0, x1, y1 int, c color.RGBA) {
	dx := abs(x1 - x0)
	dy := -abs(y1 - y0)
	qadamX, qadamY := 1, 1
	if x0 > x1 {
		qadamX = -1
	}
	if y0 > y1 {
		qadamY = -1
	}
	xato := dx + dy

	for {
		img.Set(x0, y0, c)
		if x0 == x1 && y0 == y1 {
			break
		}
		e2 := 2 * xato
		if e2 >= dy { // вақти қадам дар тири X
			xato += dy
			x0 += qadamX
		}
		if e2 <= dx { // вақти қадам дар тири Y
			xato += dx
			y0 += qadamY
		}
	}
}

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 400, 400))
	draw.Draw(img, img.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)

	kabud := color.RGBA{R: 37, G: 99, B: 235, A: 255}

	// «Ситора»: аз маркази расм 12 хат ба самтҳои гуногун
	nuqtaho := [][2]int{
		{0, 0}, {200, 0}, {399, 0}, {399, 200}, {399, 399}, {200, 399},
		{0, 399}, {0, 200}, {100, 0}, {300, 399}, {0, 300}, {399, 100},
	}
	for _, n := range nuqtaho {
		xatKashidan(img, 200, 200, n[0], n[1], kabud)
	}

	fayl, err := os.Create("xatho.png")
	if err != nil {
		log.Fatal(err)
	}
	defer fayl.Close()

	if err := png.Encode(fayl, img); err != nil {
		log.Fatal(err)
	}
}

4. Алгоритми кашидани доира (CIRCLE)

Акнун алгоритми кашидани доираи пуркардашударо дар сатҳи пикселҳо амалӣ менамоем. Аз геометрия маълум аст, ки муодилаи сарҳади он — давра — чунин аст: (x − x₀)² + (y − y₀)² = R²

Агар масофа аз марказ то нуқтаи (x, y) аз R хурд ё баробар бошад, ин нуқта ба доира тааллуқ дорад:

package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"os"
)

// Функсия барои кашидани доираи пурраранг
func doiraKashidan(img *image.RGBA, x0, y0, r int, c color.RGBA) {
	for x := x0 - r; x <= x0+r; x++ {
		for y := y0 - r; y <= y0+r; y++ {
			dx := x - x0
			dy := y - y0
			if dx*dx+dy*dy <= r*r {
				img.Set(x, y, c)
			}
		}
	}
}

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 500, 500))

	// Заминаи сиёҳ
	siyoh := color.RGBA{0, 0, 0, 255}
	draw.Draw(img, img.Bounds(), &image.Uniform{C: siyoh}, image.Point{}, draw.Src)

	// Се доираи ранга дар марказҳои гуногун
	surx := color.RGBA{255, 60, 60, 255}
	sabz := color.RGBA{60, 255, 60, 255}
	kabud := color.RGBA{60, 100, 255, 255}

	doiraKashidan(img, 250, 180, 80, surx)
	doiraKashidan(img, 180, 300, 80, sabz)
	doiraKashidan(img, 320, 300, 80, kabud)

	f, err := os.Create("doiraho.png")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	if err := png.Encode(f, img); err != nil {
		log.Fatal(err)
	}
}

5. Графикаи вектории SVG бо забони Go

Ба ғайр аз расмҳои пикселӣ (PNG), имрӯз дар саросари интернет SVG (Scalable Vector Graphics) истифода мешавад. Бартарии бузурги SVG дар он аст, ки он матни оддии XML мебошад ва ҳангоми калон кардани андозаи расм сифаташ ҳеҷ гоҳ паст намешавад.

Мо метавонем бо коди ниҳоят содаи Go расмҳои вектории SVG созем:

package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	fayl, err := os.Create("tasvir.svg")
	if err != nil {
		log.Fatal(err)
	}
	defer fayl.Close()

	// Навиштани оғози файли SVG
	fmt.Fprintln(fayl, ``)

	// Заминаи хокистарии равшан
	fmt.Fprintln(fayl, `  `)

	// Доираи зарди офтоб
	fmt.Fprintln(fayl, `  `)

	// Хона: росткунҷаи кабуд ва боми секунҷаи сурх
	fmt.Fprintln(fayl, `  `)
	fmt.Fprintln(fayl, `  `)

	// Анҷоми файли SVG
	if _, err := fmt.Fprintln(fayl, ``); err != nil {
		log.Fatal(err)
	}

	fmt.Println("Файли tasvir.svg офарида шуд! Онро дар браузер кушоед.")
}

Худатон бисанҷед

11–1. Тахтаи шоҳмот: Барномае нависед, ки тахтаи шоҳмоти 8 × 8-ро бо хоначаҳои сиёҳу сафеди навбат ба навбат ҷойгиршуда созад ва ҳамчун файли shohmot.png сабт кунад.

11–2. Графики функсияи синус (y = sin x): Бо ёрии бастаи image ва функсияи xatKashidan графики функсияи синусро дар фосилаи аз 0 то 4π бо хати сабз дар заминаи сиёҳ кашед ва онро ҳамчун sinus.png сабт намоед.

11–3. Парчами Тоҷикистон дар SVG: Бо истифода аз донишҳои гирифтаатон барномае нависед, ки парчами Тоҷикистонро дар шакли файли вектории parcham.svg созад. Парчам се рахи уфуқӣ дорад — сурх, сафед ва сабз — бо таносуби паҳноии 2 : 3 : 2; таносуби бару дарозии парчам 1 : 2 аст. Барои вазифаи мураккабтар дар рахи сафед тоҷ ва ҳафт ситораи тиллоранг кашед.


Хулоса

Дар ин боб шумо дидед, ки чӣ тавр забони Go графикаи компютериро дар сатҳи комилан муосир таъмин мекунад. Шумо аз фармонҳои кӯҳна ва маҳдуди MS-DOS ба тавлиди воқеии тасвирҳои рақамии PNG ва расмҳои вектории SVG гузаштед, алгоритмҳои классикии кашидани хат (Брезенҳэм) ва доираро худатон навиштед ва дидед, ки ин тасвирҳо метавонанд дар ҳама гуна компютер, смартфон ва сомонаҳои интернетӣ бо сифати баланд истифода шаванд.

Дар боби 12 мо аз барномаҳои оддии консолӣ фаротар рафта, лоиҳаҳои воқеиро бо забони Go (веб-серверҳо, REST API, боти Телеграм ва барномаҳои ҳамзамон) меомӯзем.

пешина
аз 15
навбатӣ