Created
September 17, 2009 16:17
-
-
Save prophile/188557 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple Mastermind Game | |
// Copyright (c) Alistair Lynn <[email protected]>, 2008 | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <stdio.h> | |
// a single playing piece | |
typedef char MM_Piece; | |
// PRNG | |
static const int MM_PRNG_COEFFICIENT = 1103515245; | |
static const int MM_PRNG_CONSTANT = 12345; | |
static const int MM_PRNG_SHIFT = 0; | |
static const int MM_PRNG_MASK = 0x5FFFFFFF; | |
int MM_Random ( int* seed ) | |
{ | |
int firstSeed = *seed, output; | |
firstSeed *= MM_PRNG_COEFFICIENT; | |
firstSeed += MM_PRNG_CONSTANT; | |
output = firstSeed >> MM_PRNG_SHIFT; | |
output &= MM_PRNG_MASK; | |
*seed = firstSeed; | |
return output; | |
} | |
// a single board | |
typedef struct _MM_Board | |
{ | |
MM_Piece pieces[4]; | |
} MM_Board; | |
// a record of a game | |
typedef struct _MM_Game | |
{ | |
int nGames, seed; | |
MM_Board target; | |
MM_Piece maxPiece; | |
} MM_Game; | |
// checks if a piece is valid | |
bool MM_Piece_IsValid ( MM_Game* game, MM_Piece piece ) | |
{ | |
return piece >= 'A' && | |
piece <= game->maxPiece; | |
} | |
// generates a random piece | |
MM_Piece MM_Piece_Random ( MM_Game* game ) | |
{ | |
return (MM_Random(&(game->seed)) % (game->maxPiece - 'A' + 1)) + 'A'; | |
} | |
// compares two boards, giving numbers of matches and misplacements | |
void MM_Board_Compare ( MM_Board board1, MM_Board board2, int* matches, int* misplacements ) | |
{ | |
int i, j, nmatches = 0, nmisplacements = 0, usedMatches = 0; | |
for (i = 0; i < 4; i++) | |
{ | |
if (board1.pieces[i] == board2.pieces[i]) | |
{ | |
usedMatches |= (1 << i); | |
nmatches++; | |
} | |
} | |
for (i = 0; i < 4; i++) | |
{ | |
for (j = 0; j < 4; j++) | |
{ | |
if (j == i) continue; | |
if (!(usedMatches & (1 << j)) && (board1.pieces[i] == board2.pieces[j])) | |
{ | |
usedMatches |= (1 << j); | |
nmisplacements++; | |
} | |
} | |
} | |
*matches = nmatches; | |
*misplacements = nmisplacements; | |
} | |
// sets up a game | |
void MM_InitGame ( MM_Game* game, MM_Piece maxPiece, int seed, int nGames ) | |
{ | |
game->nGames = nGames; | |
game->seed = seed; | |
game->maxPiece = maxPiece; | |
game->target.pieces[0] = MM_Piece_Random(game); | |
game->target.pieces[1] = MM_Piece_Random(game); | |
game->target.pieces[2] = MM_Piece_Random(game); | |
game->target.pieces[3] = MM_Piece_Random(game); | |
} | |
// do a single turn, interacting with the user | |
void MM_TakeTurn ( MM_Game* game ) | |
{ | |
size_t len; | |
char inBuffer[6]; | |
int matches, misplacements, i; | |
MM_Board inBoard; | |
if (fgets(inBuffer, sizeof(inBuffer), stdin) == &(inBuffer[0])) | |
{ | |
len = strlen(inBuffer); | |
if (len != 4 && len != 5) | |
{ | |
printf("\twrong number of characters\n"); | |
return; | |
} | |
else if (len == 5) | |
{ | |
inBuffer[4] = 0; // strip newline | |
} | |
// check piece validity | |
for (i = 0; i < 4; i++) | |
{ | |
if (!MM_Piece_IsValid(game, inBuffer[i])) | |
{ | |
printf("\tbad piece: %c\n", inBuffer[i]); | |
return; | |
} | |
inBoard.pieces[i] = inBuffer[i]; | |
} | |
MM_Board_Compare(inBoard, game->target, &matches, &misplacements); | |
if (matches == 4) | |
{ | |
printf("\tSolved.\n"); | |
exit(0); | |
} | |
else | |
{ | |
printf("\tMatches: %d\n\tMisplacements: %d\n", matches, misplacements); | |
game->nGames--; | |
if (game->nGames == 0) | |
{ | |
printf("\tGame over. The board was:\n\t"); | |
fwrite(&(game->target), sizeof(MM_Board), 1, stdout); | |
putchar('\n'); | |
exit(0); | |
} | |
} | |
} | |
else | |
{ | |
printf("\tfgets() failed, try again.\n"); | |
} | |
} | |
int main ( int argc, char** argv ) | |
{ | |
MM_Game game; | |
MM_Piece maxPiece; | |
int seed, nGames; | |
if (argc != 4) | |
{ | |
printf("Usage: %s [max] [seed] [turns]\n", argv[0]); | |
return 1; | |
} | |
maxPiece = *argv[1]; | |
seed = atoi(argv[2]); | |
nGames = atoi(argv[3]); | |
MM_InitGame(&game, maxPiece, seed, nGames); | |
printf("Mastermind, v1.0.0\n"); | |
printf("Copyright (c) Alistair Lynn <[email protected]> 2009\n"); | |
while (1) | |
{ | |
MM_TakeTurn(&game); | |
} | |
// make the compiler happy | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment