4
\$\begingroup\$

I am creating a KotH (King of the Hill) challenge for Programming Puzzles and Code Golf. Other site users will write programs that play Texplode (a version of this game on a square grid). The program works, but I don't think it's anywhere near perfect; I don't often publish C programs so I rarely get any critique on them.

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool move(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum, int movepos);
bool hascounters(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum);
void writegrid(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum, FILE *file);
bool readinput(FILE *file, int *movepos);
void printoutput(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize]);
int main(int argc, char *argv[]) {
 if (argc < 3) {
 printf("Texplode, by wizzwizz4.\n");
 printf("Based on Hexplode.\n");
 printf("The first argument is the board size.\n");
 printf("The second argument is the number of players.\n");
 printf("The 2n+1th argument is the nth player's input file.\n");
 printf("The 2n+2th argument is the nth player's output file.\n");
 printf("Human-readable ANSI art will be printed to STDOUT.\n");
 return 0;
 }
 int boardsize = atoi(argv[1]);
 int playercount = atoi(argv[2]);
 if (argc < (2 * playercount + 3)) {
 printf("You promised more players than you gave me.\n");
 }
 FILE *playerinv[playercount];
 FILE *playeroutv[playercount];
 for (int i = 0; i < playercount; i++) {
 playerinv[i] = fopen(argv[2 * i + 3], "r");
 playeroutv[i] = fopen(argv[2 * i + 4], "w");
 }
 int board[boardsize * boardsize];
 memset(board, 0, sizeof(board));
 int boardown[boardsize * boardsize];
 bool stillplaying[playercount];
 memset(stillplaying, true, sizeof(stillplaying));
 bool playoverride = true;
 int numplaying = playercount;
 while (1) {
 if (numplaying <= 1) {
 break;
 }
 for (int i = 0; i < playercount; i++) {
 if (stillplaying[i] || playoverride) {
 writegrid(boardsize, board, boardown, i, playeroutv[i]);
 int movepos = 0;
 if (!readinput(playerinv[i], &movepos)) {
 printf("Error! :-S\n");
 }
 move(boardsize, board, boardown, i, movepos);
 numplaying = 0;
 for (int j = 0; j < playercount; j++) {
 if (hascounters(boardsize, board, boardown, j)) {
 numplaying += 1;
 stillplaying[j] = true;
 } else {
 stillplaying[j] = false;
 }
 }
 }
 printoutput(boardsize, board, boardown);
 }
 playoverride = false;
 }
 printf("Game over.\n");
}
bool move(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum, int movepos) {
 if (movepos >= boardsize * boardsize) {
 return false;
 }
 if (board[movepos] == 0) {
 board[movepos] = 1;
 boardown[movepos] = playernum;
 return true;
 }
 if (boardown[movepos] == playernum) {
 board[movepos] += 1;
 /* Cascade */
 bool notdone = true;
 while (notdone) {
 notdone = false;
 for (int i = 0; i < boardsize * boardsize; i++) {
 int neighbourcount = 4;
 unsigned int neighbours = 0xf;
 if (i / boardsize == 0) {
 neighbourcount -= 1;
 neighbours &= ~0x1;
 }
 if (i / boardsize == boardsize - 1) {
 neighbourcount -= 1;
 neighbours &= ~0x2;
 }
 if (i % boardsize == 0) {
 neighbourcount -= 1;
 neighbours &= ~0x4;
 }
 if (i % boardsize == boardsize - 1) {
 neighbourcount -= 1;
 neighbours &= ~0x8;
 }
 if (board[i] >= neighbourcount) {
 notdone = true;
 board[i] -= neighbourcount;
 boardown[i] = playernum;
 if (neighbours & 0x1) {
 board[i - boardsize] += 1;
 boardown[i - boardsize] = playernum;
 }
 if (neighbours & 0x2) {
 board[i + boardsize] += 1;
 boardown[i + boardsize] = playernum;
 }
 if (neighbours & 0x4) {
 board[i - 1] += 1;
 boardown[i - 1] = playernum;
 }
 if (neighbours & 0x8) {
 board[i + 1] += 1;
 boardown[i + 1] = playernum;
 }
 }
 }
 }
 return true;
 }
 return false;
}
bool hascounters(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum) {
 for (int i = 0; i < boardsize * boardsize; i++) {
 if (board[i] && boardown[i] == playernum) {
 return true;
 }
 }
 return false;
}
void writegrid(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize], int playernum, FILE *file) {
 for (int i = 0; i < boardsize * boardsize; i++) {
 if (board[i] == 0) {
 putc('0', file);
 continue;
 }
 if (boardown[i] == playernum) {
 putc('3' + board[i], file);
 } else {
 putc('0' + board[i], file);
 }
 }
 putc(';', file);
 fflush(file);
}
bool readinput(FILE *file, int *movepos) {
 return (fscanf(file, "%d;", movepos) == 1); /* 1 "%d", one match. */
}
void printoutput(int boardsize, int board[boardsize * boardsize], int boardown[boardsize * boardsize]) {
 printf("\x1B[1;1H");
 for (int x = 0, i = 0; x < boardsize; x += 1) {
 for (; i < (x + 1) * boardsize; i++) {
 if (board[i]) {
 printf("\x1B[%dm%d", boardown[i] + 30, board[i]);
 } else {
 printf("\x1B[m ");
 }
 }
 printf("\n");
 }
}

