Forums (
-   Programming (
-   -   Guesst's Programs (

guesst 03-06-2006 06:10 PM (hey, you come up with a better name then...)
The game in my sig, as I said, is a smaller, stripped down version of a bigger program. The code has been formated in a less readable format so it fits in as few lines as possible. I actually made 2 version of this. The other version is 7 lines, has better looking graphics, but only 1 solution. However, this actually makes a better intro game, so I'll post it here:

#define z printf
#define L(a,b) for(c=a;c<a+3;c++)z(x[b*!!(d&1<<c)],c+1)
#define R(a) z("\n\n\t");L(a,1);z("\n\t");L(a,2);z("\n\t");L(a,1)
char *x[]={"**... "," +===+"," | %d |"},n;int d,m[]={27,7,54,73,186,292,216,448,
432};p(){int c;R(6);R(3);R(0);}main() {srand (time(0));d=1+rand ()%511;p();do{z(
"\n\t\tmove ? ");do n=getche ()-'1';while(n<0||n>8);if(d&1<<n)d^=m[n];p();}while

This 7 line version, when you load and run it looks like this:

**********...** ...** ...
**********...** ...** ...
**********...** ...** ...

******** +===+**...**+===+
******** | 4 |**...**| 6 |
******** +===+**...**+===+

**********...** ...**+===+
**********...** ...**| 3 |
**********...** ...**+===+
****************move ?

The avaible buttons to press are represented, with a number in the middle, and the non available ones with dots. Start pressing buttons and the board will change. You win when it looks like:

******** +===+ +===+ +===+
******** | 7 | | 8 | | 9 |
******** +===+ +===+ +===+

******** +===+**...**+===+
******** | 4 |**...**| 6 |
******** +===+**...**+===+

******** +===+ +===+ +===+
******** | 1 | | 2 | | 3 |
******** +===+ +===+ +===+


Easy, huh?

Well, the 5 line version below looks a bit different but plays similarly. I'll repost the code here incase I change my sig:

int n,d[2],m[9]={27,7,54,73,186,292,216,448,432};p(){int c=6,k=0;puts("");for(;c
>=0;){putchar((d[k]&1<<c)?k?'*':'1'+c:'.');if (++c%3)continue;putchar(' ');c-=3;
()%512;p();for(;*d&&((*d-d[1])?1:puts("Goal!"));){printf("move?");do n=getche ()

When you run it you'll see:

789 *..
..6 **.
.23 ..*

Alot of prettyness goes with those 2 lines. However, I was able to make the goals different every time. In this version the 3x3 on the left are your buttons, and the 3x3 on the right is your goal. So in this case you don't win until you see

7.. *..
45. **.
..3 ..*

Some goals are more challanging than others, but there is a fantastic sense of accomplishment that goes along with working a solution backwards like this.

So there you go, an explination of my sig and a teaser for future programs to come. Feedback is welcome and if you all like it I'll post more of my super-cool C programs.

For anyone who wants a more readable version of the game, here it is:

/* Buttons
 * by Joseph Larson

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

#define L(a,b) for (c = a; c < a + 3; c++) printf(gfx[b * !!(bd & 1 << c)], c+1)
#define R(a) printf ("\t");L(a,1);printf ("\n\t");L(a,2);printf ("\n\t");L(a,1)
#define D(a) ".O"[!!(goal[lv] & 1 << a)]
#define NUMGOAL 8

char *gfx[] = { "**... ", " +===+", " | %d |"};
int bd, lv, won, won_mask,
move[] = {0x001b, 0x0007, 0x0036, 0x0049, 0x00ba, 0x0124, 0x00d8, 0x01c0, 0x01b0}
,goal[] = {0x01ef, 0x0010, 0x0054, 0x01d2, 0x004F, 0x001b, 0x0145, 0x0000};
/* O, ., \, T, L, square, corners, blank */

void show_buttons (void) {
**int c;
**printf ("\n\n");
**R(6); printf ("\tGoal:\n\n\t");
**L(3, 1); printf ("\t %c%c%c\n\t", D(6), D(7), D(8));
**L(3, 2); printf ("\t %c%c%c\n\t", D(3), D(4), D(5));
**L(3, 1); printf ("\t %c%c%c\n\n", D(0), D(1), D(2));

void puzzle (void) {
**char in;
**do lv = rand() % NUMGOAL; while (won_mask & 1 << lv);
**bd = rand () % 0x01FE + 1;
**do {
****show_buttons ();
****printf ("\n\n\t\tmove ? ");
****do in = getchar (); while (in < '0' || in > '9');
****if (in -= '0')
******if (bd & 1 << in - 1) bd ^= move [in - 1];
******else puts ("Invalad. That button is not up.");
**} while (bd && bd != goal[lv] && in);
**if (bd == goal[lv]) {
******show_buttons ();
****puts ("\n\n\t\tGoal!!!");
****won_mask |= 1 << lv;
**} else if (!bd) {
****show_buttons ();
****puts ("\n\n\tYou have no more moves.");

int want_more (void) {
**char yn;
**if (won < NUMGOAL) {
****printf ("\nDo you want to try another one? (y/n)");
****do yn = getchar (); while (tolower (yn) != 'y' && tolower (yn) != 'n');
****return tolower (yn) == 'y';
**} else puts ("Congratulations! You've solved all the puzzles!\n\n"
****"You are a master button pusher.\n\nThanks for playing.");
**return 0;

int main (void) {
**won_mask = won = 0;
**srand (time (NULL));
**puts ("Buttons\n-------\n"
**"Try to make the field of buttons look like the goal. You can press any\n"
**"button that is up by typing the number on the button, but when you press\n"
**"a button other buttons around it will change. Each button always changes\n"
**"the same buttons around it.\n"
**"Type zero ('0') as your move to quit\n"
**"There are several goals to accomplish. Try to get them all!\n\n"
**"Press ENTER to start...");
**getchar ();
**do puzzle (); while (want_more ());
**puts ("Good bye!");
**exit (0);

Note, if you take the line:

**bd = rand () % 0x01FE + 1;
And add this to the end:

**bd = rand () % 0x01FE + 1; goal[lv] = rand () % 0x01FF;
you will always have random boards to finish. Do this when the set of winning boards gets to boring.

Data 05-06-2006 11:12 AM

Please post a few more.

Did you try to optmize your programs for speed as well or merely fo as small as possibl ?
You don't mention the header files that are needed and getche isn't available at my place.

guesst 05-06-2006 04:21 PM

<div class='quotetop'>QUOTE(Data @ Jun 5 2006, 10:12 AM) [snapback]234432[/snapback]</div>

Please post a few more.

Did you try to optmize your programs for speed as well or merely fo as small as possibl ?
You don't mention the header files that are needed and getche isn't available at my place.
Ah, a responce. I wans't going to post any more without them.

Header files are unnecessary. everything is kept in the single file. just be sure to name it with a .c instead of .cpp and every complier I've used can handle it. (Even M$, although I've only complied in a windows environment. If your complier is different, let me know.)

As for getche(), that is a non-standard function. But all of my programs are designed so that getche () can be replaced with the ANSI standard getchar() and (1) still funciton and (2) not consume any more space. (I leave a space after getche_ for the extra letter in getchar every time.)

No, my programs are not optimized for speed. For programs as small as this that's kind of silly. Besides, I'm not very good at optimizing for speed.

more programs to come...

guesst 05-06-2006 09:14 PM

So, which one to continue with? I'll start with a small one and move on to a somewhat bigger one, then let you all choose.

Jumping Balls (please hold back the grade school snickering)

What inspired this little programming spree was when I found a couple of old books of BASIC programs that I would read in High School. Of course, by High School BASIC was a thing of the past, so all I could do was read the programs an imagine how cool it'd be to play them.

So when I found the entire text of both books online years later I decided that I would like to finally see these programs run. Only, instead of whipping out gwBASIC (or whatever) I'd convert the programs in it to C!

One of these programs I found such a suscinct way of expressing in C that I decided to see if it would fit in a sig. It did, and in 3 lines no less:

main(){char b[11]="\toooo.OOOO";int e=5,n,t=0;puts("\t123456789");puts(b);for(;n
==2||abs(n-e)==1)){b[e]=b[n];b[n]='.';e=n;t++;}}}if(n)printf("\n%d moves\n",t);}

This is a simple game of solitare. You start with 4 little 'o's on the left and 4 big 'O's on the right with an empty sopt (.) in the middle. The game is over when the order is reversed. To move you just choose an piece that can either move once into the empty piece, or jump over another piece into the empty space.

In a a perfect game you can win in 24 moves. How well can you do?

Below is the full, more readable, and longer more compelte version

/* Jumping Balls
 * By Joseph Larson
 * Inspired by a BASIC game of the same name by Anthony Rizzolo
 * as found in 'More BASIC Computer Games' edited by David H. Ahl (c) 1979

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

int main (void) {
**char yn, b[10], *start = "XXXX.OOOO", *end = "OOOO.XXXX";
**int empty, input, t;
**puts ("Jumping Balls\n------- -----\n"
**"This is a game of solitare. It is played with 8 balls in 9 holes. The X's\n"
**"and O's are the balls in this game and the period ('.') is the empty hole.\n"
**"The object is to get all the X's and O's to switch sides. You can move by\n"
**"either moving a ball into the empty space or jumping one ball over another\n"
**"into the empty space.\n\n"
**"On your turn input the number from the left of the space of the ball you\n"
**"want to move or jump into the empty space.\n\n"
**"If you want to quit input '0' as your move.\n\n"
**"Press ENTER to start...");
**getchar ();
**do {
****empty = 4; t = 0; strcpy (b, start);
****puts ("\t123456789");
****printf ("\t%s\t? ", b); scanf ("%d", &input);
****while (input && strcmp (b, end)) {
******if (input--) {
********if (input >= 0 && input < 9 &&
**********(abs (input - empty) == 2 || abs (input - empty) == 1)) {
**********b[empty] = b[input]; b[input] = '.'; empty = input; t ++;
********} else puts ("Invalad move.");
******printf ("\t%s\t? ", b); if (strcmp (b, end)) scanf ("%d", &input);
****if (!strcmp (b, end))
******printf ("\nCongratulations! You solved it in %d moves!\n\n"
******"Do you want to try for a better score? (y/n) ", t);
****else printf ("Do you want to start again ? (y/n) ");
****do yn = getchar (); while (!isalpha (yn));
**} while (tolower (yn) != 'n');
**puts ("Thanks for playing!");
**exit (0);

Eagg 09-06-2006 01:03 AM

Interesting how compact source code can be, even though I have a different view about what "minimal" source code is.
What I would like to know is how long it would take you to complete such a transformation on code that you have not seen before?

guesst 09-06-2006 04:10 AM

<div class='quotetop'>QUOTE(Eagg @ Jun 9 2006, 12:03 AM) [snapback]235363[/snapback]</div>

Interesting how compact source code can be, even though I have a different view about what "minimal" source code is.
What I would like to know is how long it would take you to complete such a transformation on code that you have not seen before?
Me? It would depend on the complexity of the code, I suppose. I'm not about to boast about my mad hackor skills. Minimilizing the code consists of using single character variables for starts, clearing out excessive spaces and line feeds, and then fiddling with the actual way that the code does what it does, identifying and trimming non-necessary code (like the sort of "good coding" practice like freeing memory and the like that the OS usually handles if you don't) and occasionally restructuring whole parts around a new paradgm that may involve just plain rewriting whole segments, which is the hard part, especally if you're not intimitely aquainted with what the code does and how it does it. In the end, the scaled down version may bear resemblance to the original verison in execution time only.

Which is a perfect segway into the next program.
Robot Escape
The instructions are in the game, so just read down a few lines to see them:

/* Robot Escape
 * by Joseph Larson 2005

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

#define W 77
#define H 21
#define MAX_LOC**W * H
#define SQ(a) (a) * (a)

typedef struct {int loc, type;} STUFF;

STUFF **p;
int numobj;
char msg[W], icons[4] = {' ', '#', 'O', '+'};

void intro (void) {
**printf ("Robot Escape\n------------\n"
**"You are being chased by robots. Fortunately you have two advantages. First,\n"
**"your pursures aren't very smart. Second, you have a teleport-a-matic at\n"
**"your command should you need it.\n\n"
**"The robots will take the most direct route to you, even if it means running\n"
**"into another robot. When two robots crash they make a debris heap that you\n"
**"can crash other robots into. When all robots are destroyed you win and go\n"
**"on to the next level. Try to make it to level 10!\n\n"
**"If you have to use your teleport-a-matic remember that it might teleport\n"
**"you into your enemies, so use it sparingly.\n\n"
**"You move using the number keys. (Be sure num-lock is on) Use the 5 key if\n"
**"you don't want to move for a turn. Use the 0 key to turn on your\n"
**"teleport-a-matic. And if you don't need to move for the rest of the level\n"
**"type a period ('.') for your move. Otherwise 8 is up, 2 is down, 4 is left\n"
**"and 6 is right and the corner keys are diagonal.\n\n"
**"\nGood luck! Press any the ENTER key start.\n\n");
**getchar ();

int setup (int lv) {
**int n, numleft;

**numobj = numleft = 3 + lv * 4;
**p = malloc ((numobj + 1) * sizeof (STUFF *));
**n = rand () % numleft;
**while (numleft >= 0) {
****p[numleft] = malloc (sizeof (STUFF));
****p[numleft]->loc = (numleft - numobj) ?
******numleft * (MAX_LOC / numobj) + rand() % (MAX_LOC / numobj) : MAX_LOC + W;
****p[numleft]->type = (n != numleft--) + 2;
**return n;

void takedown (void) {
**int n;

**for (n = 0; n < numobj; n++) free (p[n]);
**free (p);

int draw_floor (int l) {
**int c, d, n, s = 1;
**STUFF *temp;

**putchar ('\n'); puts (msg);
**putchar ('-'); for (c = W; c; c--) putchar ('-');
**for (d = 0; d <= numobj; d++) {
****for (n = numobj; d < numobj && n > d; n--)
******if (p[n]->loc < p[n - 1]->loc) {
********temp = p[n]; p[n] = p[n - 1]; p[n - 1] = temp;
****if (d) {
******if (p[d]->loc == p[d - 1]->loc) {p[d]->type = p[d - 1]->type = 1;}
******else do {
********if (!(c % W)) printf ("|\n|");
********putchar (icons[(p[d - 1]->loc == c) ? p[d - 1]->type : 0]);
******} while (++c < p[d]->loc && c < MAX_LOC);
******if (p[d - 1]->type == 3) s = 0;
**printf ("|\n|"); for (c = W; c; c--) putchar ('-'); printf ("-\n");
**sprintf (msg, "Level %d", l);
**return s;

void gorobo (STUFF *pl) {
**int n;

**for (n = 0; n < numobj; n++) if (p[n]->type == 3) {
****if ((p[n]->loc % W) > (pl->loc % W)) p[n]->loc -= 1;
**else if ((p[n]->loc % W) < (pl->loc % W)) p[n]->loc += 1;
****if ((p[n]->loc / W) > (pl->loc / W)) p[n]->loc -= W;
**else if ((p[n]->loc / W) < (pl->loc / W)) p[n]->loc += W;

int main (int argc, char *argv[]) {
**int n, m, w, level, d[9];
**char in;
**STUFF *pl;

**srand (time (NULL));
**intro ();
**for (n = 0; n < 9; n++) d[n] = W * (1 - n / 3) + (n % 3 - 1);
**level = (--argc) ? (atoi (argv[1]) - 1) : 0;
**sprintf (msg, "Game Start!");
**do {
****pl = p[setup (++level)]; m = 1;
****draw_floor (level);
****do {
******printf ("Move : ");
******if (m) {
********do in = getche (); while (iscntrl (in));
********if (in == '.') m = 0;
********else if (!(in - '0')) {
**********gorobo (pl); pl->loc = rand () % MAX_LOC;
**********sprintf (msg, "Stunned... Press ENTER"); draw_floor (level);
**********getche ();
**********gorobo (pl);
********} else if (in > '0' && in <= '9') {
**********n = pl->loc + d[in - '1'];
**********if (SQ((n % W) - (pl->loc % W)) < 2 && n < MAX_LOC && n >= 0)
************pl->loc = n;
**********else sprintf (msg, "You were stopped by the wall.");
********} else sprintf (msg, "Invalad entry.");
******} else gorobo(pl);
******w = draw_floor (level);
****} while (!w && pl->type == 2);
****if ((w = pl->type) == 2) sprintf (msg, "level %d complete! ", level);
****takedown ();
**} while (w == 2 && level < 10);
**if (w == 2) printf ("You Win!");
**else printf ("You were captured by the robots at level %d\n", level);
**exit (0);

And gameplay looks like this:

Stunned... Press ENTER
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************************************** |
|************************************************************ +************** |
|**************************************************************************** |
|**************************************************************************** |
|**************************************************** +**O********************|
|**************************************************************************** |
|**************************************************************************** |
|********************************************** +**************************** |
|**************************************************************************** |
|**************************************************************************** |
|**********************+******** #**** +********************+**************** |

This code is pretty dynamic. You can change the height and width of the screen. You can change the effect of teleportation. (I experimented with atleast 3 different variations on that one.) A clever programmer could even add more evil robot types.

I wanted to see how small I could get it. My goal was 1K, less than 1024 characters. After much work I got it. But oh the sacrifices that had to be made:

#define q(a)(a)*(a)
#define f(u,v) if((p[n]->l u 79)v(l->l u 79))p[n]->l
typedef struct{int l,t;}z;z*p[99];int y;k(){int a=0,b,c=0,d=0;z*e;for(;a<=y;a++
{if(p[a]->l==p[a-1]->l)p[a]->t=p[a-1]->t=3;else do{if(!(c%79))puts("");putchar(
" O+#"[(p[a-1]->l==c)?p[a-1]->t:0]);}while(++c<p[a]->l&&c<=1817);d+=(p[a-1]->t
==2);}}return d;}main(){int n=0,m,w,e=0,d[9],i;z*l;srand(time(0));for(;n<99;n++
m)+1;}l=p[n];printf("\nLevel %d",e);m=k();do{if(m){do i=getche ();while(iscntrl
(i));if(i=='.')m=0;else if(!(i-'0'))l->l=rand()%1817;else if(i>'0'&&i<='9'){n=l
->l + d[i-'1'];if(q((n%79)-(l->l%79))<2&&n<1817&&n>=0)l->l=n;}}for(n=0;n<y;n++)
if(p[n]->t==2){f(%,>)-=1;else f(%,<)+=1;f(/,>)-=79;else f(/,<)+=79;}w=k();}
while(w&&l->t==1);}while(!w);if(w)printf("Ended on %d\n",e);}

In crunching robot escape to fit in less than 1k certain features had to be fudged. Robotescape1k does not free the memory it allocates, not much of a problem to most modern systems. Robotescape1k also makes no attempt at type checking. If you input an invalid keystroke, or run into a boundary for that matter, the program makes no attempt to tell you so, you simply lose a turn as though you pressed '5'. It also doesn't draw the borders, so you have to be careful at the edges.

In the 1k version there is technically no winning condition, so you can play until you are overwhelmed by sheer numbers. But Robotescape1k has a fixed max number of enemies on screen which, by the way, is 98 enemies and you makes 99. I was so crammed for space that adding one more digit to that number would have put me over. You exceed the maximum if you make it to level 24, which will consequenly crash the game. This however is an highly difficult thing to do, so consider the game beaten if you make it that far.

The 1k restriction also introduced a bug concerning the conditions of winning a level where it checks to see if all the robots are dead before checking if you are. In other words, if the last robot(s) kill themselves upon you, you still win and move on to the next level. Ah well, such is the price of this sort of pursuit. However, it can be a strange sort of satisfying to win by kamikaze / jihad / whatever.

.:EDIT:. CRA...UD. I wrote this ages ago and just noticed in the last line that "if(w)" can be removed, saving me 5 characters meaning I could take the game up to 9999999 on screen characters, more than the screen can handle, erradicating the level 24 cap. Meh, screw it. I never survived past level 16 myself anyways.

U-Boat Commander David 09-06-2006 05:25 PM

I would give a Toe to understand this.. :wallbash:

guesst 10-06-2006 01:41 AM

Poll at the end of this post, don't forget to vote!

<div class='quotetop'>QUOTE(U-Boat Commander David @ Jun 9 2006, 04:25 PM) [snapback]235479[/snapback]</div>

I would give a Toe to understand this.
A toe? Really? You're putting a toe on the altar? I doubt your sincerity. But I'll spare you your toe and instead give you these simple steps:
  1. Download and install DevC++ with MingW (all in one easy to use package)
  2. Run DevC++
  3. Choose a program here
  4. (This is the toe saving step) Print out the program and retype it back in. No copy/paste.
  5. Press the compile and execute button
  6. Debug as (probably) necessary
I guarentee that if you do this, you can keep all your toes and will quickly begin to understand what's going on. The best way to learn is by doing it, and the best way to do it is with programs you already know work. Then you'll find yourself changing the output text, personalizing the game to your own designs, and one day quickly perhaps even making them yourself. That's what these programs were made for, actually. That is the original vision for Cymon's Games. Try it out, and then let everyone here know how it goes?

Sound like too much work? Hey, you wanted to give up a toe. If I just take the pinky toe you have to learn how to walk all over. You think you don't need it, but it's got so much to do with balance. Trust me, typing a few tried and tested programs is easier than learning how to walk again.

So what program should I do next? Maybe I'll let the people decide. Here's the list of possible choices:
  • Battleship (like the board game vs the computer)
  • Cel Life (multi-player version of John Conway's game of Life)
  • Awari (african counting game with a learning logrithm)
  • 3DMaze (randomly generated mazes to navigate in first person perspective)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Flash Cards (with pretty output, practice your math)
  • Hammurabi (rule a country, build your kingdom)
  • Black Box (find molecules in the inky depths)
  • Joust (challange the knights of the realm for the hand of the princess)
  • 4 in a Row (connect four against the computer)
  • Hangman (guess the word before you dangle)
  • Mugwump (find the creatures hiding on a grid with a distance detector)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Reverse (order a list of number by turning them around)
  • Stars/Trap/Letter Guess (3 games in 1 update, variations on a theme)
What sounds interesting to you?

Reup 10-06-2006 08:54 AM

May I ask why you chose C and it's old-fashioned procedural programming paradigm over more modern ones such as OO? Mind you, I can appreciate the beauty in an obfuscated piece of C-code (although as a Java guy, I really hate doing memory managment myself), I was just curious.

Data 10-06-2006 11:13 AM

4 in a row please.
Interrested in seeing the ai part especially.

Reup OO is a way solving the problem. not the way.

there is nothing wrong with procedural programming I think. OO was overrated in its hype.
(which fortuntaly has a passed a bit)

The current time is 04:12 AM (GMT)

Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.