Skip to content

Instantly share code, notes, and snippets.

@InfiniteCoder01
Created September 15, 2025 16:47
Show Gist options
  • Save InfiniteCoder01/f82903a3ac92b7c09eb42203faf594d1 to your computer and use it in GitHub Desktop.
Save InfiniteCoder01/f82903a3ac92b7c09eb42203faf594d1 to your computer and use it in GitHub Desktop.
Challenge #3 from @nigelwithrow, this time converting a flwaed Rust version of Rock-Paper-Scissors to C
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define FAT_PTR_IMPL(T) \
typedef struct { \
void *ptr; \
T *meta; \
} FatPtr ## T;
typedef enum {
Rock,
Paper,
Scissors,
} Move;
typedef struct RockPaperScissorsVtable {
Move (*play)(void *self);
} RockPaperScissorsVtable;
FAT_PTR_IMPL(RockPaperScissorsVtable);
// Returns whether player 1 won
bool battle(FatPtrRockPaperScissorsVtable p1, FatPtrRockPaperScissorsVtable p2) {
const Move move1 = p1.meta->play(p1.ptr);
const Move move2 = p2.meta->play(p2.ptr);
if ((move1 == Rock && move2 == Scissors)
|| (move1 == Scissors && move2 == Paper)
|| (move1 == Paper && move2 == Rock)) {
return true;
} else {
return false;
}
}
typedef struct {} RandomPlayer;
Move random_player_play(RandomPlayer *self) {
const int r = rand() % 3;
printf("> %d\n", r);
if (r == 0) return Rock;
else if (r == 1) return Paper;
else if (r == 2) return Scissors;
puts("unreachable executed!");
exit(-1);
}
RockPaperScissorsVtable RANDOM_PLAYER_VTABLE = {
.play = (void *)random_player_play,
};
int main() {
srand(128);
RandomPlayer p1inner;
RandomPlayer p2inner;
FatPtrRockPaperScissorsVtable p1 = {
.ptr = &p1inner,
.meta = &RANDOM_PLAYER_VTABLE,
};
FatPtrRockPaperScissorsVtable p2 = {
.ptr = &p2inner,
.meta = &RANDOM_PLAYER_VTABLE,
};
puts("Best of 3!");
int p1_won = 0;
for (int i = 0; i < 3; i++) {
if (battle(p1, p2)) p1_won++;
}
if (p1_won >= 2) puts("P1 wins!");
else puts("P2 wins!");
return 0;
}
use rand::rng;
enum Move {
Rock,
Paper,
Scissors,
}
trait RockPaperScissors {
fn play(&mut self) -> Move;
}
// Returns whether player 1 won
fn battle(p1: &mut dyn RockPaperScissors, p2: &mut dyn RockPaperScissors) -> bool {
use Move::*;
match (p1.play(), p2.play()) {
(Rock, Scissors) | (Scissors, Paper) | (Paper, Rock) => true,
_ => false,
}
}
struct RandomPlayer;
impl RockPaperScissors for RandomPlayer {
fn play(&mut self) -> Move {
use rand::Rng as _;
let mut rng = rng();
match rng.random::<u8>() % 3 {
0 => Move::Rock,
1 => Move::Paper,
2 => Move::Scissors,
_ => unreachable!(),
}
}
}
fn main() {
let mut p1 = RandomPlayer;
let mut p2 = RandomPlayer;
println!("Best of 3!");
let p1_won = (0..3).fold(0, |p1_won, _| {
if battle(&mut p1, &mut p2) {
p1_won + 1
} else {
p1_won
}
});
if p1_won >= 2 {
println!("P1 wins!");
} else {
println!("P2 wins!");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment