Kicsi és hasznos programok C-ben, C programozás tanuláshoz
Egy bizonyos nagyon alap szintre eljutás után, tényleg szeretnék C-ben kicsi és hasznos programokat írni Szandival / tanítani.
Az itt felsorolt dolgok mögötti motiváció, hogy hamar látszódjon eredmény, de legyen "misztikus és elvont".
Szintén motiváció az alábbi videó (már direkt kerestem a témát, úgy találtam rá):
https://www.youtube.com/watch?v=eAhWIO1Ra6M
Mit csinálnak mások (két éver csinálta, de elég pró lett):
https://www.youtube.com/watch?v=lMvFWKHhVZ0
Ötletek (kezdő)
hellomake: Egyszerű C programozási környezet Linuxon
A szokásos kis "hello világ" helyett - amit azért megcsinálunk - rögtön megnézzük, hogy milyen egy minimális makefile-t csinálni!
A helló világ mellé valami számítással kiírjuk azt is, hogy 42 - hogy legyen mit a gdb-vel nézegetni. Esetleg én írom ki és egy kicsit a számábrázolásba is belemegyünk, hogy miért tudott kiírodni, vagy valami bithack-elés stb.
Ezek nem a fő célok, a fő cél a "programozási környezet" beállítása. Ez egy minimalisztikus környezet
Tanulság:
- Terminálból milyen könnyen lehet elkezdeni Linuxon "bármikor" programozni.
- vim minimál ismeret: i, esc, :q, :w, kijelölés + középső gombos beszúrás, :set nu
- git minimál ismeret: git init, git add, git commit, git log, git diff
- makefile minimál ismeret (target-ek, egysoros és egy fájlos esetben)
- release és debug build-ek
- gdb használata, breakpoint-ok, next, step-in, run, quit, "interactive mód"
- ctrl+Z és fg (illetve több program esetén ezek számozott) használata
Továbbfejleszthető:
További alap vim parancsok, mint :tabe, :E, gt, gT, :make, dd, p, :mks! session.vim, vim -S, vim -p, .vimrc, modeline
További alap git parancsok, mint git push, git pull, esetleg egy merge-elés
cfa: Celsius-Fahrenheit átalakító
Továbbfejleszthető:
Másféle átváltások (például inch->cm stb.)
echoback: Visszhang - tehát visszaírja, amit írsz
Standard inputról, az outputra ahogy van. Ez szerintem K&R könyves példa is egyébként.
countparam: Hány karakterből áll az első paramétere a programnak?
A main megkapja a paraméterek számát és ha van, akkor az első paraméter karakterhosszát írjuk ki.
Ha nem adunk paramétert, akkor a program írja ki, hogyan kell használni!
Tanulság:
- Elágazás
- Ciklus
- puts
- char* ábrázolásmód, karakter tömb
- saját megoldás először, majd strlen megmutatása
mindreader: "Kitalálja" milyen számra tippelsz
Atilla küldte... poén...
- Megkéri a user-t, hogy gondoljon egy számra
- Beírja mire gondolt
- Elindul egy "progress bar" és felette írja, hogy "reading brain waves"
- Kiírja mit olvasott ki az agyadból, milyen számra gondoltál
Tanulság:
- Ciklus
- sleep
pulseread: Pulzusmérő
Régi "Bottyános" program:
- Megkéri, hogy tedd az egeret a nyakadra, hogy megmérhesse a pulzusod
- Entert követően random számokat írkál a pulzus tartományban
Továbbfejlesztés:
- Először egy random számot választ, majd ennek a "környezetében" ugrál már csak utána!
Tanulság:
- Random
- Alapok
countit: Karakter számláló program
Karakterek megszámolását csinálja, egyszerűen amit kap std inputon megszámolja hány karakter volt.
Tanulság:
- Ciklus
- Alap standard I/O
countlines: Hány soros a (szöveges) bemenet?
Megszámoljuk a '\n' karaktereket a standard inputon.
Továbbfejlesztés:
Hogy támogassunk más operációs rendszerről érkező fájlokat, a '\r' is számolandó - kivéve, ha egymás után van a \r\n.
Tanulság:
- Ifes elágazás
- Változók, alap nyelvi elemek
- State machine switch/if statement-el
rps: Kő, Papír, Olló
Gép ellen. A játékos beírja hogy mit akar, a gép "random" találja ki.
Extra érdekesség:
* Hackelési tutorial? Csináljuk úgy, hogy a gép előre találja ki - de hackeljük meg, hogy lássuk mit választott!
granitloss: Kiszámolni C kóddal mennyit bukok X év alatt a gránitbank trükkjén
Ugye a megtakarítás / startup hozam számla nem magára emeli a kamatot, hanem átteszi a másik számlára!
Számoljuk ki, hogy X év eltelésével (paraméter) mekkora összegtől esek el a "rendes" kamatos kamathoz képest.
Továbbfejlesztés:
A tranzakciós adó százalékos megadásával kiszámolni, hogy ha mindig átutalom magamnak,
tehát megcsinálom amit ők nem tesznek és kamatos kamat lesz, akkor mennyivel jövök ki kevesebbre úgy?
Tanulság:
- Szöveg számmá alakítása, illetve szám beolvasás
- Milyen gyorsan lehet "hasznos" programot csinálni.
- Alap nyelvi elemek
leicester: Leicester törvénye szimuláció N vs M íjászra
Csak távolsági harcosra pontos a törvény, ezért arra csináljuk meg. Ki kell guglizni a képletet.
traincar: Egyszerű matekjáték
#!/usr/bin/env luajit
local write=io.write
local int,rnd,abs=math.floor,math.random,math.abs
local fmt=string.format
math.randomseed(os.clock()*os.time()^5)
function tab(x) return (" "):rep(x) end
function center(len, str) return tab(.5*(len-#str))..str end
write(center(55, "TRAIN\n"),
center(55, "CHAOTIC COMPUTING HAMBURG, GERMANY\n"),
center(55, "CONVERTED FROM BASIC TO LUA 2018 (CC-ZERO)\n"))
repeat
print("\n\nTIME - SPEED DISTANCE EXERCISE\n")
local c=rnd(25)+40
local d=rnd(15)+5
local t=rnd(19)+20
write(" A CAR TRAVELING ", c, " MPH CAN MAKE A CERTAIN TRIP IN\n",
d, " HOURS LESS THAN A TRAIN TRAVELING AT ", t, " MPH.\n",
"HOW LONG DOES THE TRIP TAKE BY CAR?\n")
local a=tonumber(io.read("*l")) or 0
local v=d*t/(c-t)
local e=int(abs((v-a)*100/a)+.5)
if e<=5 then
write("GOOD! ANSWER WITHIN ", fmt("%.1f", e), " PERCENT.\n")
else
write("SORRY. YOU WERE OFF BY ", fmt("%.1f", e), " PERCENT.\n",
"CORRECT ANSWER IS ", fmt("%.1f", v), " HOURS.\n\n")
end
write("ANOTHER PROBLEM (YES OR NO)? ")
until not io.read("*l"):upper():find("Y")
escape: Játék a terminál escape szekvenciákkal
Lásd:
https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
Például:
#include <stdio.h>
int main(void)
{
int i, j, n;
for (i = 0; i < 11; i++) {
for (j = 0; j < 10; j++) {
n = 10 * i + j;
if (n > 108) break;
printf("\033[%dm %3d\033[m", n, n);
}
printf("\n");
}
return 0;
}
charstat: Melyik betűből hány darab van a szövegben?
Gyűjtsük össze, hogy [a..z] karakterek közül a standard bemeneten, melyikből, mennyi darab van? Amiből egy sem volt, azokat ne is írjuk ki...
Tehát ha ez érkezik a bemeneten:
almafa
Akkor ezt írjuk ki:
a: 3
f: 1
l: 1
m: 1
Megjegyzés:
Csak angol nyelvű betűket elég most kezelni!
Továbbfejlesztés:
Minden látható karakterre terjesszük ki az ASCII-ból (tehát utf8 továbbra sincs - csak byte-ok).
Tanulság:
- ASCII alapok
- Tömb használata
- Algó alapok
- Ifes elágazás
- Alap nyelvi elemek
- Egyszerű struct használat, vagy annak alternatívája
filter: Csak azokat a sorokat írja ki vissza, ami adott szöveggel kezdődik
Lényegében ez olyan, mint a grep, de sokkal egyszerűbb (és amúgy gyorsabb is). Például nagyon hasznos, nagy méretű log fájlokban "keresgélésre".
cat valami.c | ./filter "#include"
#include<stdio.h>
#include<stdlib.h> // used for memcpy
Továbbfejlesztés:
Ne csak a sor kezdetén lehessen a szó, hanem lehessen máshol is "valahol" benne.
Tanulságok:
- readline a K&R C-s könyvben való megvalósításban (vagy akár OS függetlenre csinálva)
- függvények és alprogramok írása (pl. readline)
- string összehasonlítás
- parancssori paraméterek
namefun/havefun: Vicces szavak generálása szópárokból pl. szervernév, játékosnév és egyéb neveknek
Lásd például:
https://github.com/sethblack/funny-words
Alternatíva ("havefun"):
Név lista + tevékenység lista -> ki mit csinál (ezt lehet pajzán adatokkal is feltölteni, esetleg szóhármassal ki-mivel-mit)
guess: Számkitalálós játék
Kitalál a gép random számot 0..N között és log2(N) db próbálgatásból ki kell találni. A gép mondja, hogy a szám kisebb, vagy nagyobb-e mint a tipp.
coolsay: Cowsay-jellegű program
Ami mondjuk valami dobozban megjeleníti a parancssori paraméterként kapott szöveget - esetleg csak "aláhúzza".
Ezt sokáig tovább tudjuk fejleszteni különféle effektekkel / dizájnnal egyébként:
- Csak kiírja a szöveget.
- Csak aláhúzottan kiírja a szöveget
- Körberajzolja megfelelő doboz-rajzoló karakterekkel
- Háromszöget rajzol alá csillagokból (balra zártan)
- Háromszöget rajzol alá középre zártan
- Fentről lefele írja ki a betűket (+körberajzolja megfelelő doboz-rajzoló karakterekkel)
- Szövegfájlban megadható "kép" megjelenítése a szöveg alatt / felett
- Ezek között parancssori paraméterrel tudunk váltani + van egy default.
Tanulság:
- Ciklusok
- Elágazások
- Alap nyelvi elemek, típusok, változók stb.
- függvények
- Parancssori paraméterek
- Fájlkezelés
- Resource kezelés
csizes: Mi a paraméterként kapott alaptípus mérete az én gépemen?
Ez egy kis egyszerű tool, ami lehetővé teszi, hogy megkérdezzük, egy adott alaptípus épp mekkora a saját gépeden. Nyilván elég csak a változó méretű dolgokat kezelni, illetve ami érdekel.
A program a "--help" paraméterre listázza ki mit tud:
./csizes --help
Lets you ask what a specific C basic type size is.
Usage:
------
./csizes int
4
./csizes "unsigned short"
2
Supported types:
----------------
char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
long log
unsigned long long
size_t
float
double
void*
A --help során a supported types listája úgy jöjjön ki, hogy ne legyen "előre beégetve", hanem könnyen karbantarthatóan a valóságot adja ki minden esetben, továbbá könnyű legyen felvenni "új típust" (például void* mellé az int* stb. típust is).
Ahogy a "--help" üzenetből látszik, ha nem ez a segítségkérés a paraméter, akkor a típus maga.
Ha olyat írunk be, ami nem szerepel az "adatbázisban", akkor írjunk hibaüzenetet (stderr-re!) és a program visszatérési értéke is legyen 1 a nulla helyett!
Tanulságok:
- string összehasonlítás (strcmp)
- típusok méretének lekérdezése
- tömb méretének lekérdezése és iterálás
- esetszétválasztás if, else if láncolattal
- default else ágas kezelés
- parancssori paraméterek (pontosabb) megértése
- továbbfejleszthetőségi kérdések és kódszervezés jobb megértése
xo3: Tic-Tac-Toe játék
1v1 két személyre (x és o karakterek jelöljék hova tettünk)
1 2 3
1 x|o| ----- 2 x|x| ----- 3 | |o
Továbbfejlesztés:
AI írása, amely minden lépésre "optimálisan" lép - tehát nem tud veszteni.
ULTRON: A harcolós játék
Eredeti angol szöveg:
I named it ULTRON, this is based on classic attack & defense game.
You and ULTRON have the HP as 100. In this game you have to either ATTACK or DEFENSE in each turn.
Who got zero health loses the match.
In this game, I used these contexts…
When I will choose defense and ULTRON chooses attack, then half of attack point will be added as health to me and vice versa.
If both choose attack then, it will give damage to both.
If both choose defense then, nothing will happen.
Saját kiegészítés:
- Ha 4x DEFENSE-t választottál zsinórban, akkor 25hp-t vesztesz
- A gép "teljesen random" választ, hogy attack vagy defense.
- Azt, hogy mennyi sebzést akarsz bevinni 10, 20, 30, azt paraméterként választod!
Továbbfejlesztés:
Hálózati játék, socket-en keresztül!
basgames(x): Régi basic játékok
https://github.com/silizium/basic_games/tree/master/basic
De checkout-oltam ide a könyvtárba...
bsdgames(y): Régi BSD játékok
https://github.com/vattam/BSDGames
Ötletek (közepesebb)
hama: Hangman játék
Szavak listája adott, random választunk belőle. A szavak listája simán #include-olódik egy fájlból egy tömböt feltölteni...
Aláhúzás jelekkel mutatja a keresendő szót, adott betűkkel tippelhetünk (a-z) mely így megjelenik minden találat helyén. Korlátozott sokszor lehet tippelni.
xo5: Ötödölő játék NxM pályán
Terminálban, mint a tic-tac-toe, de rendes ötödölő, rendes méretű pályán.
Továbbfejlesztés:
Hálózati játék socket-en keresztül!
tor: Battleship
Torpedó játék a terminálban. Amikor a "másik" jön, akkor a képernyőt töröljük le és csak az ő nézőpontját rajzoljuk, de előtte legyen egy gomb, hogy "Player2 köre - kezdhetjük?" vagy hasonló!
Továbbfejlesztés:
Hálózati játék, socket-en keresztül!
peons: "Parasztugrálós sakk"
8x8 sakktáblán játszottuk régen.
A parasztokat két sorba felhelyezzük így:
x x x x
x x x x
A másik játékost mondjuk o-val jelöljük, az üres mezőket pedig mondjuk ponttal. A paraszt át tud ugorni egy, vagy akárhány parasztot "sréhen". Ha ellenfelet ugrunk át, akkor azt levehetjük. Egyébként a parasztok sréhen X irányba mindig léphetnek egyesével is.
Az nyer, akinek marad parasztja. Döntetlen csak akkor van, ha már sok lépés óta nincs semmi ütés és már csak 1-1 figura van.
Továbbfejlesztés:
Valamilyen egyszerű AI írása - esetleg negamax?
cypu: Cyberpunk 2077 hack minigame
Ennek a terminálos változata (stopper nélkül):
https://www.youtube.com/watch?v=ROr1BBqnGoo
https://github.com/spyoungtech/breachman
nsls: Könyvtárban lévő fájlok "természetes" rendezési sorban kiírása
Jelen könyvtárból indulva ki, csak írjuk ki a fájlokat a természetes rendezésük szerint.
Tehát a 10.md később legyen, mint a 5.md
sliderz: "Terminálos powerpoint"
- Clear
- standard inputon megkapott fájl lista (soronként 1db) nyitása a megadott sorrendben
- Enterre a következő "képernyőt" látjuk
Továbbfejlesztés:
N betűre következő, P betűre előző slide - tehát ide-oda visszalépni is lehet
Megjegyzés:
Az előző, természetes rendezéses programmal könnyen össze-pipeolható / össze szkriptelhető,
hogy valamely egész könyvtárat slideshow-zzuk ki!
Tanulságok:
- "Unix filozófia": kis programok egyenkénti összeépítése!
- "Suckless filozófia": Minimalisztikus, de működő és teljes értékű programok!
- Fájlból olvasás
minigraph: Terminálos grafikon rajzoló
A program parancssori paraméterként három számot kap:
./minigraph 50 100 10
Standard inputon ilyen érkezik:
Egy 5
Kettő 10
Három 5
Top 20
Az első szám megadja, hogy milyen széles grafikont rajzoljunk (hány karakter legyen a 100% méretű grafikon) A második szám megadja, hogy a standard inputon érkező számok maximális értéke mi lehet. A harmadik szám azt adja meg, hogy hány karaktert mutassunk a grafikontól balra (kettősponttal és space-ekkel).
A bemenetből a következő kimenet lesz:
Egy: **
Kettő: *****
Három: **
Top: **********
Azért ezt kapjuk, mert:
- Azt mondtuk, hogy 50 karakternyinek fogjuk mutatni a 100%-ot
- A második paraméterben 100-t írtunk, tehát a 100-as érték felel meg a 100%-nak
- Az egy értéke 5 volt. Az 5 az 5%-a a 100-nak. Az 50 karakternek az 5%-al pedig 1/20-ada, azaz 2.5 karakter, ebből lett a 2db '*'
- Hasonlóan a Kettő esetében kijön az öt csillag, hiszen a 10-es érték a 10%-ot jelenti
- Három és Top értékek hasonlóan
Továbbfejlesztés:
Ha az utolsó paraméterünk nulla, akkor neveket ne várjunk, csak rögtön a számokat!
Tehát olyankor az input lehessen ./minigraph 50 100 0 esetén:
5
10
5
20
Amiből ez lesz:
**
*****
**
**********
Ha elhagyja valaki azt a paramétert, akkor alapból is ez legyen + írhatnánk '--help' támogatást is!
Tanulságok:
- Szám beolvasás parancssori paraméterből és standard bemenetről - ezek különbségei
- Lebegőpontos matekozás és konvertálás
- "Left pad" ellentéte: lényegében "right pad" programozzuk le
- Unix filozófia: a sliderz programhoz jól használható kis grafikon generáló...
sym: Kis-közepes méretű szimulációk
Társadalmi szimulációk, aktor-szerű dolgok - ezekről amúgy is akartam youtube-ozni...
Például:
- Helyben maradók hatása a gazdaságra vs. individualizmus
- Demokrácia skálázódása szimuláció
- Lakosság hullámvölgyek szimuláció (ha tegyük fel növekszik a gyermekvállalási arány, meddig lesz még csökkenő népesség a völgyben)
- stb.
gol: Game of life a terminálban
Életjáték - akár "magától" futva (sleep) egy random kiindulási pontból a képernyőn.
Továbbfejlesztés:
Például szövegfájlból beolvasható
ntree: Könyvtárfa kirajzolása terminálban (tabulátorral indentálva)
Ilyesmi kimenetetet csinálva:
/prenex
/munka
/c_c++
/youtube
...
/Downloads
alma.txt
...
...
Lényegében a "tree" parancs újraírása.
gntree: Könyvtárfa kirajzolása graphviz-el
Az adott könyvtár fáját grafikusan kirajzolja (alkönyvtárakkal) - ez jó gyakorlás rekurzióra is pl.
Továbbfejlesztés:
Teszünk köré shell scriptet, ami graphviz-el együtt futtatja
Továbbfejlesztés:
Mutatja rajta, hogy melyik alkönyvtár hány byte-os (esetleg ez parancssori paraméter, hogy mutassa-e)
cingraph: C (és C++) programok függőségi fájának kirajzolása graphviz-el
- Végigolvasni a bemenetként megadott fájlt
- Megkeresni benne a "#include"-okat
- Azokat rekurzívan lekövetni
- Kimeneti gráfot graphviz szövegként kiadni
Továbbfejlesztés:
Teszünk köré shell scriptet, ami graphviz-el együtt futtatja
polcal: Lengyelformás számológép
Ilyenek kiszámítása:
8 4 + 10 * 2 /
> 60
Ha stack overflow van, akkor hibajelzés kell. Az int számokat tároló stack külön .c és .h fájlban legyen A makefile-t csináljuk meg úgy, hogy build-elje az egészet!
Továbbfejlesztés:
Header-only és single-header VS. több fájlos megoldásokról beszélni pár szót
Tanulságok:
- stack / verem adatszerkezet tömbös ábrázolással
- Külön fájlba szervezés
- Makefile függőség kezelés megismerése (kézzel kiírás egyszerűbben VS. függőséges módon kiírás - inkrementális fordítás)
- Lengyelforma előnyei, működése
minilogo: Mini comlogo nyelv és futtató terminálban
Standard inputon kér bemenetet a program, clear után a terminal képernyőn rajzol (ncurses).
Minden "parancs" egy sor
- Csak jobbra-balra-fel-le lépések, esetleg ezeknek "hányszor csináljuk" változatai: fel, afel, le, ble, jobb, cjobb, bal, dbal
- toll,radir,repul szavak arra, hogy csillagokat rajzolunk-e, amin átmegyünk space-el töröljük-e, vagy csak kurzor mozgatás
- A változók egybetűsek, csak számok. Így lehet megadni őket: a:5, b:42; Minden változó GLOBÁLIS.
- A műveletek csak kétváltozósak: a=a+1, b=b*a; ha ez nem elég, akkor több sorban kell leírni!
Továbbfejlesztés:
Alprogramok: Ezekeket "def <nev>" kezdettel, az "end"-ig írhatunk.
Ezt követően a "$nev" kezdi futtatni az alprogramot.
Tanulságok:
- Lényegében mini saját programnyelv interpreter!!!
- Dolgok logikai strukturálása
topol: Lengyelformára hozás (Shunting yard)
A program standard inputon megadott bemenetet vár és átalakítja lengyelformára amit kiír a kimenetre.
Megjegyzés:
A lengyelformás programmal együtt kész is van a kis számológépünk!
Tanulságok:
- Shunting yard algoritmus
- "Unix filozófia": kis programok egyenkénti összeépítése!
infect: Vírus infekciós játék
Ez a játék azt próbálja szimulálni, ahogy egy "vírus" terjed, melynek terjedését akadályozni szeretnénk.
Ez egy körönként játszódó játék 10x10-es pályán, ahol a '@' jelzi a vírust, a space a "sima teret" és a '#' karakter a "karantén" mezőket amiket felhúzunk.
Szabályok:
- Három darab kezdeti vírusgóc van (három mező vírusos kezdetben valahol random helyen)
- A köröket számoljuk és ez vizuálisan látszik
- A páros körben a vírusmezők mellett jobbra-balra lévők is "fertőződnek" (az összes)
- A páratlan körben a vírusmezők alatt-felett lévők fertőződnek (az összes)
- A játékos minden körben egy X, vagy kereszt alakú karantént tud letenni
X-alakú karantén:
. .
.
. .
Kereszt-alakú karantén:
.
...
.
A karanténokat az 1..8 koordinátákra lehet csak helyezni, ha valamely mező korábban vírusos volt, az megszűnik.
Játéktábla például:
0|@.
1|...
2| .
3| @
4| @@
5| @
6| . .
7| @.
8|@.@.
9| @
----------
0123456789
1
A '@' a vírust jelenti, a '.' a karantén-mezőt, amin a vírus nem tud átszaporodni.
Ez a játéktábla két lépés után lehetséges például: Kezdeti víruspozíciók (0,0); (1,8); (9,4) voltak. A bal felső sarokban lévő vírusmezőt már hatástalanítottuk, tehát az nem tud tovább terjedni.
A játék akkor ér véget, ha a vírusok nem tudnak már további területet fertőzni - akár elszigetelés, akár végigfertőzés miatt!
Pontszám: Milyen hamar sikerült megállítani a vírust? (lépések száma)
Érdekesség: Ha egy gócot megfékezünk, de a többit nem sikerül, lehet hogy rosszabb score lesz, mintha azt is hagyjuk!
Továbbfejlesztés:
- Nagyobb pályák lehetősége (lásd aknakereső játék)
- "Kötelezően megvédendő" helyek (mondjuk X a térképen)
mine: Aknakereső játék
A windows-os aknakereső kisebb, terminálos változata.
- 10x10-es grid, esetleg NxN grid (továbbfejlesztés)
- Lépés előtti kérdés: "akció? [(M)ark, (S)tep, (Q)uit]"
- Utána "kattintás" helyett az oszlop és sor "számát" (256-osnál: hexa byte) kell megadni hol nézel aknát.
- Ha van akna a szomszédos mezőkön, akkor az aknák számát kell megmutatni
- Ha nincs, akkor "flood-fill"-ezni addig amíg olyanhoz nem érünk, ami szomszédos már aknával (onnan nincs tovább rekurzió)
- A "flood-filles" mezők '.' karakterrel jelölik hogy hol tuti nincs akna. Az 'm' jelöli a mi saját jelölésünk.
Játéktábla például:
0|...3
1|..1
2|1.1
3| 2
4|
5|
6| m1
7|m21..
8|1....
9|......
--------------------
01234567890123456789
1 2
Ezzel a kialakítással megoldható tehát, hogy space-ek nélkül írjunk ki több mint 10 oszlopot rendesen címezhetően.
Továbbfejlesztés:
- Eleve továbbfejlesztés, ha nem csak 10x10-es a játék
- Esetleg rajzoljuk ki a "vonalakat" táblázat-szerűen az oszlopok és sorok közt, hogy könnyebben áttekinthető legyen
beast: Szörnyes tili-toli játék karakteres módban
A long time ago, on a 286 computer, we had this game called beast. The game took place on one screen, each position on the page was a character (which was common back then). You had a maze of walls that the player couldn’t walk through, but that you could push. By pushing, you could build corridors and lay traps for the beasts, which were animals that walked around the level semi-randomly, and killed you if you touched them.
You could only kill beasts by crushing them between two pieces of walls. The game is very easy to make in technical terms, but lead to interesting emergent gameplay because you had to be creative to lay traps for the beasts and spring them at the right time. It’s a little more complicated than what Alex Myczko proposed, but worth a try I think! I’ve always been meaning to replicate this game sometime, but never got around to it.
Of course, some other common examples are: Tic Tac Toe, Snake
Snake: Standard kígyós játék
Almákat fogyasztva egyre hosszabb a kígyó mérete. Ha elérsz X méretet nyersz.
Tanulságok:
- Double-ended queue / circular buffer adatszerkezet (max méretre)
- ncurses programozás
adv: Szöveges kalandjáték(ok)
Vannak egyszavas parancsok (lookaround, backpack) és parancs paraméter kétszavas jellegűek (pl. go north, pickup axe, use axe)
Igazából "szobák" vannak, melyek másik szobákkal kapcsolódhatnak (pl. adott irányokban), ezek között a go parancs visz.
A szoba meg kell tudja adni, hogy:
- Mik vannak benne (csak szó felsorolás - yellowkey, axe, armor) és felszedhetők-e
- Milyen szobákba lehet rajta keresztül eljutni (és melyik irányba)
- A "use" műveletre mi történik?
Szabályok:
- Igazából a go és use műveletek nagyon hasonlóak és mindkettő csak egy "másik szobába" vezet.
- Tehát ha használjuk a kulcsot, akkor például olyan szobába, ami a mostanivan azonos, de még egy irány lett!
- A use egyszerre használhatja a szobákban lévő tárgyakat, vagy a nálunk lévőket.
- A pickup a szobából felszedi az adott dolgot (ha felszedhető)
- A use esetén az adott tárgy "eltűnik" a dolgaink közül
A 'use' helyett az engine elfogad még:
- touch
- apply
Megvalósítás:
- Szerintem egy "szoba" legyen egy függvény pointer.
- Valami kis "engine-szerűség" kell: A függvény kap: backpack pointert, parancs-típust (lookaround, go, pickup, use), paramétert.
- A függvény visszatérési értéke lehet új szobába lépésnél egy új függvény pointer (vagy NULL, ha szobában maradunk).
- A backpack használata a backpack-et paraméterül váró függvényekkel lehetséges
A backpack "használata" (függvények, melyek első paramétere "backpack*"):
bool backpack_has(const char *thing);
void backpack_add(const char *thing);
Egy példa térkép:
enum Command {LOOKAROUND, GO, PICKUP, USE};
typedef void*(*Room)(struct backpack_data *backpack, Command command, const char *param);
void *hallway2(struct backpack_data *backpack, Command command, const char *param);
void *winroom(struct backpack_data *backpack, Command command, const char *param) {
switch(command) {
case LOOKAROUND:
puts("You have entered the secret room, use the lever to win the game or go back to hallway!');
return NULL;
case GO:
if(param && (strcmp(param, "hallway") == 0)) {
return hallway2;
}
return NULL;
case USE:
if(param && (strcmp(param, "lever") == 0)) {
puts("Thank you for completing the game!");
exit(0);
}
return NULL;
default:
puts("Sorry Dave, I Cannot do that!");
return NULL;
}
}
void *hallway2(struct backpack_data *backpack, Command command, const char *param) {
switch(command) {
case LOOKAROUND:
puts("You have entered the hallway, there is an opened door in this room.');
return NULL;
case GO:
if(param && (strcmp(param, "door") == 0)) {
return winroom;
}
return NULL;
default:
puts("Sorry Dave, I Cannot do that!");
return NULL;
}
}
void *hallway(struct backpack_data *backpack, Command command, const char *param) {
switch(command) {
case LOOKAROUND:
puts("You have entered the hallway, there is a key on the floor and a door in this room.');
return NULL;
case PICKUP:
if(param && (strcmp(param, "key") == 0)) {
backpack_add("key");
}
return NULL;
case USE:
if(param && (strcmp(param, "key") == 0) && backpack_has("key")) {
return hallway2;
}
return NULL;
default:
puts("Sorry Dave, I Cannot do that!");
return NULL;
}
}
Ezt követően így lehetne játszani vele:
#include "textengine.h
#include "map.h"
int main() {
backpack_init("flashlight", "matches");
return start(hallway);
}
Egy jó példa map lehetne:
https://en.wikipedia.org/wiki/River_crossing_puzzle
Megj.: Nyilván az engine része kéne legyen a typedef és az enum, de ezt most hagyjuk.
crappy: Flappy bird klón
Ez tényleg egy jó kis minimál projekt, lásd tiny games könyvtár
Tanulsádok:
SDL
stb_image
egyszerű grafikus programozás
Továbbfejlesztés:
Hangok hozzáadása
memory: Egyszerű memória-játék
A megadott könyvtárban lévő 4:3-as képekből állítja elő a "kártyákat"
Tanulságok:
stb_image
egérkezelés
SDL, vagy megfelelő dolgok