Forums

Forums (http://www.abandonia.com/vbullet/index.php)
-   Programming (http://www.abandonia.com/vbullet/forumdisplay.php?f=25)
-   -   Guesst's Programs (http://www.abandonia.com/vbullet/showthread.php?t=10494)

guesst 03-06-2006 05:10 PM

http://img.photobucket.com/albums/v6...Cymon/logo.gifButtons (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:
Code:

#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
(d&&(d==495)?!z("\n\n\t\tGoal!!!\n"):1);}

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

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

******** +===+**...**+===+
******** | 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:
Code:

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

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

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

****************Goal!!!

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:
Code:

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;
if(k=!k)continue;puts("");c-=3;}}main(){srand(time(0));*d=1+rand()%511;d[1]=rand
()%512;p();for(;*d&&((*d-d[1])?1:puts("Goal!"));){printf("move?");do n=getche ()
-'1';while(n<0||n>8);if(*d&1<<n)*d^=m[n];p();}}

When you run it you'll see:
Code:

789 *..
..6 **.
.23 ..*
move?

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
Code:

7.. *..
45. **.
..3 ..*
move?

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:
Code:

/* 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));
**R(0);
}

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++;
****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:
Code:

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

**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 10: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 03:21 PM

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

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.
[/b]
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 08: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:
Code:

main(){char b[11]="\toooo.OOOO";int e=5,n,t=0;puts("\t123456789");puts(b);for(;n
&&strcmp("\tOOOO.oooo",b);puts(b)){n=getche();if(n-='0'){if(n>0&&n<=9&&(abs(n-e)
==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
Code:

/* 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 12: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 03:10 AM

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

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?
[/b]
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 Escapehttp://img.photobucket.com/albums/v6...llerRobots.gif
The instructions are in the game, so just read down a few lines to see them:
Code:

/* 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.");
**********gorobo(pl);
********} 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:
Code:

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:
Code:

#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++
){for(b=y;a<y&&b>a;b--)if(p[b]->l<p[b-1]->l){e=p[b];p[b]=p[b-1];p[b-1]=e;}if(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++
){if(n<9)d[n]=79*(1-n/3)+(n%3-1);p[n]=malloc(sizeof(z));p[n]->l=1976;}do{y=m=7+
++e*4;n=rand()%m;w=1817;while(m-->0){p[m]->l=w-=rand()%(w/(m+1))+1;p[m]->t=(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 04:25 PM

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

guesst 10-06-2006 12: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>
Quote:

I would give a Toe to understand this.
[/b]
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 07: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 10: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)

Reup 10-06-2006 01:49 PM

As I recall I didn't say there was anything against procedural programming, only that it was more old-fashioned then OO. I'm also aware that it's not the only and best way. I was merely asking about guesst preference.
Maybe we sould start a 'which paradigm rocks donkey-balls' thread to discuss the benefits of each one?

guesst 10-06-2006 02:37 PM

Boys, now, let's calm down. No paradgm bashing here.

@ Reup, you haven't voted.

I chose plain C because it's a place to start. In fact, it's where I started. I was esentally going back to my roots. The plan was for me to write a few programs in C, then move on to CPP. However, it didn't last that long. When I started getting ready to do Wumpus in CPP, an exelent program to do OO, and life got in the way. That was a few months ago. Some day, soon I hope, I'll be able to finish what I started and show some CPP programs. Then I'm going to start simple graphical programs, then take over the world.

guesst 12-06-2006 08:33 PM

Well, I've gotten a single vote and that's probably going to be it. So here you go, by popular request:
Four in a Row
This was a algorithm adapted directly from a BASIC program and is uniquely frustrating because I've played it tons of times and only beaten it once.

The page in the link for the BASIC program above explains a little bit about the procedure the computer takes when making a move. I'll explain a bit after the code. So without further ado:
Code:

/* 4inarow
 * by Joseph Larson
 * based on a BASIC game by James L. Murphy
 * as found in 'More BASIC Computer Games' by David H. Ahl (c) 1979
 */

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

#define SHOWBD for (c=9; c >= 0; c--) puts (bd[c])
#define _X 'X'
#define _O 'O'

unsigned long v[16] = {1, 75, 500, 1e9, 1, 800, 4000, 1e9
**********************,1,100, 900, 1e7, 1, 450, 3000, 1e7};
int inrow[4], open[4], h[8];
char bd[9][20];

void intro (void) {
**puts ("Four in a Row\n---- -- - ---\n"
**"Stack X's and O's in order to make 4 in a row either vertically,\n"
**"horizontally diagonally before your opponent does.\n");
}

void init (void) {
**int c;

**for (c = 0; c < 8;) {
****h[c] = 0;
****strcpy (bd[++c], "- - - - - - - - ");
**}
**strcpy (bd[0], "1 2 3 4 5 6 7 8 ");
}

int count (int x, int y, char token) {
**int w, k, dx, dy, cx, cy, c, t;
**char op;

**x *= 2; op = (token - _X) ? _X : _O;
**for (c = 0; c < 4; c++) {
****inrow[c] = 1; open[c] = 0;
****dx = 2 * (c - 1 - (c > 2));
****dy = (c != 3);
****for (w = 0; w < 2; w++) {
******t = 1;
******for (k = 1; k < 4 && bd [cy = y + dy * k][cx = x + dx * k] != op; k++)
********if (cx <= 15 && cx >= 0 && cy <= 8 && cy > 0) {
**********if (t && bd[cy][cx] == token) inrow[c]++;
**********else {open[c]++; t = 0;}
********}
******dx = -dx; dy = -dy;
****}
****if (inrow[c] > 3) return 1;
**}
**k = 0;
**for (c = 0; c < 8; c++) if (h[c] < 8) k++;
**if (!k) return 2;
**return 0;
}

int domove (int m, char token) {
**bd [++h[m]][2 * m] = token;
**return count (m, h[m], token);
}

int getmove (int pl) {
**int input = 0;

**do {
****if (input) puts ("Illegal move, try again.");
****printf ("Player %d, pick a column (1 - 8) ? ", pl); scanf ("%d", &input);
****if (input < 1 || input > 8 || h[input - 1] > 7) input = -1;
**} while (input < 0);
**return --input;
}

int compmove (void) {
**unsigned long rank, bestrank;
**int bestmove, w, x, y, c, n[4], numsame;
**char token;

**bestmove = bestrank = 0; numsame = 1;
**for (x = 0; x < 8; x++) {
****y = h[x] + 1;
****if (y < 9) {
******rank = 1; token = _O;
******for (w = 0; w < 2; w++) {
********if (count (x, y, token)) {
**********printf ("Computer picks column %d\n", x + 1); return x;
********}
********for (c = 0; c < 4; c++) n[c] = 0;
********for (c = 0; c < 4; c++) {
**********open[c] += inrow[c];
**********if (open[c] > 3) {rank += 4; n[inrow[c] - 1]++;}
********}
********for (c = 0; c < 4; c++) if (n[c]--)
**********rank += v[8 * w + 4 * (n[c] ? 1 : 0) + c] + n[c] * v[8 * w + c];
********token = _X;
******}
******if (y < 8) if (count(x, y + 1, token)) rank = 2;
******if (rank == bestrank) if (rand() < RAND_MAX / ++numsame) {
********bestrank = rank; bestmove = x;
******}
****}
****if (rank > bestrank) {bestrank = rank; bestmove = x; numsame = 1;}
**}
**printf ("Computer picks column %d\n", bestmove + 1);
**return bestmove;
}

int main (void) {
**int c, numpl, w = 0;
**
**intro ();
**srand (time (NULL));
**init ();
**printf ("One or two human players? (1/2) "); scanf ("%d", &numpl);
**while (numpl > 2 || numpl < 1) {
****printf ("Please type the number 1 or 2 ? "); scanf ("%d", &numpl);
**}
**if (!--numpl) puts ("The Computer will be Player 2.");
**if (rand () % 2) {
****puts ("Player 1 goes first.");
****SHOWBD;
****domove (getmove (1), _X);
**} else puts ("Player 2 goes first.");
**while (!w) {
****SHOWBD;
****if (!(w = domove ((numpl) ? getmove (2) : compmove (), _O))) {
******SHOWBD;
******w = domove (getmove (1), _X);
****} else if (w == 1) w = 3;
**}
**SHOWBD;
**switch (w) {
****case 1 : puts ("Player 1 wins!"); break;
****case 2 : puts ("Tie game."); break;
****case 3 : puts ("Player 2 wins!");
**}
**exit (0);
}

A few notes about the code. The main funciton is a bit bigger than some programmers like to see. I suppose it could have been relegated to a sub routine, and still could I suppose. But I was experimenting with different styles of coding and this happened to be the one I chose at the time. It works, so meh.

How the computer makes a move. First of all, the board data is maintained in strings so that outputting the board is simply a matter of coughing it up. At the top there is an array called v that has a bunch of wierd number in it. Those numbers are the ranking assigned to the successfull creation of 1 in a row, 2 in a row, 3 in a row, and (altho unnecessary because it's an automatic "take it") 4 in a row for enemy first, then self. The compmove routine is called when it's the computer's turn to move. It virutally drops it's oppoenets (your) pieces in each slot, and adds up the rank of each move. Then it virtually drops it's own pieces into each slot and adds up the rank of each of those moves. Assuming that it didn't find that any move made 4 in a row (either pass), in which case it automaticly does that move, it then compares all the possible moves and chooses the highest scorer.

And as usual, I already see things I'd do to change it. Ah well, that's programming for you.

So come one, come on. Let's choose the next one. One responce with a choice, one program till we're done.
  • 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)
  • 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)

Reup 13-06-2006 06:56 AM

Okay. Now do 'joust' :D

Btw, where you say logarithm, don't you mean algorithm? :unsure:

guesst 13-06-2006 04:20 PM

<div class='quotetop'>QUOTE(Reup @ Jun 13 2006, 06:56 AM) [snapback]236324[/snapback]</div>
Quote:

Okay. Now do 'joust' :D

Btw, where you say logarithm, don't you mean algorithm? :unsure:
[/b]
Ah, yes. I have a bit of a problem doing that, even in my conversation. For some reason those two words get confused in my mind. Okay, hopefully I won't do that again.

So, Joust you say, eh?
This game was another taken from a BASIC game of the same name (from the second book of BASIC programs). It's kind of a choose your own story with a weighted random. On some of the BASIC programs I converted my attempt was to duplicate the algorithm of the original game exactly, so as to experience the game as it was meant to be played. On this one, however, I couldn't resist making a few small improvements. First of all, the original game had a bug that would allow you to choose defense options that were not shown if you knew their number. Fixed. Also in this one, if you mightaly unseat your opponent your next opponent (unless it's the fearless black night) will bow out.

Buy why am I just talking about the game, I should show it to you:
Code:

/* Joust
 * Based on a BASIC game of the same name by Alan Yarbrough
 * as found in 'More BASIC Computer Games' edited by David H. Ahl (c) 1979
 * by Joseph Larson
 */

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

#define WAIT puts ("\nPress ENTER to continue..."); getchar(); getchar()


char *roundintro[5] = {
**"This is your first joust. You are up aginst the Red Knight."
**,"This is your second joust. Your opponent is the Silver Knight."
**,"You are doing well! Your third joust is against the Gold Knight."
**,"This is your final test! If you win this one the princess is yours!\n"
**"This fight is against the fierce Black Knight!"
**,"Huzzah! You are the winner!\n"
**"Your prowis on the field of tournament has proven you worthy of the hand\n"
**"of the princess. With the concent of her father you marry the fair maden\n"
**"and live happily ever after.\n The End."},
*aimd[8] = {"1 - Helm", "2 - Shield, Upper Left", "3 - Shield, Upper Middle"
**,"4 - Shield, Upper Right", "5 - Shield, Lower Left"
**,"6 - Shield, Lower Middle", "7 - Shield, Lower Right", "8 - Base of Shield"},
*defd[6] = {"1 - Lower Helm", "2 - Right Lean", "3 - Left Lean"
**,"4 - Steady Seat", "5 - Shield High", "6 - Shield Low"},
*defmsg[8] = {"He missed you.", "He glanced off your shield."
**,"He knocked off your helm.", "He broke his lance."
**,"He has unseated you. (Thud!)"
**,"He has broken his lance, injured and unseated you."
**,"He hs injured and useated you. (crash)"
**,"He has broken his lance and unseated you. (Clang!)"},
*aimmsg[8] = {"You missed him. (Hiss!)", "You hit his shield but glanced off."
**,"You knocked off his helm! (Cheers!)", "You broke your lance. (Crack...)"
**,"You unseated him. (Loud cheers and huzzahs!)"
**,"You broke your lance, unseated and injured your foe. (The croud goes wild!)"
**,"You injured and unseated your opponenet."
**,"You broke your lance but unseated your opponent."};
int defok[8] = {7, 15, 63, 23, 7, 63, 7, 39},
defx[6][8] = {{0, 4, 5, 1, 3, 7, 1, 3},**{0, 3, 4, 0, 6, 1, 0, 1},
**{0, 0, 1, 3, 0, 3, 7, 5}, {2, 3, 3, 1, 3, 7, 1, 3}, {4, 3, 7, 1, 0, 5, 1, 5},
**{0, 0, 6, 4, 3, 3, 1, 3}},
aimx[8][6] = {{0, 0, 0, 2, 4, 0}, {4, 3, 0, 3, 3, 0}, {5, 4, 1, 3, 7, 6},
**{1, 0, 3, 1, 1, 4}, {3, 7, 1, 3, 0, 3}, {7, 1, 3, 7, 5, 3},
**{1, 0, 7, 1, 1, 1}, {3, 1, 4, 3, 5, 3}};

void intro (void) {
**printf ("Joust\n-----\n"
**"Hear ye, hear ye. Let all the noble knights of the kingdom come to joust\n"
**"at the King's tournament for the favor of the his daughter, the beautiful\n"
**"princess.\n\n");
}

int main (void) {
**int c, aim, def, r, droll, aroll;

**intro ();
**srand (time (NULL));
**r = 0;
**puts (roundintro[r]);
**do {
****puts ("\nChoose your aiming point :");
****for (c = 0; c < 8; c++) puts (aimd[c]);
****printf ("? "); scanf ("%d",**&aim);
****aim--;
****while (aim < 0 || aim > 7) {
******printf ("Invalid. Choose a number between 1 and 8.\n? ");
******scanf ("%d", &aim); aim--;
****}
****puts ("\nYou may use one of these defenses:");
****for (c = 0; c < 6; c++) if (defok[aim] & 1 << c) puts (defd[c]);
****printf ("? "); scanf ("%d", &def); def--;
****while (!(defok[aim] & 1 << def)) {
******printf ("Invalid. Choose an option from the menu above.\n? ");
******scanf ("%d", &def); def--;
****}
****putchar('\n');
****droll = rand () % 8;
****puts (defmsg[defx[def][droll]]);
****do {
******aroll = rand () % 6;
******switch (droll) {
********case 0:
********case 4:
********case 6: if (aroll < 3) aroll = -1; break;
********case 1: if (aroll < 2) aroll = -1; break;
********case 3: if (aroll == 0 || aroll == 2) aroll = -1; break;
********case 7: if (aroll == 1 || aroll == 2) aroll = -1;
******}
****} while (aroll < 0);
****puts (aimmsg[aimx[aim][aroll]]);
****if (defx[def][droll] < 4)
******if (aimx[aim][aroll] > 3) {
********puts ("\nYou have won this joust.");
********r++;
********WAIT;
********puts (roundintro[r]);
********if (aimx[aim][aroll] == 5 && r < 3) {
**********puts ("\nDue to your mighty victory in the last round your next "
************"opponent has conceded \nto you the win in this round.");
**********r++;
**********WAIT;
**********puts (roundintro[r]);
********}
******}
**** else {
****** puts ("\nYou are both ready to try again.");
****** WAIT;
**** }
**} while (r < 4 && defx[def][droll] < 4);
**if (r < 4) if (aimx[aim][aroll] < 4)
****puts ("\nToo bad, you lost. You leave the field of tournament a disgrace.");
**else puts ("\nToo bad, you both lost. At least your honor is intact.");
**puts ("\nFarewell Sir Knight.");
**WAIT;
}

Sample output
Code:

Joust
-----
Hear ye, hear ye. Let all the noble knights of the kingdom come to joust
at the King's tournament for the favor of the his daughter, the beautiful
princess.

This is your first joust. You are up aginst the Red Knight.

Choose your aiming point :
1 - Helm
2 - Shield, Upper Left
3 - Shield, Upper Middle
4 - Shield, Upper Right
5 - Shield, Lower Left
6 - Shield, Lower Middle
7 - Shield, Lower Right
8 - Base of Shield
? 6

You may use one of these defenses:
1 - Lower Helm
2 - Right Lean
3 - Left Lean
4 - Steady Seat
5 - Shield High
6 - Shield Low
? 4

He broke his lance.
You broke your lance, unseated and injured your foe. (The croud goes wild!)

You have won this joust.

Press ENTER to continue...

This is your second joust. Your opponent is the Silver Knight.

Due to your mighty victory in the last round your next opponent has conceded
to you the win in this round.

Press ENTER to continue...


You are doing well! Your third joust is against the Gold Knight.

Choose your aiming point :
1 - Helm
2 - Shield, Upper Left
3 - Shield, Upper Middle
4 - Shield, Upper Right
5 - Shield, Lower Left
6 - Shield, Lower Middle
7 - Shield, Lower Right
8 - Base of Shield
? 1

You may use one of these defenses:
1 - Lower Helm
2 - Right Lean
3 - Left Lean
? 1

He glanced off your shield.
You missed him. (Hiss!)

You are both ready to try again.

Press ENTER to continue...

And so on. It is possible to win the lady, I've done it several times. But sometimes fate steps in. Try it a few times, you may like it.

Next?
  • 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)
  • 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)
While at the moment this thread has Reup and Data apparently reading it, and U-Boat commander Dave offering his digits for programming skill, my hope is that this is a thread that over a long time will get noticed once in a while. But at the moment, how are you all liking it so far?

Abi79 13-06-2006 07:10 PM