I also have a basic UI program that I used for testing on Windows, where I don't have the luxury of using /dev/ttyn files. I know that this is not well-written, but I am providing it so that people have a way to test any changes that they make.

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
char * getline(void);
int main(int argc, char* argv[]) {
 /* "\\.\pipe\" pipename */
 HANDLE pipein = CreateNamedPipe(
 argv[1],
 PIPE_ACCESS_INBOUND,
 PIPE_TYPE_BYTE,
 PIPE_UNLIMITED_INSTANCES,
 0, /* Out buffer */
 256, /* In buffer */
 0, /* Default wait timeout */
 NULL
 );
 HANDLE pipeout = CreateNamedPipe(
 argv[2],
 PIPE_ACCESS_OUTBOUND,
 PIPE_TYPE_BYTE,
 PIPE_UNLIMITED_INSTANCES,
 256, /* Out buffer */
 0, /* In buffer */
 0, /* Default wait timeout */
 NULL
 );
 while (1) {
 if (_kbhit()) { /* Keyboard hit */
 char* input = getline();
 WriteFile(
 pipeout,
 input,
 strlen(input),
 NULL,
 NULL
 );
 free(input);
 }
 DWORD availbytes = 0;
 PeekNamedPipe(
 pipein,
 NULL,
 0,
 NULL,
 &availbytes,
 NULL
 );
 if (availbytes) {
 char byte;
 ReadFile(
 pipein,
 &byte,
 1,
 NULL,
 NULL
 );
 printf("%c", byte);
 }
 }
}
/* https://stackoverflow.com/a/314422/5223757 */
char * getline(void) {
 char * line = malloc(100), * linep = line;
 size_t lenmax = 100, len = lenmax;
 int c;
 if(line == NULL)
 return NULL;
 for(;;) {
 c = fgetc(stdin);
 if(c == EOF)
 break;
 if(--len == 0) {
 len = lenmax;
 char * linen = realloc(linep, lenmax *= 2);
 if(linen == NULL) {
 free(linep);
 return NULL;
 }
 line = linen + (line - linep);
 linep = linen;
 }
 if((*line++ = c) == '\n')
 break;
 }
 *line = '0円';
 return linep;
}
asked Feb 15, 2017 at 17:18
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You shouldn't assume that people here know what KotH stands for. \$\endgroup\$ Commented Jul 26, 2017 at 18:04

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.