Skip to content

Instantly share code, notes, and snippets.

@rexim
Created August 28, 2019 22:53
Show Gist options
  • Save rexim/8169cb021fb8d03e6ea26d5baa8a9e21 to your computer and use it in GitHub Desktop.
Save rexim/8169cb021fb8d03e6ea26d5baa8a9e21 to your computer and use it in GitHub Desktop.
// Copyright 2019 Alexey Kutepov <reximkut@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/////////////////////////////////////////
// Linux Build: $ gcc -o pairs pairs.c //
/////////////////////////////////////////
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <termios.h>
#include <unistd.h>
#define WIDTH 6
#define HEIGHT 6
char cards[HEIGHT][WIDTH];
int open[HEIGHT][WIDTH] = {0};
int srow = 0, scol = 0;
int quit = 0;
int onhold_index = -1;
int open_count = 0;
int points = (WIDTH * HEIGHT) / 2;
static inline
char *card_by_index(int index)
{
return &cards[index / WIDTH][index % WIDTH];
}
static inline
int *open_by_index(int index)
{
return &open[index / WIDTH][index % WIDTH];
}
static inline
void generate_cards(void)
{
assert((WIDTH * HEIGHT) % 2 == 0);
int cells[WIDTH * HEIGHT];
int cells_count = WIDTH * HEIGHT;
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
cells[i] = i;
}
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
int j = rand() % (WIDTH * HEIGHT);
int t = cells[i];
cells[i] = cells[j];
cells[j] = t;
}
while (cells_count > 0) {
char c = (rand() % ('z' - 'a')) + 'a';
*card_by_index(cells[--cells_count]) = c;
*card_by_index(cells[--cells_count]) = c;
}
}
static struct termios orig_stdin;
static struct termios orig_stdout;
void disable_raw_mode(void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_stdin);
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &orig_stdout);
}
void enable_raw_mode(void)
{
struct termios raw = orig_stdin;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
static inline
void render(void)
{
printf("Points: %d\n", points);
for (int row = 0; row < HEIGHT; ++row) {
for (int col = 0; col < WIDTH; ++col) {
if (srow == row && scol == col) {
putc('[', stdout);
putc(open[row][col] ? cards[row][col] : '*', stdout);
putc(']', stdout);
} else {
putc(' ', stdout);
putc(open[row][col] ? cards[row][col] : '*', stdout);
putc(' ', stdout);
}
}
putc('\n', stdout);
}
}
int main()
{
srand(time(0));
tcgetattr(STDIN_FILENO, &orig_stdin);
tcgetattr(STDOUT_FILENO, &orig_stdout);
enable_raw_mode();
atexit(disable_raw_mode);
generate_cards();
printf("---------------------------\n");
printf("Controls: W, A, S, D, Space\n");
printf("---------------------------\n");
render();
while (!quit) {
char c;
read(STDIN_FILENO, &c, 1);
switch (c) {
case 'w': if (srow > 0) srow--; render(); break;
case 's': if (srow < HEIGHT - 1) srow++; render(); break;
case 'a': if (scol > 0) scol--; render(); break;
case 'd': if (scol < WIDTH - 1) scol++; render(); break;
case 'q': quit = 1; break;
case ' ': {
if (!open[srow][scol]) {
if (onhold_index < 0) {
open[srow][scol] = 1;
onhold_index = srow * WIDTH + scol;
render();
} else if(cards[srow][scol] == *card_by_index(onhold_index)) {
// Successful attempt
open[srow][scol] = 1;
onhold_index = -1;
open_count += 2;
points += 5;
render();
if (open_count >= WIDTH * HEIGHT) {
printf("WON with %d Points\n", points);
quit = 1;
}
} else {
// Failed attempt
open[srow][scol] = 1;
render();
open[srow][scol] = 0;
*open_by_index(onhold_index) = 0;
onhold_index = -1;
points--;
if (points <= 0) {
printf("LOST!\n");
quit = 1;
}
}
}
} break;
default: render();
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment