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.

Revisions

  1. InfiniteCoder01 created this gist Sep 15, 2025.
    74 changes: 74 additions & 0 deletions challenge.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    #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;
    }


    52 changes: 52 additions & 0 deletions challenge.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    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!");
    }
    }