Quote:

But at the moment, how are you all liking it so far?[/b]
It's a very great source of C(++) games for me. Very useful, since I study C++ at school and I can use this to learn lots of things. (the next computers or how it is called olympiad will be in February, and I need to get better results then this year - I only got the 13th place out of 40 at the National Olympiad phase <_< )

And I vote for 3DMaze to be posted here next. ^_^

guesst 14-06-2006 04:02 PM

Hey, 13 out of 40 in a competition where no morons are allowed isn't bad. You were doing well just to get in.

3DMaze
This is a real cool one. Taken from yet another entry in the International Obvscated C-Code Contest (another exelent place to find C-Code examples written by people better than me). Sean Barrett's winning 1991 entry drew an ascii representation of a first person view through a maze. For the maze the program read it's own code in and used the whitespaces for floor. Clever, but not very dynamic.

So I decided to make a random maze generator and attach it to the drawing algorithm. This meant I had to take code that was not formatted for reading and reformat it with variables with understandable names and everything. It was an interesting way to figure out how this extremely clever routine worked.

The final result is uber-cool and looks like this:
Code:

****\****************************************** /
**** |**************************************** |
**** |**************************************** |
**** |**************************************** |
**** |**************************************** |
**** |--------\********************** /--------|
**** |****** |**\****************** /**|****** |
**** |****** |****\************** /****|****** |
**** |****** |**** |************/|**** |****** |
**** |****** |**** |**********/**|**** |****** |
**** |****** |**** |---------|** |**** |****** |
**** |****** |**** |** |**** |** |**** |****** |
**** |****** |**** |---------|** |**** |****** |
**** |****** |**** |**********\**|**** |****** |
**** |****** |**** |************\|**** |****** |
**** |****** |****/************** \****|****** |
**** |****** |**/****************** \**|****** |
**** |--------/********************** \--------|
**** |**************************************** |
**** |**************************************** |
**** |**************************************** |
**** |**************************************** |
****/****************************************** \

(F)orward, (L)eft or (R)ight?

Do you want to see the program now? Here it is...
Code:

/* 3DMaze
 * by Joseph Larson 2005
 * Maze generator written by Joseph Larson
 * 3D drawing routine by Sean Barrett 1991, found at the International
 * Obfuscated C Code Contest http://www.ioccc.org
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#define XMAX 39
#define YMAX 11
#define MID 26
#define WALL 0
#define UNSEEN 1
#define SEEN 2
#define TRAVL 3
#define EXIT -1
#define D(a) (2 * (a + 1))
#define NP(a, b) (a * (b - 1) + (a - 1) * b)
#define SWAP(a,b) a ^= b; b ^= a; a ^= b
#define X(a) xytable[(a) % 4]
#define Y(a) xytable[(a + 1) % 4]

int scale[6] = {11, 10, 6, 3, 1, 0};
int xytable[4] = {1, 0, -1, 0};
int maze[D(XMAX)][D(YMAX)], xsize, ysize, x, y, face, hpos;

void drawmap (void) {
**int c, d;

**for (d = 2 * ysize; d >= 0; d--) {
****putchar ('\n');
****for (c = 1; c < D(xsize); c++)
******putchar ((c == x && d == y) ? '*' : "## ."[maze[c][d]]);
**}
}

void snr (int n1, int n2) { /* search and replace */
**int c, d;

**if (n1)
****for (c = 2; c < D(xsize); c++) for (d = 1; d < D(ysize) - 1; d++)
******if (maze[c][d] == n1) maze[c][d] = n2;
}

void generate (void) {
**int px[NP(XMAX, YMAX)], py[NP(XMAX, YMAX)], b, c, d;

**for (c = 0; c < D(XMAX); c++) for (d = 0; d < D(YMAX); d++)
****maze[c][d] = (c) ? WALL : EXIT;
**b = 0;
**/* populate potentials */
**for (c = 3; c < 2 * xsize; c += 2) for (d = 1; d < 2 * ysize; d += 2) {
****px[b] = c; py[b++] = d;
**}
**for (c = 2; c <= 2 * xsize; c += 2) for (d = 2; d < 2 * ysize; d += 2) {
****px[b] = c; py[b++] = d;
**}
**/* randomize potentials */
**for (b = 0; b < NP(xsize, ysize); b++) {
****c = rand () % NP(xsize, ysize);
****if (c - b) {SWAP (px[c], px[b]); SWAP (py[c], py[b]);}
**}
**/* make the maze */
**for (b = 0; b < NP(xsize, ysize); b++) {
****c = d = 0;
****if (py[b] % 2) c = 1; else d = 1;
****if (!maze[px[b] + c][py[b] + d] || !maze[px[b] - c][py[b] - d]
******|| maze[px[b] + c][py[b] + d] != maze[px[b] - c][py[b] - d]) {
******snr (maze[px[b] + c][py[b] + d], b + 1);
******snr (maze[px[b] - c][py[b] - d], b + 1);
******maze[px[b]][py[b]] = maze[px[b] + c][py[b] + d]
******= maze[px[b] - c][py[b] - d] = b + 1;
****}
**}
**snr (maze[2][1], UNSEEN);
**/* now make an exit */
**maze[1][2 * (rand () % ysize) + 1] = UNSEEN;
**x =**2 * xsize; y =**2 * (rand () % ysize) + 1; face = 2;
}

int look (int f, int s) {
**int c, d, r;

**c = x + X(face) * f + X(face - 1) * s;
**d = y + Y(face) * f + Y(face - 1) * s;
**r = maze[c][d]; if (r == UNSEEN) maze[c][d] = SEEN;
**return r;
}

void draw (int col, char *s) {
**while (hpos < col) {putchar (' '); hpos++;}
**printf ("%s", s); hpos += strlen (s);
}

void draw3d(void) {
**int line, side, depth, p, q, i;
**
**putchar ('\n');
**for (line = -11; line <= 11; ++line) {
****for(side = 1, depth = 0; side + 3; side-=2) {
******for (; depth != 2 + 3 * side; depth += side) {
********if(look (depth, 0) < UNSEEN) {
**********p = scale[depth];
**********if (abs(line) < p && look(depth, 0) == WALL || abs (line) > p) break;
**********for (i = -p; i < p; ++i) draw (MID + i * 2, "--");
**********draw (0, "-"); break;
********}
********if (depth == 5) continue;
********p = scale[depth + 1]; q = scale[depth];
********if (abs (line) > q) continue;
********if (abs (line) < p) draw (MID - side * (2 * p + 1), "|");
********else if (look (depth, side)) {
**********if (abs (line) <= p)
************for(i = (side == 1 ? -q : p); i != (side == 1 ? -p : q);
**************(abs (line)), ++i)
**************draw (MID + 2 * i + (side == -1), "--");
********} else if (abs(line) == p)
**********draw (MID - side * (2 * p + 1), "|");
********else draw (MID - (abs (line) * side * 2),
**********(side == 1) ^ (line > 0) ? "\\" : "/");
******}
******depth -= side;
****}
****putchar ('\n'); hpos=0;
**}
**if (maze[x][y] != EXIT) maze[x][y] = TRAVL;
}

int move (void) {
**char in;

**printf ("\n%c (F)orward, (L)eft or (R)ight? ", "WSEN"[face]);
**do in = getche (); while (!isalnum (in)); in = tolower (in);
**if (in == 'm') drawmap ();
**else {
****if ((in == 'w' || in == 'f') && look (1, 0) != WALL)
******{x += X(face); y += Y(face);}
****if ((in == 's' || in == 'b') && look (-1, 0) != WALL)
******{x -= X(face); y -= Y(face);}
****face += (in == 'd' || in == 'r') + 3 * (in == 'a' || in == 'l');
****if (in == 'z'&& look (1, 0) != WALL) do {x += X(face); y += Y(face); draw3d ();}
******while (look (1, 0) > WALL && look (0, 1) == WALL && look (0, -1) == WALL);
****draw3d (); face %= 4;
**}
**return (in != 'q');
}

void setsize (void) {
**char in;
**
**printf ("(E)asy, (M)edium or (H)ard? ");
**do {
****do in = getche (); while (!isalnum (in)); in = tolower (in);
****switch (in) {
******case 'e' : xsize = ysize = 5; break;
******case 'm' : xsize = 15; ysize = 11; break;
******case 'h' : xsize = XMAX; ysize = YMAX; break;
******default : printf ("\nInvalad Option. Please choose E, M, or H? ");
********xsize = ysize = 0;
****}
**} while (!xsize);
}

int main (void) {
**clock_t st, et;
**double secs;
**
**srand (time (NULL));
**setsize ();
**generate ();
**draw3d ();
**st = clock ();
**while (move () && look (0,0) != EXIT);
**if (look (0, 0) == EXIT) {
****et = clock ();
****secs = (double)(et - st) / CLOCKS_PER_SEC;
****snr (UNSEEN, SEEN);
****drawmap ();
****printf ("\nYou escaped the Labryinth in %2.3f seconds!\n", secs);
**}
**exit (0);
}

I made my own keys for playing this. Yes, 'L' will go left, 'R' will go right and so forth, but also 'WADS' can be used. 'M' displays the map so far and 'Z' is a special command I made that will zip you forward until you hit a wall or a branching path.

The constants WALL, UNSEEN, SEEN, TRAVL, and EXIT are for the map. When the maze is generated you have WALLs and UNSEEN everywhere and EXIT at the end. As you see an area UNSEEN becomes SEEN and as you go there the spot you stand on becomes TRAVL. That way at the end you can see what path you took through the maze.

The maze generating algorithm doesn't make paths through the maze or anything. It just makes sure you can get anywhere from anywhere else one and only one way. It connectes two spaces with a numbered path. If two paths are connected the higher number over rides the other path so that if it wanto to join two areas it only needs to be sure they aren't of the same path, meaining a loop would be generated. A hole is punched in the left side for the exit. I had considered having a square maze, dropping the player in the exact middle, and punching one hole in any of the outside walls, meaning you could wander the wrong direction for a long time before getting out. But I decided against that for a straight east to west progression to make it less diabolical. Besides, a square map of more than 11x11 would not show well on the map printout.

This game is so cool I absolutely recomend downloading DevCPP and playing this one. It's a hoot. I wanted to include the executable here, but the boards don't allow it. But you have the code, so go on with you.

So there is 3DMaze. What's next?
  • 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 algorithm)
  • 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)
  • 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)

Abi79 14-06-2006 07:23 PM

Awari, Awari! (since I don't know what a learning a(?)lgorithm is, and would like to see :D )

guesst 14-06-2006 08:52 PM

I don't want to post two in one day, so I'll just say (1) thanks, I missed that one. And (2) did you even play the maze game yet? Tell me what you thought of it.

guesst 15-06-2006 04:53 PM

http://img.photobucket.com/albums/v6...ymon/Awari.gifAwari
Awari is an ancient African counting game. Each player has 6 places with 3 markers or stones in each to start and an empty home. A move is made by taking all the markers from any non-empty place on your side, then “sowing” the markers one at a time in a counter-clockwise direction around the board. If the last marker sown lands in your home then you get a second move. (No more than two moves in one turn.) If the last marker is sown in an empty spot and the spot opposite is not empty then you capture the last marker and all the markers in the opposite spot. When either side is empty then the game is finished.

Another conversion of a BASIC program of the same name. In the original the board was layed out left to right, more like one would play it in real life. I thought that was a bit confusing so I wrote a new version (just this morning) which layed things out top to bottom. I'm not sure it's that much better so I kept the original version but commented it out.

So here we go...
Code:

/* Awari */
/* by Joseph Larson */
/* based on a BASIC game by Geoff Wyvill */
/* as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978 */

#include <stdio.h>
#include <time.h>
#include <math.h>

int memory[51], board[14];
int turn;

void intro (void) {
**char input;

**printf ("\nAwari\n");
**printf ("------\n");
**printf ("Do you need the rules? (y\\n) ");
**scanf ("%c", &input);
**if ((input == 'y') || (input == 'Y')) {
****printf ("\nAwari is an ancient African counting game. Each player has 6\n"
****"places with 3 markers or stones in each to start and an empty home. A\n"
****"move is made by taking all the markers from any non-empty place on your\n"
****"side, then \"sowing\" the markers one at a time in a counter-clockwise\n"
****"direction around the board. If the last marker sown lands in your home\n"
****"then you get a second move. (No more than two moves in one turn.)\n\n"
****"If the last marker is sown in an empty spot and the spot opposite is not\n"
****"empty then you capture the last marker and all the markers in the\n"
****"opposite spot. When either side is empty then the game is finished.\n\n"
****"Player one is at the left with home at the bottom, player two (or the\n"
****"computer in a one player game) is at the right with home at the top.\n"
****"By the way, the computer opponent is designed so that the more you play\n"
****"it, the better it gets.\n\n"
****"Good luck and have fun!\n");
**}
}

void drawboard (void) {
**int c;
**
**printf("\n\t (%2d)**Player 2", board[13]);
**for (c = 0; c < 6; c++)
****printf ("\n\n %d (%2d)\t\t(%2d) %d", c + 1, board[c], board[12 - c], 6 - c);
**printf("\n\nPlayer 1**(%2d)\n\n", board[6]);
/***printf ("\n");
**for (c = 12; c > 6; c--) printf ("%3d ", board[c]);
**printf ("\n%d %24d \n", board[13], board[6]);
**for (c = 0; c < 6; c++) printf ("%3d ", board[c]);
**printf ("\n\n"); */
}

int domove (int move, int home) {
**int c;

**c = board[move]; board[move] = 0;
**do {
****if (++move > 13) move -= 14;
****board[move]++;
**} while (--c > 0);
**if ((board[move] == 1) && (move != 6) && (move !=13) && (board[12 - move])) {
****board[home] += board[12 - move] + 1;
****board[move] = board[12 - move] = 0;
**}
**if (move == home) return (1);
**else return (0);
}

void remember (int move) {
**turn++;
**if (move > 6) move -= 7;
**if (turn < 9) memory[memory[0]] = memory[memory[0]] * 6 + move;
}

int playermove (int pl) {
**int input;

**do {
****printf ("Player #%d, your move? (1 - 6) ", pl + 1);
****scanf ("%d", &input);
****if ((input < 1) || (input > 6) || !board[input + ((pl) ? 6 : - 1)]) {
******printf ("Illegal move.\n");
******input=0;
****}
**} while (!input);
**remember (--input);
**return (input + ((pl) ? 7 : 0));
}

int computermove (void) {
**int move, bestmove, rank, bestrank, c, r, check;
**int saveboard[14];
**
**for (c=0; c < 14; c++) saveboard[c] = board[c];
**bestrank = -99;
**for (move = 7; move <= 12; move++)
****if (board[move]) {
******rank = 0;
******domove(move, 13);
******for (c = 0; c < 5; c++)
********if (board[c]) {
**********r = 0; check = board[c] + c;
**********while (check > 14) { check -= 14; r = -1;}
**********if ((!board[check]) && (check !=6) && (check != 13))
**********r-=board[12 - check]; rank =(r < rank) ?**r : rank;
********}
******rank += board[13] - board[6];
******if (turn < 9) {
********check = memory[memory[0]] * 6 + move - 7;
********for (c = 1; c < memory[0]; c++)
**********if ( check == (int) ((float) memory[c] / pow (6, (7 - turn)) + 0.1))
************rank -= 2;
******}
******for (c=0; c < 14; c++) board[c] = saveboard[c];
******if (rank >= bestrank) {bestrank = rank; bestmove**= move;}
****}
**remember (bestmove);
**printf("Computer moves %d", (bestmove - 6));
**return (bestmove);
}

int endgame (void) {
**int c, d, e;

**d = e = 0;
**for (c = 0; c < 6; c++) d += board[c];
**for (c = 7; c < 13; c++) e += board[c];
**if ((!d) || (!e)) return (1);
**else return (0);
}

void playgame (void) {
**int c, numpl;

**for (c = 0; c < 13; c++) board[c] = 3;
**board[6] = board [13] = memory[memory[0]] = numpl = 0;
**do {
****printf ("\nHow many players (1 - 2) ? ");
****scanf ("%d", &numpl);
****if (numpl < 1 || numpl > 2) {
******printf ("Please input either 1 or 2.\n");
******numpl = 0;
****}
**} while (!numpl);
**turn = 0;
**do {
****drawboard ();
****if (domove (playermove (0), 6))
******if (!endgame()) {
********drawboard ();
********printf ("Again.\n");
********domove (playermove (0), 6);
******}
****drawboard ();
****if**(!endgame ()) {
******if (domove ((numpl - 1) ? playermove (1) : computermove (), 13))
********if (!endgame()) {
**********drawboard ();
**********printf ("Again.\n");
**********domove ((numpl - 1) ? playermove (1) : computermove (), 13);
********}
******printf("\n");
****}
**} while (!endgame ());
**drawboard ();
**printf ("\nGame Over.\n");
**c = board[6]-board[13];
**if (c < 0) printf ("%s by %d points.\n",
**(numpl - 1) ? "Player 2 wins" : "I win", (-c));
****else {
******if (numpl - 1 && memory[0] < 50) memory[0]++;
******if (c == 0) printf ("Drawn game.\n");
******else printf ("Player 1 wins by %d points.\n", c);
****}
}

int playagain (void) {
**char input[50];

**printf ("\nDo you want to play again? (y\\n) ");
**scanf ("%s", input);
**if ((input[0] == 'y') || (input[0] == 'Y')) return 1;
**else return 0;
}

void loadmemory (void) {
**FILE *fp;
**int c;
**
**c = 0;
**fp = fopen ("awari.dat", "r");
**if (fp == NULL)
****memory[0] = 1;
**else {
****while (!feof (fp)) fscanf (fp, "%d", &memory[c++]);
****fclose (fp);
**}
}

void savememory (void) {
**FILE *fp;
**int c;
**
**fp = fopen ("awari.dat", "w");
**if (fp != NULL) {
****for (c=0; c <= memory[0]; c++)
******fprintf(fp, "%d\n", memory[c]);
****fclose(fp);
**}
}

int main (void) {
**intro ();
**loadmemory ();
**do playgame (); while (playagain ());
**if (memory[0] > 1) savememory ();
**return 0;
}

The AI plays by a fairly simple set of rules; Try every move and see which one scores the most point with provision for if you leave yourself open, but then takes it a step further. Every game is encoded into a number that if looked at in base 6 (not one of your common bases) is the first 8 digits of the game played. Then every game so far is compared to an array of games that it lost in the past. If this game is shaping up to look like a loser it will adjust it's strategy. In other words, when the computer loses it tucks that loss away and tries not to make that mistake again.

The list gets shorter every time! This time I added one I had forgotten however.
  • Battleship (like the board game vs the computer)
  • Cel Life (multi-player version of John Conway's game of Life)
  • 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)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)
  • 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)

Abi79 16-06-2006 05:47 AM

<div class='quotetop'>QUOTE(guesst @ Jun 14 2006, 11:52 PM) [snapback]236864[/snapback]</div>
Quote:

And (2) did you even play the maze game yet? Tell me what you thought of it. [/b]
I've played it yesterday. After saying OH MY GOD HOW COOOOOOOOOOOOOOOOOOOOOOOOOOOL..., I've tried to actually get to the exit, but I couldn't find it on the easy level. Anyway, is there a way to exit the game without pressing CTRL+Break in C++ or reaching the actual exit?

This games will be very useful tomorrow at school, and will certainly make the 10 year olds also studying C++ with me have some fun...and ask the teachers how they were made again and again and again. Poor teachers.

Oh, and are the games made in C, or C++? In C++, I had to add an extra library for getche for the game to work, and I also got the warning that int main(void) should return a value. Couldn't you have used void main instead of int main(void)?

Mugwump is what I would like to be posted next. (meanwhile I have to try the other games)

#BlakhOle# 16-06-2006 10:30 AM

Hi im kinda new to this, but you recommended this thread to me in one of the game threads, i think othello, so im about as nooby as a noob can possibly noob, so bear with me here. :D I reckon this would be the most amazing thing to be able to do, and to able to do it good would be awesome. But everyone has to start off somewhere, dont they? Anyways,
i have a few questions to ask you.

First of all, in the tutorial they gave me in with the C++ program guides me through the "Hello World" program and ive already typed it in and compiled it and everything, but every time i try to run it I see the command prompty kinda box pop up for a fraction of a second then just disappear. And it does this everytime. So i went a bit further to find out about loops and put a neverending loop in, and it worked perfectly, the box came up and a neverending greeting to the world flashes down the screen. But i cant work out how to do the simple one line one. Any hints?

Secondly, ive been through a couple of the programs you have posted here but every single one is rejected by the compiler, and of course, having not even been able to configure the Hello World program correctly, I cant work out what is wrong with them.

On a smaller note could you try to explain the integers and floats a bit more coz i cant make head nor tail of them. Thanx :)

Abi79 16-06-2006 11:46 AM

<div class='quotetop'>QUOTE(#BlakhOle# @ Jun 16 2006, 01:30 PM) [snapback]237123[/snapback]</div>
Quote:

First of all, in the tutorial they gave me in with the C++ program guides me through the "Hello World" program and ive already typed it in and compiled it and everything, but every time i try to run it I see the command prompty kinda box pop up for a fraction of a second then just disappear. And it does this everytime. So i went a bit further to find out about loops and put a neverending loop in, and it worked perfectly, the box came up and a neverending greeting to the world flashes down the screen. But i cant work out how to do the simple one line one. Any hints?[/b]
Here's something for you:
Code:

#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
printf("Hello BlakhOle! Do you like C++? I bet you don't :P ");
getch();
}

See 'getch();'? Is it included in the program from the tutorial? This instruction makes everything on the screen stay there until you press a key. If it isn't included, then the results still appear, but you need to press Alt+F8 (if I remember well) to see them.

<div class='quotetop'>QUOTE(#BlakhOle# @ Jun 16 2006, 01:30 PM) [snapback]237123[/snapback]</div>
Quote:

Secondly, ive been through a couple of the programs you have posted here but every single one is rejected by the compiler, and of course, having not even been able to configure the Hello World program correctly, I cant work out what is wrong with them.[/b]
What error does the compiler give you?

<div class='quotetop'>QUOTE(#BlakhOle# @ Jun 16 2006, 01:30 PM) [snapback]237123[/snapback]</div>
Quote:

On a smaller note could you try to explain the integers and floats a bit more coz i cant make head nor tail of them. Thanx :) [/b]
I'll let that for Guesst to do. When I explain something, people get even more confused. ^_^

guesst 16-06-2006 04:46 PM

So much to reply to! Warms my heart.

All of the programs posted here are in ANSI standard C, that is to say, not C++. If you want to eliminate some of the problems your complier is having with them, Abi79, save the files with a .C extention (not .cpp which is probably the default) and the compiler will (generally) compile it slightly differently.

@#BlakhOle#
I assume you're using DevCPP that I recomended at the start. Yes, "hello world" does come and go quickly. The problem is that when the program runs it opens a window, does the output, and closes the window before you get a chance to see what happened. There are two ways around this. One is to add the line
Code:

**getch();getch();
just inside the last bracket. This way the last thing the program will do is wait for you to input something before exiting. Try that first.

PS, Albi79, your hello world is not technically C++ code. It's a kind of bastardized hybred. A proper C++ program would use streams like this:
Code:

#include <iostream>
** int main(int argc, char **argv)
** {
**** char c;
******
**** std::cout << "Hello BlakhOle! Do you like C++? I bet you don't :P" << std::endl;
**** std::cin.get();
**** return (0);
** }

Which is why I don't write C++ code much yet. To do it properly is learning a whole new language. However, the above program you would want to tack on a .CPP extension or the compiler will likely bugger it up.

Back to #BlakhOle#'s question, as for getting the programs here to work the first thing to do when you compile them if they don't run is look at the frame that pops up at the bottom. It will give you any warnings or errors that may be impeeding the execution of the program. If you can't make heads or tails of them tell us which program you're running and post the error here and we'll see if we can't help out.

Ah, floats and ints. Well, there is a simple answer and a more complicated answer to that. Most books will take the complicated answer, explaining the inner workings of your computer and whatnot. I'll take the simple one.

char, int, and long are all the same thing in that they can be used to store only whole numbers, that is to say no decimals, no fractions. 1, 2, 3, 100, 121, etc. The difference in them is that a char can only hold number less than 256 if unsigned or between -127 and 128 if signed. It's very limited but works for certian things very well. Ints can hold bigger numbers than a char. Use them for your regular counting. Longs are for when you may need a really big number. If you try to put a number that's too big into a variable that can't hold it all sorts of wonky thinks can happen.

float and double are for holding numbers that may have decimal values. 1.1, 5.6, 10057.3, 3.14159, etc. Decimal points are a tricky thing for a computer to handle, so it's recomended that if you can do the job with whole numbers not to use floats as you're only going unnecessarly bog down your computer.

Well folks, I have an eye appointment, so that's all the time I have for now. Maybe I'll do mugwump later, maybe not until tomorrow. If you have any more questions, you know where to find me.

Ta

plix 16-06-2006 08:22 PM

<div class='quotetop'>QUOTE(Abi79 @ Jun 16 2006, 01:47 AM) [snapback]237089[/snapback]</div>
Quote:

I also got the warning that int main(void) should return a value. Couldn't you have used void main instead of int main(void)?[/b]
It's bad form. The return value is also known as the exit status and important for knowing how the program exited. This doesn't generally make a big difference on Windows, but in a Unix-like environment it's important for piping (command chaining), diagnostics, etc.

#BlakhOle# 17-06-2006 03:36 AM

Ok lets see whats worked here... first of all, C++ doesnt seem to like the getch(); command much, the compiler log comes up with
Quote:

`getch' undeclared (first use this function)
(Each undeclared identifier is reported only once for each function it appears in)
[/b]
It seems to come up with this sort of thing alot in the programs youve posted before. It does it whether I save it as a .cpp file or just .c file.
The program you fixed from abi also worked pretty well, dunno how though. :P
Apart from that all seems well, except from the fact i still dont know what everything means. Back to the HELP file i guess...

PS @abi: Actually i dont hate C++, but i might like it a bit more if it was a bit more self explanatory :bleh:

guesst 17-06-2006 04:10 AM

Got time for some quick responces. You never confirmed which compiler you're using. It would be helpful in the future to know what program you're working form.

As for getch() being no-go, okay, try getchar() or my personal favorate getche(). Getch is a non-standard function so it behaves differently, if it's there at all, between different compliers. Getchar is the standard version that all of my programs are written to be compatible with. However getche, unline getchar, doesn't wait until you hit the enter key before moving on. Getche will just take one character and run with it.

void main () is possible on some compilers, but is extremely bad form like plix said. Always have int main() and to be completely compliant alway use return(0) at the end of the program to indicate a successful run. (Potentially you could exit with a non-zero value to pass information like error messages to external programs, but that's mostly a Unix thing.)

So, to sum up:
  • getchar should always work.
  • guesst prefers getche.
  • int main() in every program and
  • return(0) for extra credit.
And while I'm here, and since I may not have time tomorrow...

Mugwump

This is a good game to show the difference between ints and floats that we were just talking about above. In 101 BASIC games and it's successor there were numerious hide and seek games played on a grid where by various means the player was given hints as where to find whatever ridiculous creature they were hunting for. Of all of them Mugwump was perhaps the most intersting of them. Instead of directional hints this game gives the distance to your targets. In an improvement over the original this one sorts the resultant distances so you don't know which ones are for which any more. Also, there's a timing loop that simulates a distance reading machine of some sorts with the output. Check it out.
Code:

/* Mugwump Hunt
 * by Joseph Larson 2005
 * inspired by a BASIC game by an unknown author
 * as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978
 */
 
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

#define dist(a,b) sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y))
#define NUM 5
#define SIZE 20

typedef struct {
**int x, y;
} COORD;

int greater (double *a, double *b) {return (*a > *b);}

void intro (void) {
**printf ("Mugwump Hunt\n-----------\n"
**"You are hunting Mugwumps using a state of the art radar system. There are\n"
**"%d mugwumps hidden hiding in a %d,%d grid. After every guess you will be\n"
**"told how close the remaining Mugwumps are to your guess.\n"
**"Input the your guess by typing the x and y location seperated by a comma\n"
**"(IE \"5,5\" or \"3,10\")\n"
**"(Mugwumps only hide whole number locations.)\n\n",
**NUM, SIZE, SIZE);
}

void hunt (void) {
**int c, turns, left, dsize;
**COORD h[NUM], input;
**double d[NUM];
**time_t st, cur, dit;

**for (c = 0; c < NUM; c++) {
****h[c].x = rand() % SIZE + 1;
****h[c].y = rand() % SIZE + 1;
**}
**printf ("The Mugwumps are hiding.");
**turns = 0;
**left = NUM;
**while (left > 0) {
****turns ++;
****printf ("\n%d Mugwumps left.\n", left);
** input.x = input.y = -1;
****do {
******if (input.x != -1 && input.y != -1)
********printf ("X and Y values must be between 1 and %d", SIZE);
********printf ("\nWhere do you want to search? X,Y : ");
********scanf ("%d %*c %d", &input.x, &input.y);
****} while (input.x < 1 || input.x > SIZE || input.y < 1 || input.y > SIZE);
****dsize = 0;
****printf ("Mugwump Radar Searching from %d,%d...", input.x, input.y);
****for (c = 0; c < NUM; c++)
******if (h[c].x == input.x && h[c].y == input.y) {
********printf ("\nMugwump found!");
********h[c].x = h[c].y = -1;
********left--;
******} else if (h[c].x > 0) d[dsize++] = dist(h[c], input);
****if (dsize) {
******qsort (d, dsize, sizeof(double), greater);
******time (&st); dit = st;
******for (c = 0; c < dsize; c++) {
********do {
**********time (&cur);
**********if (difftime (cur, dit) > 0.2) {putchar ('.'); time (&dit);}
********} while (difftime (cur, st) < d[c] / 2);
********printf ("\nMugwump at distance %.2f", d[c]);
******}
****}
**}
**printf ("Congratulation! All Mugwumps found in %d turns!", turns);
}

int again (void) {
**char input;

**printf ("\nDo you want to play again? (y/n) ");
**while (!isalpha (input = getchar()));
**if (tolower (input) != 'n') return 1;
**return 0;
}

int main (void) {
**intro();
**srand (time (NULL));
**do {hunt();} while (again ());
**exit (0);
}

Now, if you're plaing the game with grid paper and a compass you should have a pretty good idea after three moves where most, if not all of the mugwumps are hiding, and each one you find will narrow it down further. However, if you're not playing with grid paper you may find your hunt a bit more challenging.

If you change the constants NUM and SIZE at the start of the program you can easily adjust the difficulty of the game. Enjoy!

And the winner for best supporting gaffer is...
  • Battleship (like the board game vs the computer)
  • Cel Life (multi-player version of John Conway's game of Life)
  • 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)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)
  • 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)

Abi79 18-06-2006 03:14 PM

<div class='quotetop'>QUOTE(#BlakhOle# @ Jun 17 2006, 06:36 AM) [snapback]237264[/snapback]</div>
Quote:

PS @abi: Actually i dont hate C++, but i might like it a bit more if it was a bit more self explanatory[/b]
Well, assuming that you have Borland C++ (the DOS one), just like I do, you could try looking in the help, but I don't guarantee that you aren't going to look like :tai: after that. :bleh:

As for guesst, Hammurabi, Hammurabi! :D

guesst 19-06-2006 03:44 PM

http://img.photobucket.com/albums/v6.../hammurabi.gifHammurabi
Not feeling like typing much today. But your wish is my command. Once again this is a BASIC program that got the C treatment. Follow the link if you want to know more.

.:EDIT:. I'm feeling like typing more now. While I realize no one is going to take the time to read this, I'm posting it any ways.

Hammurabi borrows it's name from the Babylonia ruler who is famous for setting up a standard of laws and punishments. By "setting up a standard" I mean he literally built an 8 foot tall black stone monument, clearly meant to be placed in the center of town. There was no excuse for not knowing the laws in Hammurabi's reign, because they were before you day and night. In this way it was believed that Hammurabi kept order in his town.

Now it's your chance. See if you can expand your land and grow your population in a 20 year reign as king in this exciting simulation game.
Code:

/* Hammurabi
 * by Joseph Larson
 * based on a BASIC program written by David Ahl
 * as found in 'BASIC Computer Games' edited by David H Ahl (c) 1978
 * inspired by a Focal program from an unknown author
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SHORT_LAND_MSG printf ("Hammurabi, think again."\
**" You own only %d acres. Now then,\n", acres)
#define SHORT_GRAIN_MSG printf ("Hammurabi, think again."\
**" You have only %d bushels of grain. Now then,\n", grain)

int pop, acres, grain, starved, born, yield, rats, food, year;

void resign (void) {
**printf ("Hammurabi, I can not do what you wish."
****" Get yourself another steward!\n");
**exit (0);
}

void endgame (int rank) {
**switch (rank) {
****case 0:
****printf ("Due to this extreme mismanagement you have not only been"
******" impeached\nand thrown out of office but you have been also declared"
******" a national fink!\n");
****break;
****case 1:
****printf ("You heavy handed performance smacks of Nero and Ivan IV."
******" The people\n(remaining) find you an unpleasant ruler and frankly"
******" hate your guts!!\n");
****break;
****case 2:
****printf ("Your performance could have been somewhat better but really"
******" wasn't\ntoo bad at all. %d people dearly would like to see you"
******" assassinated\nbut we all have our trivial problems.\n"
******, pop * (rand () % 80) / 100);
****break;
****default:
****printf ("A fantastic performance!!! Charlemagne, Disraeli, and Jefferson\n"
******"combined could not have done better!!\n");
**}
}

void report (void) {
**printf ("\n\nHammurabi, I beg to report to you;\n\n"
****"In year %d, %d people starved, %d came to the city.\n"
****, year, starved, born);
**if (rand() < (RAND_MAX / 100 * 15) && year > 1) {
****printf ("A horrible plague struck! Half the people died.\n");
****pop /= 2;
**}
**printf ("Population is now %d.\n"
****"The city now owns %d acres.\n"
****"You harvested %d bushels per acre.\n"
****"Rats ate %d bushels.\n"
****"You now have %d bushels in store.\n\n",
****pop, acres, yield, rats, grain);
}

void buysell (void) {
**int input, price;

**price = rand() % 10 + 17;
**printf ("Land is trading at %d bushels per acre.\n", price);
**printf ("How many acres do you wish to buy? ");
**scanf ("%d", &input);
**while (price * input > grain) {
******SHORT_GRAIN_MSG;
******printf ("how many do you wish to buy? ");
******scanf ("%d", &input);
**}
**if (input < 0) resign();
**if (input) {
****acres += input;
****grain -= price * input;
**} else {
****printf ("How man acres do you wish to sell? ");
****scanf ("%d", &input);
****while (input > acres) {
******SHORT_LAND_MSG;
******printf ("how many do you wish to buy? ");
******scanf ("%d", &input);
****}
****if (input < 0) resign ();
****acres -= input;
****grain += input * price;
**}
}

void feed (void) {
**do {
****printf ("How many bushels do you wish to feed your people? ");
****scanf ("%d", &food);
****if (food < 0) resign ();
****if (food > grain) SHORT_GRAIN_MSG;
**} while (food > grain);
}

void farm (void) {
**int input, v;

**do {
****v = 1;
****printf ("How many acres do you wish to plant with seed? ");
****scanf ("%d", &input);
****if (input < 0) resign ();
****else if (input > acres) {SHORT_LAND_MSG; v = 0;}
****else if (input / 2 > grain) {SHORT_GRAIN_MSG; v = 0;}
****else if (input > 10 * pop) {
******printf ("But you only have %d people to tend the fields! Now then,\n"
******, pop);
******v = 0;
****}
**} while (!v);
**grain -= input / 2;
**yield = rand () % 5 + 1;
**rats = rand () % 5 + 1;
**rats = (rats % 2) ? grain / rats : 0;
**grain += input * yield - rats;
}

int main (void) {
**int cstarved = 0;
**int cps = 0;

**srand (time (NULL));
**printf ("Hammurabi\n\n"
**"Try your hand at governing ancient summeria for a ten-year term of office.");
**pop = 100;
**grain = 2800;
**yield = 3;
**rats = 200;
**acres = 1000;
**born = 5;
**for (year = 1; year <= 10 && starved < pop * 45 / 100; year ++){
****report ();
****buysell ();
****feed ();
****farm ();
****born = ((rand () % 5 + 1) * (20 * acres + grain) / pop / 100) + 1;
****starved = (pop < food / 20) ? 0 : pop - food / 20;
****pop += born - starved;
****cstarved += starved;
****cps += starved * 100 / pop;
**}
**if (starved >= pop * 45 / 100) {
****printf ("\nYou starved %d people in one year!!!\n", starved);
****endgame (0);
**} else {
****year--;
****report ();
****cps /= 10;
****printf ("In your 10-year term of office %d%% of the people died per year\n"
******"on the average, IE a total of %d people died!\n", cps, cstarved);
****acres /= pop;
****printf ("You started with 10 acres per person and ended with %d acres per\n"
******"person.\n\n", acres);
****endgame ((cps<34 && acres>6)+(cps<11 && acres>8)+(cps<4 && acres>9));
**}
**exit (0);
}

The game is made tricky by having this out of logical order forcing you to calculate and plan ahead. This of course could be remidied by changing the order of the funciton calls in the main for loop in main. Ideally I should encapulate this so as to make them easier to find, but meh.

Keep 'em comming
  • Battleship (like the board game vs the computer)
  • Cel Life (multi-player version of John Conway's game of Life)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Flash Cards (with pretty output, practice your math)
  • Black Box (find molecules in the inky depths)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)
  • 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)

BeefontheBone 19-06-2006 05:38 PM

Oooh, Awari! My dad has a beautiful Awari board he got when he was in Africa - 's a great game.

guesst 22-06-2006 02:43 AM

@Beefonthebone - You should try this one. I think you'll find that even before it starts learning (which it only does when it loses) it'll regularly teach you a thing or two about playing the game. It's quite fun.

Without provocation or invition I will choose the next game, since no one cast a vote. Plus if all goes well I won't have time tomorrow...

Stars/Trap/Letter Guess

Oh yeah, 3 in one today. These games are all kind of variations on a theme. The sort of "guess what I'm thinking" games that entertained me so as a child. I figured no one would vote for these so I'm picking them before they're the last left on the field.

The benifit to these games is they are extremely simple and therefore extremly short. This is the sort of game that if you're writing your first game you'd want to write. (Not sure that came out ...good.) Two out of three of these are adapted from BASIC programs. I've linked the book that I got them from before, so I'm not going to worry about it now. I cracked all of these out in about a day. The challange was to not make them all look like I just edited a few lines between them. As they stand I'm not sure how successful I was at that. They all consist of only a main function and a few loops. They were just so small it seemed unnecessary to strech them out more than that.

They are also so abstract that, besides "Stars" I had nothing with which to make an illustration of. I haven't made illustrations for all of them, but the point is how would I even illustrate the first two? Ah well, here we go:

Letter Guess. This is the "higher/lower" sort of hint system. There exists a well defined method for finding the subject in question in the least number of guesses, so the game will actually tell you in the end if you took too long.

Technical note, I had actually inlined the BEFORE/AFTER bit, but took it out because as simple as the program is I didn't want to confuse new programmers with what is really a pretty odd looking bit of code.
Code:

/* Letter Guess Game
 * by Joseph Larson 2005
 * Inspired by the BASIC game 'Letter' written by Bob Albrecht
 * as found in 'BASIC Computer Games' edited by David H Ahl (c)1978
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

int main (void) {
**char input, goal;
**int num;

**srand(time(NULL));
**printf ("Guess My Letter Game\n\n");
**do {
****goal = rand() % 26 + 'A';
****num = 0;
****printf ("I have a letter between A and Z.\n");
****do {
******num ++;
******printf ("Guess #%d (A - Z) : ", num);
******do input = getchar (); while (!isalpha (input));
******input = toupper (input);
******if (input != goal) {
********printf ("\nNo, my letter comes ");
********if (input < goal) printf ("AFTER");
**********else printf ("BEFORE");
********printf (" your guess.\n");
******}
****} while (input != goal);
****printf ("\nYou got it! It took you %d tries to guess my letter.\n", num);
****if (num >= 4) printf ("I'm sure you could do better, though.\n");
****printf ("\nDo you want to play again? (y/n) ");
****do input = getchar (); while (!isalpha (input));
**} while ((input == 'y') || (input == 'Y'));
**printf ("\nGoodbye.\n");
**exit (0);
}

In Trap you try to surround the mystery number by choosing a high and a low number. Hints therefore come in 3 flavors, high, low, or trapped. To make the game more challenging you could make the high and low message exactly the same. Still, it's easy to develop a method to narrow your options fast.
Code:

/* Trap
 * written by Joseph Larson 2005
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

#define MAX 100
#define MG 8

int main (void) {
**int x, h, l, try, temp;
**char yesno;

**printf ("Trap\n----\n"
**"In this game you have to try to guess a number between 1 and %d by\n"
**"trapping it. Every guess you type a low and high number seperated by a\n"
**"comma (like \"15, 30\") and you'll be told if the number you are trying to\n"
**"find is between your number. When you think you have it type the same\n"
**"number for both the high and low guess. And remember, you only have %d\n"
**"guesses to find the number\n"
**"Good luck!\n\n", MAX, MG);
**srand (time (NULL));
**do {
****x = rand () % MAX + 1;
****printf ("I have a number. You have %d guesses.\n", MG);
****for (try = 1; try <= MG && !(l == h && h == x); try ++) {
******printf ("\nGuess %d (low , high) : ", try);
******scanf ("%d %*c %d", &l, &h);
******if (l > h) { temp = h; h = l; l = temp;}
******if (l <= x && x <= h)
********printf ("You've trapped my number.\n");
******else printf ("My number is %s than your guesses.\n",
******(l > x) ? "lower" : "higher");
****}
****if (l == h && h == x) printf ("I am undone! You caught my number.\n\n");
****else printf ("Ha ha! That's %d guesses. My number was %d.\n\n", MG, x);
****printf ("Do you want to do play again? (y/n) ");
****while (!isalpha (yesno = getchar ()));
**} while (tolower (yesno) == 'y');
**printf ("Until next time then!\n");
**exit (0);
}

The last is Stars. The hints in Stars are sort of a geiger counter giving a visual representation of how close you're getting to the target. You'll find jumping around too much will only confuse you. Creeping up on the number is a much better idea.
Code:

/* Seeing Stars */
/* By Joseph Larson 2005 */
/* Number guessing game inspired by the BASIC game "Stars" by Bob Albrecht */
/* as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978 */

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

#define MAX 100
#define MAX_GUESS 10

int main () {
**int goal, guess, c, wins, loses;
**char yesno;
**float d;
**
**srand(time(NULL));
**wins = 0;
**loses = 0;
**printf ("Seeing Stars\n------------\n"
**"This is a number guessing game with a twist. After every guess you\n"
**"will be given a number of stars to tell you how close you are to the\n"
**"number you are trying to guess. The more stars you see, the closer\n"
**"you are.\n"
**"You only have %d guesses, so think quick.\n\n", MAX_GUESS);
**do {
****goal = rand() % MAX + 1;
****guess = 0;
****printf ("\nI'm thinking of a number between 1 and %d.", MAX);
****for (c = 0; c < MAX_GUESS && guess != goal; c++) {
******printf ("\nWhat is your guess? ");
******scanf ("%d", &guess);
******for (d = MAX; (int)d > abs(guess - goal); d /= 2) printf ("**");
****}
****if (guess != goal) {
******printf ("\nSorry, thats %d guesses. My number was %d.\n", MAX_GUESS, goal);
******loses ++;
****} else {
******printf ("******\nBingo! You got my number.\n");
******wins ++;
****}
****printf ("Do you want to play again? (y/n) ");
****while (!isalpha (yesno = getchar()));
**} while (tolower (yesno) != 'n');
**printf ("\nWell then, you won %d out of %d games, or %d%%.\n",
****wins, wins + loses, wins * 100 / (wins + loses));
**exit (0);
}

Still plenty left. Tell me what looks good and I'll give it to you.
  • Battleship (like the board game vs the computer)
  • Cel Life (multi-player version of John Conway's game of Life)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Flash Cards (with pretty output, practice your math)
  • Black Box (find molecules in the inky depths)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Reverse (order a list of number by turning them around)

Blood-Pigggy 22-06-2006 04:52 AM

Cel Life, John Conway's Life was awesome.

Abi79 23-06-2006 07:19 AM

Battleship looks good.

guesst 23-06-2006 04:56 PM

@Abi79, you've gotten to pick the last few. I'm letting Blood-piggy choose. (Besides, he was first.) If no-one steps up after this one, then you're in the queue.

Cell Life
A Google search for John Conway's Game of life will provide more information on this than you ever wanted to know. (Wiki is also a good source)

Without taking up too much space, John Conway came up with a game that seems simple but in the end has proven to be the playground for the intelectual. The game is played on a grid, like a checker board. Markers are placed on the board. Then every "generation" the pieces live, die, or are born according to a simple set of rules:
  • A marker dies of lonelyness if it only has one or no neighbors.
  • A marker dies of overcrowing if it has neighbors on 5 or more sides.
  • Markers with two or three neighbors survive to the next generation.
  • A marker is born if an empty spot has exactly 3 neighbors.
In this program an attempt was made as giving ownership to the pieces so that two, three or four player games could be realized. So the last rule was modified thus
  • A marker is born when if an empty spot has exactly 3 neighbors. If at least two neighbors are the same type then the marker will be of that type. If no two neighbors are the same then a hybred is created.
In this game markers are called "cells" to give it an organic feel. To add an even more competitive edge to it, every generation players get to place one marker on the board to sway the game in their favor. The game is only won (at this time) with a 100% purging of the enemy cels. Thus games could potentially go on for a long time.
Here's a screenshot of a small three player game in action:
Code:

**12345
 1..@X.1
 2**OOX2
 3*..X.3
 4...*.4
 5.....5
**12345


Press ENTER to advance the generation:

Here's a large 4 player game (1 players already been elimitedy by now) in action:
Code:

************111111111122222
**1234567890123456789012345
 1........***..............1
 2.........................2
 3.......*..*..............3
 4........*..*.............4
 5.........**..............5
 6.........................6
 7.........................7
 8.........................8
 9............*............9
10..........XOX*...........10
11........XX...X...........11
12..........X..XX..........12
13........OX..XX...........13
14........O..XX............14
15..........XX.............15
16.........@...............16
17..........*O.............17
18..........*O.............18
**1234567890123456789012345
************111111111122222

Press ENTER to advance the generation:

I chose both screen shots because a hybred (@) had entered into the game.

Winning this game is a challange. Every turn the players rotate through who goes first. Going first is not an advantage because it's all to easy for your opponent to turn a birth into an overcrowing after they've seen what you're doing. However, this was the only way to insure that the game is played fair since, in this form, having everyone choose their move unseen isn't possible. Both methods have their advantages.

You can set the game for 4 computer players and just watch it go. This in and of itself is not uninteresting to see. But if you can master predicting the next generation just feel your brain grow.

Silly me, I haven't given you the code yet!
Code:

/* Cell Life
 * by Joseph Larson
 * based on a 2 player BASIC game by Bryan Wyvill
 * as found in 'BASIC Computer Games' edited by David H Ahl (c) 1978
 * which game was derived from John Conway's Game of Life
 * as found in Scientific America, October 1970
 */

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

#define F(a,b) for (a = 0; a < (b); a++)
#define DIG v * tp(5) + w * tp(4) + x * tp(3) + y * 100 + z * 10
#define TURN ((c + f + g) % players)
#define MAX_W 26
#define MAX_H 19
#define PIECES 3

int bd[MAX_W][MAX_H], dis[8][2], pop[5], surv[5][55], hyb[10];
int height, width, players;
char tokens[6] = ".OX*#@";

void intro (void) {
**printf ("Cell Life\n---------\n\n"
**"The rules of this game are based on Conway's Game of Life. Tokens are\n"
**"placed on the board, then with every generation a token will live, die, or\n"
**"be born based on these rules :"
**" o A token with 2 or 3 neighbors survives.\n"
**" o A token with more or less than 2 or 3 neighbors dies from lonelyness or\n"
**"** overpopulation.\n"
**" o An empty space with exactly 3 neighbors gives birth to a new token.\n\n"
**"When giving birth the player with the majority of the 3 neighbors of an\n"
**"empty cell gets the new cell. If no one has the majority (in the case of\n"
**"a 3 way tie) the cell becomes a hybred that no one controls.\n"
**"Remember to count the number of neighbors same as in minesweeper. In other\n"
**"words a cell can have up to 8 neighbors.\n\n"
**"The first three moves (Generation 0) are when you place your initial\n"
**"pieces.\n\n"
**"Remember to pay close attention to who's turn it is as every turn a\n"
**"different player gets to go first.\n\n"
**"Good Luck.\n\n");
}

int tp (int x) {return ((x == 0) ? 1 : 10 * tp (x - 1)); }

void init (void) {
**int p, v, w, x, y, z, c, i, sum;

**srand (time (NULL));
**F(p, 5) {
****i**= 0;
****F(v, 4) F(w, 4) F(x, 4) F(y, 4) F(z, 4) {
******sum = v + w + x + y + z;
******if (sum == 3 || sum == 2) surv[p][i++] = (p + 1) + DIG;
******else if (sum == 1)
********surv[p][i++] = DIG + 2 * tp(p + 1);
****}
**}
**i = 0;
**F(v, 2) F(w, 2) F(x, 2) F(y, 2) F(z, 2) {
****sum = v + w + x + y + z;
****if (sum == 3) hyb[i++] = DIG;
**}
**i = 0;
**F (x, 3) F (y, 3) if (!(x == y && y == 1)) {
****dis[i][0] = x - 1; dis[i++][1] = y - 1;
**}
}

void print_bd (void) {
**int x, y;

**printf ("**"); /* 2 spaces */
**F (x, width) putchar (" 12"[x / 10]);
**putchar ('\n');
**F (y, (height + 2))
****F (x, (width + 2))
******(!y || y > height) ? (!x) ? printf ("**") /* 2 spaces */
******: putchar ((x > width) ? '\n' : '0' + (x % 10))
******: (!x) ? printf ("%2d", y) : (x > width) ? printf ("%-2d\n", y)
******: putchar (tokens [bd[x][y] % 10]);
**printf ("**"); /* 2 spaces */
**F (x, width) putchar (" 1234"[x / 10]); putchar ('\n');
}

int survives (int x) {
**int k, p;

**F (p, 5) F(k, 55) if (surv[p][k] == x) return p + 1;
**F (k, 10) if (hyb[k] == x) return 5;
**return 0;
}

void generation (void) {
**int x, y, k, p;

**F (x, width + 1) F (y, height + 1) if (p = (bd[x][y] % 10))
****F (k, 8) bd[x + dis[k][0]][y + dis[k][1]] += tp (p);
**F (k, 5) pop[k] = 0;
**F (x, width + 2) F (y, height + 2)
****if (!y || y > height || !x || x > width) bd[x][y] = 0;
****else {
******bd[x][y] = survives (bd[x][y]);
******if (bd[x][y]) pop[bd[x][y] - 1]++;
****}
}

void getxy (int *x, int *y) {
**printf ("<X,Y>: ");
**scanf ("%d %*c %d", x, y);
**while (*x > width || *x < 1 || *y > height || *y < 1) {
****printf ("Invalad location. Retry. x,y : ");
****scanf ("%d %*c %d", x, y);
**}
}

void compyturn (int p, int g) {
**int x, y, c, d, bestx, besty, r, bestr, k;
**int bdc[MAX_W][MAX_H], popc[5];

**if (g <= PIECES) if (g == 1) {
****bestx = rand() % (width - 1) + 1;
****besty = rand() % (width - 1) + 1;
**} else {
****F (x, width) F (y, width) if (bd[x][y] == (p + 1)) {bestx = x; besty = y;}
****r = 0;
****do {
******k = rand () % 8;
******if (bd[bestx + dis[k][0]][besty + dis[k][1]]) k = -1;
******else if ((bestx + dis[k][0]) > width || (bestx + dis[k][0]) < 1) k = -1;
******else if ((besty + dis[k][1]) > height || (besty + dis[k][1]) < 1) k = -1;
****** r |= 1 << k;
****} while (k < 0 && r < 255);
****if (k < 0) {
******bestx = rand() % (width - 1) + 1; besty = rand() % (width - 1) + 1;
****} else { bestx += dis[k][0]; besty += dis[k][1]; }
**} else {
****F (c, height + 1) F (d, width + 1) bdc[c][d] = bd[c][d];
****F (k, 5) popc[k] = pop[k];
****bestx = rand() % (width - 1) + 1;
****besty = rand() % (width - 1) + 1;
****bestr = -99;
****F (y, height - 1) F (x, width - 1) if (!bd[x + 1][y + 1]) {
******bd[x + 1][y + 1] = p + 1;
******generation ();
******r = 0;
******F (k, 5) if (k == p) r += pop[k]; else r -= pop[k];
******if (r > bestr) {bestr = r; bestx = x + 1; besty = y + 1;}
******F (c, height + 1) F (d, width + 1) bd[c][d] = bdc[c][d];
******F (k, 5) pop[k] = popc[k];
****}
**}
**bd[bestx][besty] = p + 1;
**printf ("Computer Player %d (%c) : %d, %d\n", p + 1, tokens[p + 1], bestx, besty);
}

int winner (void) {
**int c, w = 0;

**F (c, players) if (pop[c]) if (w) return 0; else w = c + 1;
**return (w) ? w : 5;
}

int getint (int low, int high) {
**int t;

**scanf ("%d", &t);
**while (t < low || t > high) {
****printf ("Invalad. Choose a number between %d and %d : ", low, high);
****scanf ("%d", &t);
**}
**return t;
}

void play (void) {
**int c, d, f, x, y, comp[4], g = 0;

**printf ("How many players? (2 - 4) ");
**players = getint (2, 4);
**F(c, players) {
****printf ("Player %d, (1) human or (2) computer? : ", c + 1);
****comp[c] = getint (1, 2) - 1;
**}
**printf ("(1) Small or (2) large game? ");
**c = getint(1, 2);
**width = (--c) ? MAX_W - 1 : 5;
**height = (c) ? MAX_H - 1 : 5;
**f = rand() % players;
**printf ("Each player gets %d pieces to play.\n", PIECES);

**F (c, players) pop[c] = 1;
**do {
****g++;
****F (c, players) {
******if (pop[TURN]) {
********print_bd ();
********if (!comp[TURN]) {
**********printf ("Generation %d, player %d (%c) ", (g < PIECES) ? 0 : g - PIECES
************, TURN + 1, tokens[TURN + 1]);
**********getxy (&x, &y);
**********if (bd[x][y]) printf ("Occupied. Turn discarded.\n");
**********else bd[x][y] = TURN + 1;
********} else compyturn (TURN, g);
******}
****}
****if (g >= PIECES) {
******print_bd ();
******printf ("\nPress ENTER to advance the generation:\n");
******getchar (); getchar ();
******generation ();
****}
**} while ((g < 0) || !(d = winner ()));

**print_bd();
**printf ((d == 5) ? "\n\nTotal extinction." :
****(d == 4) ? "\n\nHybred takeover!" : "\n\nPlayer %d wins!", d);
}

int main (void){
**intro ();
**init ();
**play ();
**getchar ();
**exit (0);
}

This particular code bears less resemblance to the BASIC game that inspired it. I've taken many liberties with it, but for those who are interested you can see the original here. The BASIC game is surprisingly compact, but at the same time not as robust as this program.

This is a game that would probably be better suited to something more graphical. In this form it's a bit hard to play. But then again, if you're the sort of person for whom Conway's Game of Life holds your interest something like console graphics is no turn off.

Abi put in a vote for Battleship next, and since i love my regurar reader (wish I could put an 's' there) that'll probably be next, but feel free to queue up your preference :
  • Battleship (like the board game vs the computer)
  • Reverse (order a list of number by turning them around)
  • Black Box (find molecules in the inky depths)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Flash Cards (with pretty output, practice your math)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)

guesst 30-06-2006 04:23 AM

Sorry, I've been at school all week, so I've been unable to update with this program. But maybe absense has mad all yawl's hears go fonder. So you should be very excited to finally have...

Battleship

This is the biggest program that I have to contribute. However, it is a game that should need little introduction. Battleship. Place your ships, hunt theirs, hope you win. The computer plays against you on this one. The routine for choosing where to shoot is not the best out there, but it's not entirely stupid either.

Here's what the game looks like in play:
Code:

Your shot coordinates : f9
Miss.

My shot : g4
HIT!
I sunk your cruser.
****** R A D A R********************** F L E E T
_ 1 2 3 4 5 6 7 8 9 10**********_ 1 2 3 4 5 6 7 8 9 10
a . . . . . . . . . .********** a . . . . . o . . . .
b . . . . . . . . . .********** b . . . . . . . . . .
c o . . . . . . . . .********** c . . 2 2 2 . . . . .
d X . o . . . . . . .********** d . . . . . . . . . 5
e X . . . . . . . . .********** e . . . . 1 1 . . . 5
f X . . . o . . . o .********** f . o o . 4 4 4 4 . 5
g X . . . . o . . . .********** g o X X X . . . . . 5
h . . . . . . o . . .********** h . o . . . . . . . 5
i . . . . . . . . . .********** i . . . . . . . o . o
j . . . . . . . . o .********** j . . . . o . . . . .
****carrier : #####**************** carrier : #####
 battleship : SUNK************** battleship : ####
**** cruser : ###********************cruser : ...
**submarine : ###**************** submarine : ###
****pt ship : ##********************pt ship : ##

Your shot coordinates :c5

You may notice that the game is set up side-by-side instead of up and down like a battleship game in real life is. This is purely because up and down didn't fit, but side to side fits with enough room for you to see the results of the previous move, which is a good thing because that's where it says when you sink something.

So why don't we just get to the code:
Code:

/* Batttleship (R)
 * written by Joseph Larson 2005
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <math.h>

#define PL 0
#define CP 1
#define FULL(x) ((x + (x < 2)) + 1)
#define ADD(a,b) if (!bd[a][b].chit) {t[i].x = a; t[i].y = b; i++;}

typedef struct {
**unsigned int x : 4;
**unsigned int y : 4;
} COORD;

typedef struct {
**unsigned int pship : 3;
**unsigned int chit : 1;
**unsigned int cship : 3;
**unsigned int phit :3;
} GRID;

GRID bd[10][10];
COORD t[51];
char ship_life[2][5];
char *ship_name[5] = {"pt ship", "submarine", "cruser", "battleship", "carrier"};

COORD getloc (void) {
**char input[10];
**COORD loc;

**loc.x = loc.y = input[0] = 0;
**do {
****if (input[0]) printf ("Invalad location, letter first then number : ");
****scanf ("%s", input);
****if (isalpha (input[0]) && (loc.x = atoi (&input[1]))) {
******loc.y = tolower (input[0]) - 'a';
******if (loc.y > 9 || loc.x > 10 || loc.x < 0) loc.x = 0;
****}
**} while (!loc.x);
**loc.x --;
**return loc;
}

void show_board (void) {
**int x, y;
**
**printf ("%16s\t\t%16s\n_ 1 2 3 4 5 6 7 8 9 10\t\t_ 1 2 3 4 5 6 7 8 9 10"
****,"R A D A R","F L E E T");
**for (y = 0; y < 10; y++) {
****printf ("\n%c ", y + 'a');
****for (x = 0; x < 10; x++)
******printf ("%c ", (bd[x][y].phit) ? (bd[x][y].cship) ? 'X' : 'o' : '.');
****printf ("\t\t%c ", y + 'a');
****for (x = 0; x < 10; x++)
******printf ("%c ", (bd[x][y].chit) ? (bd[x][y].pship) ? 'X'
******: 'o' : ".12345"[bd[x][y].pship]);
**}
**for (y = 4; y >= 0; y--) {
****printf ("\n %10s : ", ship_name[y]);
****if (ship_life[CP][y]) for(x = 0; x < FULL(y); x++) putchar ('#');
****else printf ("SUNK");
****printf ("\t\t %10s : ", ship_name[y]);
****for (x = 0; x < FULL(y); x++) putchar (".#"[ship_life[PL][y] > x]);
**}
}

int valad_ship (COORD s, COORD e, int c) {
**int v, check, d;
**COORD step;
**
**check = abs ((s.x + 10 * s.y) - (e.x + 10 * e.y));
**if (check % (FULL(c) - 1)) {
****printf ("\nInvalad location. The %s is only %d long\n"
************"and ships can only be placed vertical or horizontal.\n",
************ship_name[c], FULL(c));
****v = 0;
**} else {
****step.x = step.y = 0;
****if ((check / (FULL(c) - 1)) - 1) step.y = 1;
****else step.x = 1;
****if (s.x > e.x) s.x = e.x;
****if (s.y > e.y) s.y = e.y;
****for (d = 0; d < FULL(c) && v; d++) {
******check = bd[s.x + d * step.x][s.y + d * step.y].pship;
******if (check && check != 7) {
********printf ("\nInvalad location. Ships can not overlap.\n");
********v = 0;
******}
****}
**}
**if (v) for (d = 0; d < FULL(c); d++)
****bd[s.x + d * step.x][s.y + d * step.y].pship = c + 1;
**return v;
}

void player_setup (void) {
**int ship, d;
**COORD start, end;
**
**for (ship = 4; ship >= 0; ship--)
****do {
******show_board ();
******printf ("\nEnter start location for your %s : ", ship_name[ship]);
******start = getloc();
******printf ("Enter end location (length %d) : ", FULL(ship));
******end = getloc();
****} while (!valad_ship (start, end, ship));
**show_board ();
}

void auto_setup (int pl) {
**COORD s, step;
**int c, d;
**
**for (c = 0; c < 5; c++) {
****do {
******s.x = rand() % 10; s.y = rand() % 10;
******step.x = step.y = 0;
******if (rand() < RAND_MAX / 2) {
********step.x = 1;
********if (s.x + FULL(c) > 10) s.x -= FULL(c);
******} else {
********step.y = 1;
********if (s.y + FULL(c) > 10) s.y -= FULL(c);
******}
******for (d = 0; d < FULL(c) &&
******(pl) ? !bd[s.x + d * step.x][s.y + d * step.y].cship
******: !bd[s.x + d * step.x][s.y + d * step.y].pship; d++);
****} while (d < FULL(c));
****for (d = 0; d < FULL(c); d++)
******(pl) ? bd[s.x + d * step.x][s.y + d * step.y].cship
******: bd[s.x + d * step.x][s.y + d * step.y].pship = c + 1;
**}
}

void init (void) {
**int c, d;
**char input;
**
**srand (time (NULL));
**for (c = 0; c < 10; c++)
****for (d = 0; d < 10; d++)
******bd[c][d].pship = bd[c][d].chit = bd[c][d].cship = bd[c][d].phit = 0;
**for (c = 0; c < 5; c++)
****ship_life[PL][c] = ship_life[CP][c] = FULL(c);
**printf ("Battleship (R)\n\nDo you want (A)uto or (M)anual setup ? (a/m) ");
**while (!isalpha (input = getchar()));
**if (tolower (input) == 'm')
****player_setup ();
**else auto_setup (PL);
**auto_setup (CP);
}

int check_for_lose (int player) {
**int c;
**
**for (c = 0; c < 5 && !ship_life[player][c]; c++);
**return (c == 5);
}

void player_turn (void) {
**COORD shot;
**int ship;
**
**show_board ();
**printf ("\n\nYour shot coordinates : ");
**shot = getloc ();
**if (bd[shot.x][shot.y].phit)
****printf ("A wasted shot! You already fired there!\n");
**else {
****bd[shot.x][shot.y].phit = 1;
****if (ship = bd[shot.x][shot.y].cship) {
******printf ("HIT!\n");
******if (!(--ship_life[CP][--ship]))
********printf ("You sunk my %s.\n",ship_name[ship]);
****} else printf ("Miss.\n");
**}
}

int hit_no_sink (int x, int y) {
**if (bd[x][y].chit)
****if (bd[x][y].pship == 7)
******return 1;
****else if (bd[x][y].pship)
******if (ship_life[PL][bd[x][y].pship - 1])
********return 1;
**return 0;
}

int fill_t (void) {
**COORD c, d;
**int m[5] = {0, 1, 0, -1, 0};
**int x, i = 0;
**
**for (c.x = 0; c.x < 10; c.x++)
****for (c.y = 0; c.y < 10; c.y++)
******if (hit_no_sink (c.x,c.y)) {
********for (x = 0; x < 4; x++)
**********if (c.x + m[x] >= 0 && c.x + m[x] < 10
************&& c.y + m[x + 1] >= 0 && c.y + m[x + 1] < 10) {
************if (hit_no_sink (c.x + m[x], c.y + m[x + 1])) {
**************d.x = c.x; d.y = c.y;
**************while (d.x >= 0 && d.x < 10 && d.y >= 0 && d.y < 10
****************&& hit_no_sink (d.x, d.y)) {d.x -= m[x]; d.y -= m[x + 1];}
**************if (d.x >= 0 && d.x < 10 && d.y >= 0 && d.y < 10) ADD (d.x, d.y);
************}
**********}
********if (!i)
**********for (x = 0; x < 4; x++)
************if (c.x + m[x] >= 0 && c.x + m[x] < 10
**************&& c.y + m[x + 1] >= 0 && c.y + m[x + 1] < 10)
**************ADD (c.x + m[x], c.y + m[x + 1]);
******}
**if (!i)
****for (c.x = 0; c.x < 10; c.x++)
******for (c.y = 0; c.y < 10; c.y++)
********if ((c.x + c.y) % 2) ADD (c.x, c.y);
**return i;
}

void compy_turn (void) {
**int z, c, d, v;
**char input;
**COORD s, e;
**
**c = fill_t ();
**z = rand () % c;
**printf ("\nMy shot : %c%d\n", t[z].y + 'a', t[z].x + 1);
**bd[t[z].x][t[z].y].chit = 1;
**if (c = bd[t[z].x][t[z].y].pship) {
****printf ("HIT!\n");
****if (!(--ship_life[PL][c - 1]))
******printf ("I sunk your %s.\n", ship_name[c - 1]);
**} else printf ("Miss.\n");
}

void play (void) {
**int winner = 0;
**
**if (rand () < RAND_MAX / 2) {
****printf ("\nYou go first.\n");
****player_turn ();
**} else printf ("\nI'll go first.\n");
**do {
****compy_turn ();
****if (check_for_lose (PL)) {
******winner = 1;
******printf ("\nI win!\n");
****} else {
******player_turn ();
******if (check_for_lose (CP)) {
********winner = 1;
********printf ("\nYou win!\n");
******}
****}
**} while (!winner);
**show_board ();
}

int play_again (void) {
**char input;

**printf ("\nDo you wish to play again? (y/n) ");
**while (!isalpha (input = getchar()));
**if (tolower (input) != 'n') return 1;
**else return 0;
}

int main (void) {
**init ();
**do {play ();} while (play_again ());
**printf ("\nIt's been fun! So long Admiral!\n");
**exit (0);
}

Techinal note; the way the computer chooses it's shot is mostly handled by the function fill_t, or "fill target list." The comptuer analizes the board and makes a list of the best shots. If it's made an isolated hit, it fills the list with the spaces up, down, left and right of it, provided they're not already misses. If it's made two hits in a row it fills the list with the shots at the end, provided they're not already misses. If the list is still 0 in length, or it hasn't found any potential targets up to now, then the list is populated with ever other shot, resulting in a checkerboard pattern of possibilities. (No point in missing 3 in a row if the smallest ship is 2 in length.) Then it just chooses randomly from this list. Check it out and see if you can see this in action.

Now, if a clever programmer out there want to try to make a smaller version of this, go say for it. I'm actually disapointed with how humongus this is. This, Awari, and Cell I wish I could reduce a bit.

Now is when I beg you for you support. How do you support this great project? Just choose a program from the following list and tell me you want to play it. Because as long as this has got your support we're not stopping until the list is empty:
  • Reverse (order a list of number by turning them around)
  • Black Box (find molecules in the inky depths)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Flash Cards (with pretty output, practice your math)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)

Abi79 01-07-2006 10:20 AM

There's a small lil' problem...or maybe two problems.

1. Even if I've saved the file as a *.c, when I tried to run it in BorlandC++ for DOS, I got the following error message:
"Lvalue required" at
Code:

: bd[s.x + d * step.x][s.y + d * step.y].pship = c + 1;
I've fixed this (added another = before c + 1) and then I've started the game.

Setup: auto
At the fleet screen, I couldn't see any of my ships. I've ignored that and chosed to attack c5. Of course I missed (I always lose in games :P ), and the computer started it's turn. But nothing happened. Following the using of the ingenious key combo CTRL+Break, I managed to see that the computer entered a loop.

Code:

int hit_no_sink (int x, int y) {
**if (bd[x][y].chit)**// bd[x][y].chit=0
//*skips rest of code*
**return 0;
}

Then it goes to
Code:

if (hit_no_sink (c.x,c.y)) {**
/*starts hit_no_sink and does the same thing as above; it doesn't go further because hit_no_sink always returns 0*/

For Setup: manual the computer does the same thing, after I finish choosing the locations of my ships and he starts his turn.

What might cause the problem?

guesst 02-07-2006 03:45 AM

I guess this means I have to install Borland compiler. I know it workes in DevC++ because the screenshot you see is taken from an on-the-fly compile of the exact code that got copy/pasted into the post.

It's true, tho, that not all compilers are the same. I've known this for some time. I can't promise I'll be able to get to this any time soon, so until then, what's your next vote for the project?

Abi79 04-07-2006 01:36 PM

Sorry for the late reply. I was a bit busy. :(

Anyway, my next vote is Black Box.

guesst 10-07-2006 11:57 PM

I'm trying to make up for all the things I promised I'd do but haven't yet done. I'm such a slacker and Cymon's Games has suffered.

Not that anyone but Abi79 even cares.

But, in Pennance I bring you today:
BlackBox

Unfortunately there are better games I could have done my pennance with. This game isn't particularly cool to see played. To get the most out of it you should really play with a piece of graph paper next to you to take notes on. The purpose of the game is to discover the location of 6 spots in a 10x10 field. You can't see the field (it's covered) but you can shoot rays into it and observe where they exit, which will tell you likely places where the spots can be found.

The game actually contains pretty detailed instructions on how the ray reacts to the spots, so I'm gonna let it do all the talking:
Code:

/* Blackbox or AtomSweeper
 * written by Joseph Larson
 * based on a BASIC program 'Blackbox' by Jeff Keton
 * as found in 'More Basic Computer Games' edited by David H. Ahl (c) 1979
 */

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

#define SIZE 10
#define NUM 6
#define FS(a) for (a = 1; a <= SIZE; a++)
#define RS (rand () % (SIZE - 2) + 2)

void drawbox (int b[][SIZE + 2], int opt) { // 1: input coords 2: xy coords
**int x, y;
**
**printf ("\n**");
**FS(x) printf(" %c",(opt < 2) ? '0' + ((4 * SIZE - x + 1) / 10)
****: " 123"[(x / 10)]);
**printf ("\n**");
**FS(x) printf(" %c",'0' + ((opt < 2) ? ((4 * SIZE - x + 1) % 10) : (x % 10)));
**FS(y) {
****printf ("\n%2d", y);
****FS(x) printf (" %c", (opt < 3) ? '+' : (b[x][y]) ? 'O' : '.');
****if (opt < 2) printf (" %-2d", 3 * SIZE - y + 1);
**}
**if (opt < 2) {
****printf ("\n**");
****FS(x) printf(" %c"," 1234"[(SIZE + x) / 10]);
****printf ("\n**");
****FS(x) printf(" %c",'0' + ((SIZE + x) % 10));
**}
**printf("\n\n");
}

void intro (void) {
**printf ("BlackBox\n--------\n"
**"Try to find atoms that are hidden in a Black Box by firing rays into the\n"
**"box and observing where they emerge.\n"
**" 1) A ray that enters a square diagonal to an atom, so that it would be\n"
**"****next to the atom if it continued, is deflected 90 degrees.\n"
**" 2) A ray that is fired directly at an atom is reflected back the way it\n"
**"****came. It will emerge where it was fired.\n"
**" 3) A ray that is traveling so as to pass between two atoms that are one\n"
**"****square away will also be reflected.\n"
**"\t......\n"
**"\t...O..**********\t\t.....****...O\n"
**"\t--\\...Deflection\t\t---O. or ---. Reflection\n"
**"\t..|...**********\t\t.....****...O\n\n"
**"Input the starting place of the ray you want to fire by typing the\n"
**"cooresponding number on the illustration you will be given at the start\n"
**"of the game.\n"
**"If you need to see this illustration again or want to guess the\n"
**"location of the atoms input 0 (zero) for your move.\n"
**"You will gain one point for every reflection, two for every deflection,\n"
**"and 15 for every atom guessed incorrectly. Try for the lowest score!\n\n"
**"Press ENTER to begin.\n");
**getchar ();
}

void setup (int b[][SIZE + 2]) {
**int x, y, c;

**for (x = 0; x < SIZE + 2; x++) for (y = 0; y < SIZE + 2; y++) b[x][y] = 0;
**for (c = 0; c < NUM; c++) {while (b[x = RS][y = RS]); b[x][y] = 1;
**}
**printf ("%d atoms hidden.\n", NUM);
}

int shoot (int start, int b[][SIZE + 2]) {
**int x, y, dx, dy, temp;

**switch ((start - 1) / (SIZE)) {
****case 0 : x = 1; y = start; dx = 1; dy = 0; break;
****case 1 : x = start - SIZE; y = SIZE; dx = 0; dy = -1; break;
****case 2 : x = SIZE; y = 3 * SIZE + 1 - start; dx = -1; dy = 0; break;
****case 3 : x = 4 * SIZE + 1 - start; y = 1; dx = 0; dy = 1;
**}
**while (1) {
****switch ((b[x][y] * 7) | (2 * b[x + 1][y - 1] + 2 * b[x - 1][y + 1]
******+ b[x + 1][y + 1] + b[x - 1][y - 1])) {
******case 1 : temp = dx; dx = -dy; dy = -temp; break;
******case 2 : temp = dx; dx = dy; dy = temp; break;
******case 3 :
******case 7 : puts ("The shot was reflected."); return 1;
****}
****x += dx; y += dy;
****if (!(x % (SIZE + 1)) || !(y % (SIZE + 1))) {
******if (!x) temp = y;
******else if (!y) temp = 4 * SIZE - x + 1;
******else if (x > SIZE) temp = 3 * SIZE - y + 1;
******else temp = SIZE + x;
******printf ("Ray exited at %d.\n", temp);
******return 2;
****}
**}
}

int endgame (int b[][SIZE + 2], int *s) {
**int c, x, y;
**char input;
**
**printf ("Do you want to guess now? (y/n) ");
**while (!isalpha (input = getchar ()));
**if (tolower(input) != 'y') {
****drawbox(b, 1);
****return 0;
**}
**drawbox(b, 2);
**for (c = 0; c < NUM; c++) {
****printf ("What is the location of atom #%d? <x,y> ", c);
****scanf ("%d %*c %d", &x, &y);
****if (b[x][y] == 1) {
******puts ("\nCorrect");
******b[x][y] = 10;
****} else {
******puts ("\nIncorrect. Plus 15 points.");
*******s += 15;
****}
**}
**printf ("\nYour final score : %d\nHere's the Blackbox.\n**", *s);
**drawbox (b, 3);
**return 1;
}

int playmore (void) {
**char yesno;

**printf ("\nWould you like to play again? ");
**while (!isalpha (yesno = getchar ()));
**if (tolower(yesno) != 'n') return 1;
**return 0;
}


int main (void) {
**int board[SIZE + 2][SIZE + 2], ray, score, done;

**srand (time (NULL));
**intro ();
**do {
****setup (board);
****score = 0;
****drawbox (board, 1);
****done = 0;
****do {
******printf ("Ray # ? ");
******scanf ("%d", &ray);
******if (ray && ray < 4 * SIZE) score += shoot (ray, board);
******if (!ray) done = endgame (board, &score);
****} while (!done);
**} while (playmore ());
**puts ("Goodbye!");
**exit (0);
}

Oh, and I forgot to mention that, yes, this one is a BASIC conversion with liberty taken on the fact that I didn't like the way edge spots were handled, so I made it so no spots would ever be edge spots, and changed absorption to reflection to increase potential mis-direction.

This is a game of solitare where the object is to perfect your technique to get the most acurate reading with the fewest hints. If you find 6 spots on a 10x10 field not to your liking, the code is very happy, if you change a few constants at the top, to customize for you.

Now, I know it's been a while, but the problem was I didn't have my programs with me, and darned if I was going to waste my weekends with my wife and kids on the computer. But now I have the programs with me at school and nothing better to do all day long, so expect the rest of the list to fly by. Only a few left. Make your choice or, if no one chooses, I'll choose for you. But as always, I love your feedback!
  • Reverse (order a list of number by turning them around)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Flash Cards (with pretty output, practice your math)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)

Abi79 13-07-2006 12:23 PM

Sorry for answering so late, but something happened to my Internet connection. The good part is that today, when I called the customer support, the one who responded actually knew what I was talking about, and in 30 minutes my connection started working again. Romanian Data Systems rocks. :P

I choose...FlashCards. Me likey math. :D

guesst 13-07-2006 02:52 PM

<div align="center">FLASH CARDS</div>
The name says it all. This is a perfect oporutinty to practice your basic math skills, addition, subraction, multplication and division. At the end of your session (defined in length by the NUM constant) your score will be added up and you will be assigned a grade.

Flash Cards uses binary data, encoded in decimal form, to make the shapes of the form. Take the data listed in the shape array at the top of the program, write them out in binary form (1's and 0's) and stack them on top of each other to see how it works. The drawline routine is the one that decodes the data sent to it. A line variable is loaded with what each of the 6 characters per line will be. Then it looks for that numbered shape in the shape array and uses that data to output the numbers. #20 is blank, because #0 is the number 0, so that #1 can be 1 and so on. After 0-9 comes the plus sign, the minus sign, ect, two equals signs, the strike icon (for when you get an answer wrong), three icons for when you get an answer right, and finally the blank space.

For fun, change the data in the shape array and see if you can't make your own style of numbering!
Code:

/* Flash Cards
 * by Joseph Larson 2005
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NUM 25
 
int shape[21][9] = {
**{ 28,**54,**99,**99,**99,**99,**99,**54,**28},
**{ 24,**28,**30,**24,**24,**24,**24,**24, 126},
**{ 62,**99,**99,**48,**24,**12,** 6,** 7, 127},
**{127,**96, 112,**48,**56,**96,**99,**99,**62},
**{ 32,**48,**52,**54,**54,**51, 127,**48,**48},
**{127,** 3,** 3,** 3,**63,**96,**99,**51,**30},
**{ 56,**12,** 6,** 3,**63,**99,**99,**99,**62},
**{127,**99,**48,**48,**24,**24,**12,**12,**12},
**{ 28,**54,**54,**28,**54,**99,**99,**54,**28},
**{ 62,**99,**99,**99, 126,**96,**48,**24,**14},
**{**0,**24,**24, 126, 126,**24,**24,** 0,** 0},
**{**0,** 0,** 0, 126, 126,** 0,** 0,** 0,** 0},
**{**0,** 0, 102,**60,**24,**60, 102,** 0,** 0},
**{**0,**24,** 0, 126, 126,** 0,**24,** 0,** 0},
**{**0, 126, 126,** 0,** 0, 126, 126,** 0,** 0},
**{**0,** 0,** 0, 255, 255,** 0,** 0,** 0,** 0},
**{**0, 255, 231, 189, 153, 189, 231, 255,** 0},
**{112, 140, 146,**80, 248, 136, 136, 132,** 4},
**{**0,** 0,**12,**96,**84, 234, 246,**73,**56},
**{128, 166, 146,**61, 139,**58,** 6,** 0,** 0},
**{**0,** 0,** 0,** 0,** 0,** 0,** 0,** 0,** 0}};
char *name[21] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six",
 "Seven", "Eight", "Nine", "Plus", "Minus", "Times", "Into", "Equals", "Equals",
 "Strike", "Right", "htRig", "ightR", " "};

void drawline (const int msg[6]) {
**int ch, col, row;

**for (row = 0; row < 9; row ++) {
****for (ch = 0; ch < 6; ch ++) for (col = 0; col < 8; col ++)
******putchar ((shape[msg[ch]][row] & 1 << col) ?
******name[msg[ch]][(col + row) % strlen (name[msg[ch]])] : ' ');
****putchar ('\n');
**}
**putchar ('\n');
}

int main (void) {
**int op, max, q1, q2, ans, input, strikes, s, v, z, line[6], score[4];
**double cscore;

**srand (time (NULL)); s = 0;
**printf ("Choose an option:\n 1) Addition (easy)\n 2) Addition (hard)\n"
****" 3) Subtraction (easy)\n 4) Subtraction (hard)\n"
****" 5) Multiplication\n 6) Division\n 7) Shuffle\n ? ");
**scanf("%d", &input);
**while (input < 1 || input > 7) {
****printf ("Please type a number between 1 and 7 ? "); scanf("%d", input);
**}
**switch (input) {
****case 1 : max = 10; op = 1; break;
****case 2 : max = 99; op = 1; break;
****case 3 : max = 10; op = 2; break;
****case 4 : max = 99; op = 2; break;
****case 5 : max = 10; op = 3; break;
****case 6 : max = 10; op = 4; break;
****case 7 : max = 10; s = 1;
**}
**for (z = 0; z < 4; z++) score[z] = 0;
**for (z = 0; z < NUM; z++) {
****q1 = rand () % max; q2 = rand () % (max - 1) + 1; ans = rand () % max;
****v = (rand () < RAND_MAX / 2);
****strikes = 0;
****if (s) op = rand () % 4 + 1;
****switch (op) {
******case 1 : ans = q1 + q2; break;
******case 2 : if (q1 < q2) {q1 ^= q2; q2 ^= q1; q1 ^= q2;}
************** ans = q1 - q2; break;
******case 3 : ans = q1 * q2; break;
******case 4 : q1 = ans * q2; ans = q1 / q2; break;
****}
****do {
******if (v) {
********line[0] = (q1 / 10) ? (q1 / 10) : 20;
********line[1] = q1 % 10;
********line[2] = 9 + op;
********line[3] = (q2 / 10) ? (q2 / 10) : 20;
********line[4] = q2 % 10;
********line[5] = 14;
********drawline (line);
******} else {
********line[0] = line[1] = line[4] = line[5] = 20;
********line[2] = (q1 / 10) ? (q1 / 10) : 20;
********line[3] = q1 % 10;
********drawline (line);
********line[0] = line[4] = line[5] = 20;
********line[1] = 9 + op;
********line[2] = (q2 / 10) ? (q2 / 10) : 20;
********line[3] = q2 % 10;
********drawline (line);
********line[0] = line[4] = line[5] = 20;
********line[1] = line[2] = line[3] = 15;
********drawline (line);
******}
******scanf("%d", &input);
******if (input != ans) {
********line[0] = line[2] = line[4] = 20;
********line[1] = (++strikes > 1) ? 16 : 20;
********line[3] = 16;
********line[5] = (strikes > 2) ? 16 : 20;
********drawline (line);
******}
****} while (input != ans && strikes < 3);
****line[0] = line[1] = line[4] = line[5] = 20;
****line[2] = (ans / 10) ? (ans / 10) : 20;;
****line[3] = ans % 10;
****drawline (line);
****if (input == ans) {
******line[0] = line[4] = line[5] = 20;
******line[1] = 17;
******line[2] = 18;
******line[3] = 19;
******drawline (line);
****}
****score[strikes] ++;
****puts ("Press any key...");
****getchar (); getchar ();
**}
**printf ("Report Card\n------ ----\n\n"
****"Out of %d:\n %d on first try (%2.1f%%)\n %d on second try (%2.1f%%)\n %d on"
****" last try (%2.1f%%)\n %d missed (%2.1f%%)\n\n",
****NUM, score[0], (float)score[0] * 100 / NUM,
****score[1], (float)score[1] * 100 / NUM,
****score[2], (float)score[2] * 100 / NUM,
****score[3], (float)score[3] * 100 / NUM);
**cscore = (float)score[0] * 100.0 / NUM + (float)score[1] * 50.0 / NUM +
****(float)score[2] * 25.0 / NUM;
**printf ("Grade: %c, (%2.2f%%)\n", 'A' + (cscore < 90.0) + (cscore < 80.0)
****+ (cscore < 70.0) + 2 * (cscore < 60.0), cscore);
**exit (0);
}

Be aware. This game uses a non-standard screen size. It sometimes wants more lines than an average DOS window is willing to give. If you're running it in a DOS windows and can't make it longer change the line
Code:

****v = (rand () < RAND_MAX / 2);
to
Code:

****v = 1;
I love you all, you are my people, and the list is getting shorter. We're in the home strech, so what's next?
  • Reverse (order a list of number by turning them around)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Hangman (guess the word before you dangle)
  • Rotate (like those sliding block puzzles but that you rotate pieces)

Abi79 15-07-2006 01:34 PM

You love us? Oh, my... *faints* :P

As for this program, I was pretty impressed by the flag made out of "right" and the numbers made out of, well numbers. (I would have made them all by hand :D ) Still, it took me some time to understand that those were numbers...but I got it in the end, when I switched from Full Screen to Window. Another friend of mine had the same problem with the Maze. He just couldn't understand what those lines (the wall) were. :P (and he had never heard before of Fog of War, so he didn't even know why the map wasn't revealed to him; poor guy...)

As for the next program...Hangman is what I choose.

guesst 17-07-2006 07:03 PM

<div align="center">HangMan</div>

Now, whenever I'm at a loss for words, the worst that happens is I make a fool of myself. However, in HangMan being at a loss for words is a life and death stuation.

In this game the "graphics" are designed so to take up the fewest lines of code. Consequently it can be said that they suck. In order to see a fully hanged man you need to tilt your head 90 degrees to the left. Here is what the fully hung man looks like:
Code:

****************** O ||
||****@**/==O /===// ||
||-O):o{)X###]<******||
||\** @**\==O \===\\ ||
||\\************** O ||
|==========AEOQMBCDPR||

Can you see it?

If you don't like the way the graphic looks you can re-write the drawgallows() routine yourself to draw the gallows according to how much of the player is left. 10 is hung, 0 is empty. Post your drawgallows routine here if you make one! (I know I'd love to see a better one.)

Code:

/* Hangman
 * by Joseph Larson 2005
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <ctype.h>

char missed[11] = "==========";
char dict[255][25] = {"artfull", "baton", "brazier", "create", "disgard",
**"flight", "great", "hydrant", "justify", "lacerate", "master", "niagra" ,
**"oxygen", "pieces", "question", "rough", "sachet", "trumpet", "vestibule"};
int dictnum = 19;

void drawgallows (int d) {
**printf ("\n****************** %c ||\n", d < 9 ? ' ' : 'O');
**printf ("||****%c**%s%s%s%s ||\n", d < 1 ? ' ' : '@', d < 3 ? "** " : "/==",
****d < 7 ? "**" : "O ", d < 5 ? "****" : "/===", d < 9 ? "**" : "//");
**printf ("||%s%s******||\n", d < 1 ? "--ss(O)" : "-O):o{)",
****d < 2 ? "******" : "X###]<");
**printf ("||\\** %c**%s%s%s%s ||\n", d < 1 ? ' ' : '@', d < 4 ? "** " : "\\==",
****d < 8 ? "**" : "O ", d < 6 ? "****" : "\\===", d < 10 ? "**" : "\\\\");
**printf ("||\\\\************** %c ||\n", d < 10 ? ' ' : 'O');
**printf ("|==========%s||\n\n", missed);
}

void play (void) {
unsigned long guessed = 0;
char *word, input;
int c, found, nummissed = 0;

**for (c = 0; c < 10; c++) missed[c] = '=';
**c = rand () % dictnum;
**word = dict[c];
**guessed = ULONG_MAX << strlen (word);
**for (c = 0; c < strlen (word); c++)
****if (toupper(word[c]) < 'A' || toupper(word[c]) > 'Z')
******guessed |= (1 << c);
**do {
****drawgallows (nummissed);
****for (c = 0; c < strlen (word); c++)
******putchar (guessed & (1 << c) ? word[c] : '-');
****printf ("\nWhat is your guess? "); input = getche ();
****found = 0;
****for (c = 0; c < strlen (word); c++)
******if (toupper(word[c]) == toupper(input)) {
********found = 1;
********guessed |= (1 << c);
******}
****if (toupper(input) < 'A' || toupper(input) > 'Z') {
******found = 1;
******puts ("\nPlease guess a letter");
****}
****if (!found) {
******printf ("\nNope, no %c.\n", input);
******missed[nummissed++] = toupper(input);
****}
**} while (nummissed < 10 && guessed < ULONG_MAX);
**drawgallows (nummissed);
**if (nummissed == 10) printf ("\nYour man is hanged. My word was '%s'.\n", word);
**else printf ("%s\n\nGood work! You guessed my word!", word);
}

int play_again (void) {
**char yesno;

**printf ("\nWould you like to try another one? ");
**while (!isalpha (yesno = getche ()));
**if (tolower(yesno) != 'n') return 1;
**return 0;
}

int main (int argc, char *arg[]) {
FILE *fp;
char buffer[25];

**srand (time (NULL));
**if (--argc > 0) {
****dictnum = 0;
****fp = fopen (arg[1], "r");
****while (fgets (buffer, 25, fp)) {
******buffer[strlen(buffer) - 1] = 0;
******strcpy (dict[dictnum++], buffer);
****}
**}
**puts ("Hangman\n-------\n"
**"Try to guess the word and save yourself from the gallows.\n"
**"(To see the graphic tilt your head to the left.)\n");
**do {play ();} while (play_again ());
**puts ("Good-bye.\n");
**exit (0);
}

The word list included is actually pretty clever. If you don't peek at the list you'll often find it difficult to figure out the word. But if you get used to that list you can either type in a new one (up to 25 words) or you can load in a text file with your new word list with one word per line. To tell the program to do that just type the name of the txt file as a parameter of the program. In windows you can drag and drop the txt file into the compiled program's icon.

And NEXT?
  • Reverse (order a list of number by turning them around)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Pickup Piles (1000 games in one, set the rules and play)
  • Rotate (like those sliding block puzzles but that you rotate pieces)

DonCorleone 17-07-2006 09:24 PM

Woohoo, finally some motivation to get back into c/c++. If I may say this in my case at all. I donŽt believe that I ever came way further than the silly "Hello World" program :whistling:
Indeed I got a little bit deeper into C of course. But I never made programming to a great passion although I always liked to. Maybe I was to layzy and easygoing, maybe I was absorbed with other things. "Anytime I will try to program every day a little" I thought to myself.
And who knows: probably IŽll get my spurs in here. In any case I have to take my hat off to Guesst :kosta:

guesst 17-07-2006 11:19 PM

And if you write something, anything silly, dumb, creative, or awesome, post it here. That's what I started this project for.

I've been thinking I want to start up the Cymon's Games website in the next year or so. These games will be the first, but hopefully there will be enough people submitting that by the time they run out I'll have a ready flow of incomming programs. So who knows, DonCorleone, you may be the first, getting in on the ground floor of the future new thing on the Internet.

Actually, it's a little below the ground at the moment. And it may never be built up. But stay tuned.

guesst 18-07-2006 05:40 PM

Well, since no one voulenteered a game they'd like to see, it's my turn to pick. And I pick...
<div align="center">http://img.photobucket.com/albums/v6...mon/rotate.gifRotate</div>
Remember those little sliding puzzles where you'd win when all the pieces were in order? I loved those games. I was a wiz at them. This game has a similar concept. Once again I must kaotao to the BASIC program this game draws inspiration from.

A 4x4 block of letters have been scrambled. In order to unscramble them you rotate 4 at a time clockwise. Thus there are 9 overlapping areas of rotation centered between each block of 4 letters.
Code:

********A B C D

********E F G H

********I J M N

********K O L P

Which position to rotate (0 - 9) ?

To make control intuitive the number pad can be used and the rotations coorespond to the position. (See the in game instructions for more information)

A proper scrambling routine would take an unscrabled board and rotate pieces randomly. However, this game doesn't do that. This game's rotation routine just drops the pieces randomly on the board. Consequently it is possible to have an unwinnable situation if you limited yourself to just rotating pieces. So a bonus move has been added that will allow you to swap two pieces, like taking the stickers off the rubix cube. But to make it more game like the two pieces being swapped must be adjacent and you only get to do it once (you won't ever need more than that).

Code:

/* Rotate
 * by Joseph Larson
 * Inspired by a BASIC program of the same name by David H. Ahl
 * as found in 'More BASIC Programs' edited by David H. Ahl (c) 1978
 */

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

#define DRAW for(c = 0; c < 16; c++) printf((c % 4) ? "%c " : "\n\n\t%c ", b[c])


int main (void) {
**int c, d, temp, turn, special, done, b[16];
**char input;
**int x[4] = {0, 4, 5, 1};
**int t[9] = {8, 9, 10, 4, 5, 6, 0, 1, 2};
**long mask;
**
**srand (time (NULL));
**printf ("Rotate\n-------\n"
**"Order the puzzle board from top to botom, left to right, in alphabetical\n"
**"order by rotating four blocks at a time clockwise:\n"
**"\n\tA B C D\n\t 7 8 9\n\tE F G H\n\t 4 5 6\n\tI J K L\n\t 1 2 3\n\tM N O P\n"
**"\nIn the above illustration, the numbers betweent the letters are what you\n"
**"will input. So if you want to rotate the A, D, E, and F you would input 7\n"
**"as your move.\n\n"
**"You also have one special move that you may not need where you can switch\n"
**"the location of two adjacent blocks with each other. Input 0 (zero) as\n"
**"your move if you want to do this. If you try to do a second special move\n"
**"you will be asked if you want to quit.\n"
**"\nGood luck!\n\nPress ENTER to begin...");
**getchar ();
**do {
****mask = 0;
****for (c = 0; c < 16; c++) {
******while (1 << (b[c]=rand () % 16) & mask);
********mask |= 1 << b[c];
********b[c] += 'A';
****}
****done = 0;
****for (turn = special = 0; !done; turn++) {
******done = 0;
******putchar ('\t');
******DRAW;
******printf ("\n\nWhich position to rotate (0 - 9) ? ");
******while (!isdigit(input = getchar ()))
********if (isalnum(input))
**********printf("\nPlease choose a number between 0 and 9 ? ");
******input -= '0';
******if (input) {
********temp = b[t[--input]];
********for (c = 0; c < 3; c++)
**********b[t[input] + x[c]] = b[t[input] + x[c + 1]];
********b[t[input] + x[3]] = temp;
******} else {
********printf ("\nDo you want to quit? (y/n) ");
********while (!isalpha(input = getchar ()))
**********if (isalpha (input) && toupper (input) != 'Y'
**********&& toupper (input) != 'N') printf("\nY or N please ? ");
********if (toupper (input) == 'Y') done = 2;
********else if (!special) {
**********printf ("Which two letters do you want to switch? ");
**********do input = getchar ();
**********while (toupper (input) < 'A' || toupper (input) > 'P');
**********for (c = 0; b[c] != toupper(input); c++);
**********do input = getchar ();
**********while (toupper (input) < 'A' || toupper (input) > 'P');
**********for (d = 0; b[d] != toupper(input); d++);
**********if (d - c != 1 && d - c != -1 && d - c != 4 && d - c != -4) {
************puts ("Those two letters are not adjacent."); turn --;
**********} else {temp = b[c]; b[c] = b[d]; b[d] = temp; special = 1; turn++;}
********}
******}
******if (!done) for (c = done = 1; c < 16; c++)
********if (b[c - 1] > b[c]) done = 0;
****}
****if (!--done) {
******DRAW;
******printf ("\n\nYou ordered the board in %d moves!", turn);
******printf ("\nDo you want to play again? ");
****} else printf ("\nDo you want to try another? ");
****do input = getchar ();
****while (toupper (input) != 'Y' && toupper (input) != 'N');
****done = (toupper (input) == 'N');
**} while (!done);
**puts ("Goodbye!");
**exit (0);
}

Programming challenges for this game would include modularizing the code into functions or re-writing the scrambling alogrythm so to make the swapping function unnecessary. The later would be served well by the former.

Well, Cymon's original games is drawing near it's end. There are only 3 of the original 18 programs left. So what do you want to see next?
  • Reverse (order a list of number by turning them around)
  • Acey Deucy (a card game of highs, lows, and middles)
  • Pickup Piles (1000 games in one, set the rules and play)

Abi79 18-07-2006 06:02 PM

Quote:

Well, since no one voulenteered a game they'd like to see, it's my turn to pick. And I pick...[/b]
You didn't give us enough time. I was still trying to make a new man for Hangman. :P

And now I pick Pickup Piles.
*goes back to doing math exercises; I've got an important exam next year*

guesst 20-07-2006 01:02 AM

Pickup Piles

Before you is a pile and your opponent. You can only take a certian number of pieces, and you have to take at least a certian number. Maybe you want to be the one to take the last piece. Maybe you want to take everything but the last piece. So many things to keep track of, do you have the mind to win?

The frustrating thing about this game is the outcome is almost always predictable from the first move, if at least one player knows what they are doing. Thus the only way to actually win is to stack the deck in your favor.

Where this game gets fun is the endless variations it provides. Playing with the settings and getting good at this game is what it's about. When you get the hang of the game and figure out what the trick is take your skill to family and friends, maybe even play this it in the bar and make <strike>a few dollars</strike> some new friends.

Seeing how the computer plays a perfect game can teach you the trick. It is of course mathematical in nature, so bone up on your division skills.

The computer plays a perfect game but every so often, depending on the difficulty level, it will just make a shot in the dark random move that may or may not be the right move. This can also be part of the fun, catching the computer's mistakes.
Code:

/* Pickup Pile */
/* by Joseph Larson */
/* Inspired by a BASIC game Batnum by John Kemeny */
/* as found in 'BASIC Computer Games' edited by David H. Ahl © 1978 */

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

#define random(x) ((int) rand() / ((float)(RAND_MAX + 1) / x))

int num, max, min;
int takelast, comfirst;
int skill;

void intro (void) {
**printf ("\nPick Up Pile\n------\n"
**"Pick Up Pile is a game with many variations on the same idea.\n"
**"You and the computer each take turns picking up items from an\n"
**"imaginary pile of objects. Depending on the type of game you choose\n"
**"to play you will have different restrictions on how much you can\n"
**"pick up at a time, and whether you want to be the one to pick up the\n"
**"last piece or not.\n");
}

void random_setup (void) {
******num = random (25) + 10; max = random (5) + 3;
******do min = random (3) + 1; while ( max < min );
******takelast = random (2); comfirst = random (2);
******printf ("\n%d in pile, %s first, winner %s last piece.\n", num,
********(comfirst) ? "computer goes" : "you go",
********(takelast) ? "takes" : "leaves" );
******printf ("Take at least %d and at most %d per turn.\n", min, max);
}

void custom_setup(void) {
**int input;
**char yesno;

**printf ("\nFor any option input 0 to have the computer randomly select a value.");
**printf ("\nChoose the size of the pile (at least 3) ");
**do scanf("%d", &num);
**while (num < 3 && num != 0);
**if (num == 0) {
******num = random (30) + 10;
******printf("%d in pile.", num);
**}****
**printf ("\nWhat is the least that can be taken in a turn? ");
**do scanf("%d", &min);
**while (min < 0);
**if (min == 0) {
******min = random (5) + 1;
******printf("\n%d minimum taken per turn.", min);
**}****
**printf ("\nWhat is the most that can be taken in a turn (at least %d)? ", min + 1);
**do scanf("%d", &max);
**while (max < min && max != 0);
**if (max == 0) {
******max = random (5) + min + 2;
******printf("%d maximum taken per turn.", max);
**}****
**printf ("\nShould the winner take the last peace? (y/n/0)");
**do scanf("%c", &yesno);
**while (yesno != 'y' && yesno != 'Y' && yesno != 'n' && yesno != 'N' && yesno != '0');
**switch (yesno) {
****case 'y': case 'Y': takelast = 1; break;
****case 'n': case 'N': takelast = 0; break;
****case '0':
******takelast = random (2);
******printf("Winner %s last peace.", (takelast) ? "takes" : "leaves" );
**}****
**printf ("\nDo you want to go first? (y/n/0)");
**do scanf("%c", &yesno);
**while (yesno != 'y' && yesno != 'Y' && yesno != 'n' && yesno != 'N' && yesno != '0');
**switch (yesno) {
****case 'y': case'Y': comfirst = 0; break;
****case 'n': case 'N': comfirst = 1; break;
****case '0':****
******comfirst = random (2);
******printf("%s first.", (comfirst) ? "Computer goes" : "You go" );
**}**
}

int humanmove(void) {
**int input;

**printf ("\nHow many do you want to take (%d - %d) ",
****(min > num) ? num : min, (max > num) ? num : max);
**input = 0;
**do {
****if (input) printf ("\nInvalid move. Try again. ");
****scanf ("%d", &input);
****if (num <= min) input = (input == num) ? input : -1;
******else if (input < min || input > max || input > num) input = -1;
**}
**while (input < 0);
**num -= input;
**printf ("You leave %d", num);
**return ((num) ? 0 : (takelast)? 1 : 2);
}

int compmove (void) {
**int c;
**int move;
**
**c = min + max; move = num - !takelast;
**move = move % c;
**if (move < min || move > max || skill < random (5))
****move = random((max - min + 1)) + min;
**if (move > num) move = num;
**num -= move;
**printf ("\nComputer takes %d and leaves %d", move, num);
**return ((num) ? 0 : (takelast)? 2 : 1);
}

void playgame (void) {
**int input;
**int winner;

**printf ("\n(1) 23 Matches (23 in pile, take at most 3, last piece looses)\n");
**printf ("(2) Random\n");
**printf ("(3) Custom\n");
**printf ("\nChoose a game type: ");
**input = 0;
**do {
****if (input) printf ("\nChoose 1, 2, or 3 please. ");
****scanf ("%d", &input);
**} while (input < 1 || input > 3);
**switch (input) {
****case 1 :
******num = 23; max = 3; min = 1; takelast = 0; comfirst = 0;
******break;
****case 2 :
******random_setup();
******break;
****case 3 :
******custom_setup ();
**}
**printf ("\nOn a scale of 1 to 5, 5 being best,\n");
**printf ("how well do you want the computer to play? (1-5) ");
**scanf("%d", &skill);
**winner = 0;
**if (!comfirst) {
****printf ("\n%d in pile.", num);
****winner = humanmove ();
**}
**while (!winner) {
****winner = compmove ();
****if (!winner) winner = humanmove ();
**}
**if (winner == 2)
****printf ("\nComputer wins!");
**else printf ("\nYou win!");
}

int playagain (void) {
**char input;

**printf ("\nThat was fun. Would you like to play again? (y\\n) ");
**do input = getchar();
**while (!isalpha(input));
**if (input == 'y' || input == 'Y') return (1);
**else return(0);
}

int main (void) {
**srand (time(NULL));
**intro ();
**do playgame (); while (playagain ());
**exit (0);
}

Well, this is it, folks. The last two. One will be the people's choice, and the other will be the grand finale. No losers here. (Hmmm, I wonder if I have one more running around somewhere that I can make my big surprise grand finale? I don't think so. Maybe I finally need to write Wumpus.)
  • Reverse (order a list of number by turning them around)
  • Acey Ducey (A card game of highs, lows, and middles)

Shadikka 22-07-2006 02:36 PM

You're missing Minesweeper (at least) in the original list! :wink:

I did it with Python, somebody PM me if you want to see it. (o_O)

guesst 22-07-2006 08:36 PM

Feel free to post it here or make your own thread for it.

Minesweeper in a console ap? I guess it could be done, but the input process would be tedious at best.

Abi79 23-07-2006 08:28 AM

Acey Ducey, Acey Ducey! :D

guesst 24-07-2006 05:49 PM

<div align="center">Acey Deucy</div>
Silly game, fun game. This is a game that you could play yourself with a deck of cards and a pile of M&Ms. The game is played by dealing two cards and choosing whether the next card delt will be between the first two. If the third card is between the first two you win 15 points. If not you only lose 10. If you don't like your odds and decide to forfit looking at the third card you automaticly lose 5. But like most card games this game is cruel, for while it seems like the scoring is to your advantage you will more often than not find yourself in the hole and struggling to climb out.

Code:

/* Acey Duecy
 * by Joseph Larson
 * Inspired by a BASIC game by Bill Palmby
/* as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978 */

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

#define GAIN 15
#define LOSS 10
#define FORFIT 5
#define START 100
#define WIN 200
#define LOSE 0

int score = START;

void intro(void) {
**printf("\nAcey Duecy\n""----------\n"
**"Acey Ducey is played by having the computer deal out two cards. The\n"
**"player then decides on whether the next card chosen will be between the\n"
**"first two dealt, Aces high.\n\n"
**"You start out with %d points. If the third card is between the first to\n"
**"you gain %d points. If not you lose %d points. If you decide not to see\n"
**"the third card you'll automaticly lose %d points\n\n"
**"You win the game if you can get to %d points. But if your points drop\n"
**"below %d it is game over for you.\n\n",
** START, GAIN, LOSS, FORFIT, WIN, LOSE);
**srand(time(NULL));
}

void showcard(int c) {
**if (c <= 10) printf("%d", c);
**else switch (c) {
****case 11 : printf("Jack"); break;
****case 12 : printf("Queen"); break;
****case 13 : printf("King"); break;
****case 14 : printf("Ace");
**}
}

void playhand(void) {
**int card1,card2,card3;
**char yn[50];

**printf("Here are your first two cards:\n\n\t");
**card1 = rand() % 13 + 2;
**do {
****card2 = rand() % 13 + 2;
**} while (card1 == card2);
**showcard(card1);
**printf("\t");
**showcard(card2);
**printf("\n\n");
**if (abs(card1-card2) == 1) {
****printf("Oh, tough luck. There's no card between those two.\n");
****printf("\nSorry. You lose %d points", LOSS);
****score -= LOSS;
**} else {
****printf ("Do want to see the third card? ");
****do {
******printf ("(y\\n) ");
******scanf ("%s",yn);
****} while (tolower(yn[0]) != 'y' && tolower(yn[0]) != 'n');
****if (tolower(yn[0]) == 'y') {
******printf("\nHere is the third card\n\n\t");
******do card3 = rand() % 13 + 2;
******while ((card3 == card1) || (card3 == card2));
******showcard(card3);
******if (((card1 < card3) && (card3 < card2))
******|| ((card2 < card3) && (card3 < card1))) {
********printf("\n\nCongratulations. You win.\n");
********score += GAIN;
******} else {
********printf("\n\nSorry. You lose %d points", LOSS);
********score -= LOSS;
******}
****} else {
******printf ("Nothing ventured, nothing gained, %d points lost.\n", FORFIT);
******score-= FORFIT;
****}
**}
**printf("\nScore : %d.\n", score);
}

int playagain(void) {
**char input;

**if (score >= WIN || score <= LOSE) return 0;
**printf("\nDo you wish to continue? (y\\n) ");
**while (!isalnum (input = getchar()));
**if (tolower (input) != 'n') return 1;
**else return 0;
}

int main(void) {
**intro();
**do playhand();
**while (playagain());
**if (score >= WIN) printf ("Congratulation! You WIN!\n");
**if (score <= LOSE) printf ("Sorry, try again!\n");
**printf ("Thanks for playing!\n");
**exit (0);
}

In the original BASIC game it was a gambleing game. This was the first BASIC game I converted over (since it was the first in the book) and I originally had it that way, but a little while in I decided that I didn't want gambling or shooting games in Cymon's Games, so I retrofitted the program to be point based and not include the betting aspect. To tell the truth, aspects of the game were only just adjusted moments before posting, but rest assure the game was checked before posting.

That's how I found out that VC++ makes executables that are more than 10x the size of the same code compiled in DevC++. Yet another reason to not love M$.

This is not a true dealing alogrythm. Instead, a number between 1 and 13 is just picked out of the air, and as long as it's not the same as any of the numbers picked in that hand before it, it's valid and thrown into the game. Clever programers could adjust the game so that it's a more acurate dealing simulation that reshuffles after a certian number of hands or a certian number of cards are left in the deck.

Whether or not you choose to fix the dealing alogrythm, another simple fix would be to update showcard() to actually draw cards (with randomly chosen suits if the card dealing alogrythm isn't fixed).

Now there's only one left. I'll wait a few days and finish off Cymon's Games with Reverse. Strangely enough Reverse is another program I've reduced down to sig size, which is where this whole thread started. So that makes the beginning like the end. I didn't choose the order, but it seems fitting. Maybe I'll even change my sig in honor of this thread.

But it's not over. Now the programs are in your hands. Can you improve them? Can you make them prettier, more acurate, or more fun? If you do, post your improvements here!

(By the way, why hasn't anyone asked about the sparse illustrations that have accompanied these programs? Haven't yawl noticed them?)

Abi79 24-07-2006 06:52 PM

Quote:

But it's not over. Now the programs are in your hands. Can you improve them? Can you make them prettier, more acurate, or more fun? If you do, post your improvements here!
[/b]
Abi is working on the graphics for the other game, but Abi is lazy and doesn't have any imagination, so it might take Abi a while to finish that... :D

Quote:

(By the way, why hasn't anyone asked about the sparse illustrations that have accompanied these programs? Haven't yawl noticed them?)
[/b]
I have, but when I saw that you stopped adding them, I thought you didn't have more of those.

Quote:

So that makes the beginning like the end. I didn't choose the order, but it seems fitting. Maybe I'll even change my sig in honor of this thread.[/b]
Funny, eh? Oh, and does the program in your sig actually do something? It wouldn't work in C++ for DOS, without adding the proper libraries (you know what I mean; Stdio, Conio...) and doing that int thing, which I cannot translate into English. I'm curious, but does it work in other compilers? I guess not.

guesst 24-07-2006 08:37 PM

Yeah, it compiles. In DevC++, as long as you save it as a .c file it works just fine. It give you a few warnings because it says that you aren't including the necessary files, but it will find them and complie the program anyways. There are defaults in C that you don't NEED to #include, but it's good coding practice to. Stdio.h, conio.h, math.h, ctype.h... pretty much any of the basic ones. If it's a custom made header file or library you'll need to #include it, but the rest it's usually smart enough to find on it's own.

I'm pretty sure it works in VC++ as well the same way. That's been a stapel of the international obfscated C code contest for ages.

Did you ask about the illustrations? I'll have to go check.

guesst 25-07-2006 06:18 PM

<div align="center">Reverse</div>
This game is a simple solitare game. There were a few of these that I made, games that sort of weave a pattern down the screen as you solve them and in the are not all together unpleasant to look at. (Jumping Balls was another and Corral, which may appear here at a future date) Take a look at the overall astetic of the game as it progresses:
Code:

13 12**4**2**5**7 11**8**1 10**6**3 16**9 14 15 ? 3
13 12**4**2**5**7 11**8**1 10**6**3 16 15 14**9 ? 4
13 12**4**2**5**7 11**8**1 10**6**3**9 14 15 16 ? 16
16 15 14**9**3**6 10**1**8 11**7**5**2**4 12 13 ? 13
16 15 14 13 12**4**2**5**7 11**8**1 10**6**3**9 ? 5
16 15 14 13 12**4**2**5**7 11**8**9**3**6 10**1 ? 16
 1 10**6**3**9**8 11**7**5**2**4 12 13 14 15 16 ? 4
 1 10**6**3**9**8 11**7**5**2**4 12 16 15 14 13 ? 4
 1 10**6**3**9**8 11**7**5**2**4 12 13 14 15 16 ? 7
 1 10**6**3**9**8 11**7**5 16 15 14 13 12**4**2 ? 15
 1**2**4 12 13 14 15 16**5**7 11**8**9**3**6 10 ? 3
 1**2**4 12 13 14 15 16**5**7 11**8**9 10**6**3 ? 14
 1**2**3**6 10**9**8 11**7**5 16 15 14 13 12**4 ? 13
 1**2**3**4 12 13 14 15 16**5**7 11**8**9 10**6 ? 7
 1**2**3**4 12 13 14 15 16**6 10**9**8 11**7**5 ? 12
 1**2**3**4**5**7 11**8**9 10**6 16 15 14 13 12 ? 6
 1**2**3**4**5**7 11**8**9 10 12 13 14 15 16**6 ? 11
 1**2**3**4**5**6 16 15 14 13 12 10**9**8 11**7 ? 10
 1**2**3**4**5**6**7 11**8**9 10 12 13 14 15 16 ? 8
 1**2**3**4**5**6**7 11 16 15 14 13 12 10**9**8 ? 9
 1**2**3**4**5**6**7**8**9 10 12 13 14 15 16 11 ? 7
 1**2**3**4**5**6**7**8**9 11 16 15 14 13 12 10 ? 7
 1**2**3**4**5**6**7**8**9 10 12 13 14 15 16 11 ? 6
 1**2**3**4**5**6**7**8**9 10 11 16 15 14 13 12 ?

Okay, it ain't Georga O'Keffe, but it ain't bad for rows of numbers.

The object of this game is to order a list of numbers by reversing parts of the list. Because the game is at it's root so simple I made a sig version, which in honor of this posting is now my current sig. But I'll re-post it here incase my sig ever changes again:
Code:

main(){long l[16],c,d,t;srand(time(0));for(t=d=c=0;c<16;c++){while(1<<(l[c]=rand
()%16+1)&d);d|=1<<l[c];}for (;c>0;printf ("%2d ",l[--c]));do{printf("? ");scanf(
"%d",&d);if(d>1&&d<=16){for (c=0;c<(d/2);c++){l[c]^=l[d-c-1];l[d-c-1]^=l[c];l[c]
^=l[d-c-1];}t++;}for(c=16;c>0;printf("%2d ",l[--c]));for(c=0;c<15&&l[c]>l[c+1];c
++);}while(d&&c<15);if(d)printf("\nThank you for playing! Won in %d moves!",t);}

This game can solved in a minimum amout of moves if you mearly move the first number to the end of the line, then where it belongs, and proceed with the next. So it becomes possible to grade your performance, comparing how many moves it took against the "maximum" number moves it should take, which happens at the end of the game.

This game too is a BASIC adapatation.

Here's the full version:
Code:

/* Reverse
 * by Joseph Larson 2005
 * Inspired by a BASIC game of the same name by Peter Sessions
 * as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

#define X 16

int main (void) {
**int list[X], c, d, turns;
**long mask;
**char yn;
**
**srand (time(NULL));
**printf ("Reverse\n-------\n\n"
****"This is the game of Reverse. To win all you have to do is arrange a list\n"
****"of numbers (1 through %d) in numerical order left to right.\n"
****"To move, you input how many numbers from the right you want to reverse.\n"
****"You will no doubt like this game but, if you want to quit just input '0'\n"
****"as your move.\n\n", X);
**do {
****mask = 0;
****for (c = 0; c < X; c++) {
******while (1 << (list[c] = rand () % X + 1) & mask);
******mask |= 1 << list[c];
****}
****turns = 0;
****puts ("Here we go...\n");
****do {
******putchar ('\t');
******for (c = X; c > 0;) printf ("%2d ",list[--c]);
******printf ("\t? ");
******scanf ("%d", &d);
******if (d > 1 && d <= X) {
********for (c = 0; c < (d / 2); c++) {
**********list[c] ^= list[d - c - 1];
**********list[d - c - 1] ^= list[c];
**********list[c] ^= list[d - c - 1];
********}
********turns++;
******} else printf ("You can not reverse %d. Try again.\n", d);
******for (c = 0; c < X - 1 && list[c] > list [c + 1]; c++);
****} while (d && c < X - 1);
****if (d) {
******putchar ('\t');
******for (c = X; c > 0;) printf ("%2d ",list[--c]);
******printf ("\n\nYou ordered the list in %d moves.\n", turns);
******if (turns > X * 2 - 3)
********printf ("But it shouldn't have taken more than %d moves.\n" , X * 2 - 3);
******if (turns <= X)
********puts ("Wow, you are either extremely good, or extremely lucky.");
****}
****printf ("\nWould you like to try another? (y/n) : ");
****while (!isalpha (yn = getchar ()));
**} while (yn == 'y');
**puts ("Good bye for now then!");
**exit (0);
}

The method of reversing the list uses an abuse of the binary xor (^ in C) operator. Variable A is xor(^=)ed with variable B, changing variable A to be xor-ed version of both A and B, destroying the original value of A. Variable B is xor-ed with variable A, which has the effect of making varaible B now the original value of variable A. Variable A is now xor-ed with B, which is what A used to be, effectivly reversing the original xor command but ending with A now holding the original value of B. It's very clever, works every time, and negates a temporary holding variable to swap values.

Well, that's it. But this is not the end! Cymon's Games may slow down for a while, but there are games that either need to be rewritten or written in the first place. Plus, I need to install Borland and try making my programs work on that. Any questions you have, any improvements, this topic isn't closed. Do you have your own games you want to contribute? Feel free!

So what do you have to look forward to? Now, don't go requesting one or the other. I'll get to them when I get to them. But here's a few games:
Complete but didn't make the list (usually because they're pretty lame):
  • Hurkle - Your standard, "go north", "go south" hint game with added dimension up and down.
  • Nicomanchis - An ancient number guessing trick. Not much of a game.
  • Risk Dice - Ever get tired of the constant battling in Risk? Automate it!
Complete but buggy:
  • Camel - A race across the Gobi!
  • Corral - Catch a horse in a 1D corral
Games I'm still planning to write:
  • Wumpus - Saving this one for C++
  • Lava Lamp - An "animated" version of a Basic game found here.
  • Some sort of choose your own adventure maker/player
  • Some sort of picture decoder like this or this one, but perferably more robust.
But until those show up, thanks all for the interest. I hope some of you, some day, will be inspired to program a few yourself. You can do what I did, go check out the archives of 101 Basic Games, More Basic Games, Big Basic Games and see if they don't spark some inspiration in you.

Abi79 26-07-2006 08:58 AM

Hurkle, Hurkle, where is Hurkle? :D

guesst 28-07-2006 03:55 AM

<div align="center">Hurkle</div>
I mentioned that this isn't that great a game. Well, at least it's short.

So what is a Hurkle? Why do we hunt them and their cousins the mugwumps so? Why do these elusive prizes inspire such games of hide and seek? What does a hurkle or mugwump look like?

In this game the Hurkle has evolved from it's original incarnation and has gained the power of flight. Thus you must find the hurkle not just in x and y, but in z as well.

Code:

/* Hurkle hunt in 3D
 * by Joseph Larson 2005
 * Inspired by a BASIC program by Bob Albrecht
 * as found in 'BASIC Computer Games' edited by David H. Ahl (c) 1978
 */

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

#define MG 10
#define SIZE 10

int main (void) {
**int hx, hy, hz, x, y, z, c;
**char yesno;

**printf ("Hurkle Hunt in 3D\n\n"
**"A hurkle is a cute little creature, that in this game can fly. The hurkle\n"
**"is hiding in a region %d x %d x %d. After every guess your special hurkle\n"
**"locator will tell you which way you need to go. Keep in mind that 1,1,1 is\n"
**"the lowest northwest corner.\n", SIZE, SIZE, SIZE);
**printf ("Input your move by typing the x then y then z coordinate seperated\n"
**"by commas like \"1,2,3\"\n\n");
**srand (time (NULL));
**do {
****hx = rand () % 10 +1;
****hy = rand () % 10 +1;
****hz = rand () % 10 +1;
****printf ("The hurkle is ready.");
****for (c = 1; c <= MG && !(x == hx && y == hy && z == hz); c++) {
******printf ("\nWhere do you want to look? (X,Y,Z) : ");
******scanf ("%d %*c %d %*c %d", &x, &y, &z);
******printf ("The hurkle is ");
******if (y < hy) printf ("south");
******if (y > hy) printf ("north");
******if (x < hx) printf ("east");
******if (x > hx) printf ("west");
******if ((x != hx || y != hy) && z != hz) printf (" and ");
******if (z < hz) printf ("up");
******if (z > hz) printf ("down");
****}
****if (c <= MG) printf ("HERE!\nYou found the hurkle!\n\n");
****else printf ("\nThats %d trys and you didn't find the hurkle.\n"
******"The hurkle was hiding at %d, %d, %d.\n\n", MG, hx, hy, hz);
****printf ("Would you like to play again? (y/n) ");
****while (!isalpha (yesno = getchar()));
**} while (tolower (yesno) != 'n');
**printf ("Good bye for now!");
**exit (0);
}

Aside from being short, the reason this game was too lame for me to include on the list is that there is no modivation for the hurkle to hold still, yet it does, no modivation for us to not just spot the hurkle where it's at, but we don't, and any attempts to resolve these issues are contrived. The game is academic at best. It's not even that fun to play. Just choose a spot in the center, and then subdivide the distance remaining in whatever direction indicated. You'll win every time. The only surprise is if you find it on your second or third guess. Adding the third dimension was an attempt to complicate the game by way of making one more thing to keep track of, and in that it worked. But it didn't up the satisfaction of winning much for some reason. Not for me anyways.

However, there's hope that in your home the hurkle will find more love than he has found in mine.

The Bard 30-12-2006 12:04 PM

I see that this is a dead thread, and even though I don't have any intentions on reviving it, I read all of it, and I just had to post this thankyou message. You see, I am an wannabe programmer, and at school, I'm trying to qualify myself on the ACSL, but lately I've been losing enthusiasm for learning and practising, and this thread was exactly what I needed to give me a little bumb ahead. After reading thru all of these programs, even though I work in c++ I understood most, I'm going to get to work, and advance to the recursion problems I just can't get... Again, thank you...

haakjay 02-01-2007 08:58 PM

Thats really cool. My dad learned me Visual Basic and the BASIC dragon 64 uses. I have learned some Macromedia Actionscript to. And a bit GLBasic.

I'm 13 :P

nitro 21-02-2007 09:15 AM

These are some very nice examples. I didn't try them all, but the ones I tried all worked good.

I have only one piece of advice. If you write code with the purpose of sharing it, it is a good practice to add a lot of comment to the code, so others can read it easily. Especially when it is about complicated algorithms like the AI in some of the games.

I also wrote a version of battleship in VB and it is nice to see that you use the same algorithm.

Eagg 23-02-2007 02:40 AM

<div class='quotetop'>QUOTE(Nitro @ Feb 21 2007, 11:15 AM) [snapback]280318[/snapback]</div>
Quote:

These are some very nice examples. I didn't try them all, but the ones I tried all worked good.

I have only one piece of advice. If you write code with the purpose of sharing it, it is a good practice to add a lot of comment to the code, so others can read it easily. Especially when it is about complicated algorithms like the AI in some of the games.

I also wrote a version of battleship in VB and it is nice to see that you use the same algorithm.
[/b]
Tbh. I don't think comments would help making the code more readable, this code wasn't written to be easily understandable but to be compact and as confusing as possible :bleh: .
Basically anything considered bad practice at "good programming".

This is no rant on your stuff Guesst, I enjoy your pieces.
Code hacks are a bit like art... nobody claims that art needs to be userfriendly.

guesst 07-04-2007 03:14 AM

<div class='quotetop'>QUOTE(Eagg @ Feb 23 2007, 03:40 AM) [snapback]280573[/snapback]</div>
Quote:

<div class='quotetop'>QUOTE(Nitro @ Feb 21 2007, 11:15 AM) [snapback]280318[/snapback]
Quote:

These are some very nice examples. I didn't try them all, but the ones I tried all worked good.

I have only one piece of advice. If you write code with the purpose of sharing it, it is a good practice to add a lot of comment to the code, so others can read it easily. Especially when it is about complicated algorithms like the AI in some of the games.

I also wrote a version of battleship in VB and it is nice to see that you use the same algorithm.
[/b]
Tbh. I don't think comments would help making the code more readable, this code wasn't written to be easily understandable but to be compact and as confusing as possible :bleh: .
Basically anything considered bad practice at "good programming".

This is no rant on your stuff Guesst, I enjoy your pieces.
Code hacks are a bit like art... nobody claims that art needs to be userfriendly.
[/b][/quote]

I'm a bit slow. I was busy in February. I'm still busy, but avoiding doing something else I really should be doing.

Anyways, I took no offence on your comments Eagg, but Nitro has a point. My code isn't very well comented and it was designed to be shared. However, the reason for that was not well commented is that I had intended to release these to be typed in by the reader. I took my inspiration from old books of BASIC games that did the same thing (referenced several times in previous threads). As such I didn't want some would be programmer to get frustrated when he learned that 50% of what he typed was unnecessary when he finally learned what a comment was.

Ah, who am I kidding. I was never good at commenting anyways.

guesst 18-02-2008 09:55 PM

Cymon's Games has a new home on the web
 
It's unbelievable, but since this thread these programs have actually evolved into a full blown website. If you liked these programs please consider helping me promote my website.

You can see a teaser at: http://cymonsgames.retroremakes.com/

and a few clicks later you can see what it'll actually look like, or you can skip to it by going to http://cymonsgames.retroremakes.com/#main

Thanks all for your support!


The current time is 08:49 PM (GMT)

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